ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Remotion 效果系统深度解析:基于官方 add-effect 技能文档,完整掌握为 @remotion/effects 新增特效的全流程

Remotion 效果系统深度解析:基于官方 add-effect 技能文档,完整掌握为 @remotion/effects 新增特效的全流程 Remotion 效果系统深度解析基于官方 add-effect 技能文档完整掌握为 remotion/effects 新增特效的全流程【免费下载链接】remotion Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion本篇基于 Remotion 官方仓库内的 Agent 技能文档 .agents/skills/add-effect/SKILL.md系统讲解向remotion/effects包新增一个 WebGL2 特效的完整工程流程从命名规范、createEffect()实现模板、package.json子路径导出注册到测试、文档、交互式 Demo 与目录卡片渲染。读完本文你可以独立产出一个可被 Studio 可视化编辑、可通过remotion/effects/effect-name子路径导入、并带有官方文档页面与预览图的标准特效。1. 选择合适的效果形态与命名规范新增特效的第一步是确定实现形态。技能文档给出以下决策准则优先选择 WebGL2 后端。只有当 WebGL 无法表达该效果时才考虑 2D Canvas 后端简单特效放在单文件packages/effects/src/effect-name.ts需要多份着色器、运行时辅助模块或多个文件时使用目录packages/effects/src/effect-name/并在顶层放一个 re-export 文件严格遵循包内既有的命名约定文件名 / 子路径kebab-case如chromatic-aberration函数名camelCase如chromaticAberration参数类型PascalCase如ChromaticAberrationParams效果类型字符串remotion/kebab-case-name。当前packages/effects/src/目录同时存在两类形态可直接对照参考brightness.ts、halftone.ts等单文件特效以及blur/、chromatic-aberration/、wave/等目录型特效目录内含-runtime.ts等运行时辅助文件。2. 实现效果createEffect 完整模板技能文档给出的实现要点如下每一项在仓库源码中均有对应实例从remotion导入SequenceSchema类型与Internals命名空间通过const {createEffect, createWebGL2ContextError} Internals;解构出核心 API默认值以const常量定义用satisfies SequenceSchema定义 schema——schema 中声明的字段会直接出现在 Studio 的可视化编辑面板中导出参数类型export type XxxParams用resolve()辅助函数把可选参数解析为完整参数参数校验复用两个共享模块validate-effect-param.ts对象/数字/颜色/布尔断言color-utils.ts区间校验、颜色解析等获取 WebGL2 上下文失败时抛出createWebGL2ContextError(effect name effect)将documentationLink设为https://www.remotion.dev/docs/effects/slug所有解析后的参数都必须包含进calculateKey()保证缓存 key 随参数变化。以下是技能文档提供的标准模板createMyEffectState()代表着色器编译、程序链接、全屏四边形与纹理搭建等一次性 setup 逻辑可参考halftone.ts等既有实现import type {SequenceSchema} from remotion; import {Internals} from remotion; import {assertOptionalFiniteNumber, validateUnitInterval} from ./color-utils.js; import {assertEffectParamsObject} from ./validate-effect-param.js; const {createEffect, createWebGL2ContextError} Internals; const DEFAULT_AMOUNT 1 as const; const myEffectSchema { amount: { type: number, min: 0, max: 1, step: 0.01, default: DEFAULT_AMOUNT, description: Amount, }, } as const satisfies SequenceSchema; export type MyEffectParams { readonly amount?: number; }; type MyEffectResolved { amount: number; }; const resolve (p: MyEffectParams): MyEffectResolved ({ amount: p.amount ?? DEFAULT_AMOUNT, }); const validateMyEffectParams (params: MyEffectParams): void { assertEffectParamsObject(params, My effect); assertOptionalFiniteNumber(params.amount, amount); validateUnitInterval(params.amount ?? DEFAULT_AMOUNT, amount); }; type MyEffectState { readonly gl: WebGL2RenderingContext; readonly program: WebGLProgram; readonly vao: WebGLVertexArrayObject; readonly vbo: WebGLBuffer; readonly texture: WebGLTexture; readonly uSource: WebGLUniformLocation | null; readonly uAmount: WebGLUniformLocation | null; }; const VERTEX_SHADER /* glsl */ #version 300 es in vec2 aPos; in vec2 aUv; out vec2 vUv; void main() { vUv aUv; gl_Position vec4(aPos, 0.0, 1.0); } ; const FRAGMENT_SHADER /* glsl */ #version 300 es precision highp float; in vec2 vUv; out vec4 fragColor; uniform sampler2D uSource; uniform float uAmount; void main() { vec4 color texture(uSource, vUv); fragColor vec4(color.rgb * uAmount, color.a); } ; // Follow existing helpers in halftone.ts or a runtime file for shader // compilation, program linking, fullscreen-quad setup, and texture setup. export const myEffect createEffectMyEffectParams, MyEffectState({ type: remotion/my-effect, label: My Effect, documentationLink: https://www.remotion.dev/docs/effects/my-effect, backend: webgl2, calculateKey: (params) { const r resolve(params); return my-effect-${r.amount}; }, setup: (target) { const gl target.getContext(webgl2, { premultipliedAlpha: true, alpha: true, preserveDrawingBuffer: true, }); if (!gl) { throw createWebGL2ContextError(my effect effect); } gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); return createMyEffectState(gl, VERTEX_SHADER, FRAGMENT_SHADER); }, apply: ({source, width, height, params, state, flipSourceY}) { const r resolve(params); state.gl.viewport(0, 0, width, height); state.gl.bindFramebuffer(state.gl.FRAMEBUFFER, null); state.gl.activeTexture(state.gl.TEXTURE0); state.gl.bindTexture(state.gl.TEXTURE_2D, state.texture); state.gl.pixelStorei(state.gl.UNPACK_FLIP_Y_WEBGL, flipSourceY); state.gl.texImage2D( state.gl.TEXTURE_2D, 0, state.gl.RGBA, state.gl.RGBA, state.gl.UNSIGNED_BYTE, source as TexImageSource, ); state.gl.useProgram(state.program); if (state.uSource) state.gl.uniform1i(state.uSource, 0); if (state.uAmount) state.gl.uniform1f(state.uAmount, r.amount); state.gl.bindVertexArray(state.vao); state.gl.drawArrays(state.gl.TRIANGLE_STRIP, 0, 4); }, cleanup: ({gl, program, vao, vbo, texture}) { gl.deleteTexture(texture); gl.deleteBuffer(vbo); gl.deleteProgram(program); gl.deleteVertexArray(vao); }, schema: myEffectSchema, validateParams: validateMyEffectParams, });2.1 createEffect 各字段的职责拆解结合 halftone.ts 这个真实的 WebGL2 特效实现可以逐一印证模板中各字段的作用字段职责在 halftone.ts 中的体现type特效的唯一标识字符串dev.remotion.effects.halftone注意该特效早于remotion/前缀约定新特效应按技能文档使用remotion/kebab-case-namelabelStudio 中展示的名称halftone()documentationLink文档页链接Studio 中可点击跳转https://www.remotion.dev/docs/effects/halftonebackend声明渲染后端webgl2calculateKey依据解析后参数生成缓存 key任一参数变化都会产生新 key拼入shape、dotSize、rotation等全部 10 个解析参数setup(target)一次性初始化获取 WebGL2 上下文、编译着色器、链接 program、搭建全屏四边形 VAO/VBO、创建纹理、记录 uniform 位置compileShader→linkProgram→ 创建vao/vbo/texture→getUniformLocationapply({source, width, height, params, state, flipSourceY})每帧绘制绑定纹理并上传source、设置 uniform、drawArrays绘制全屏四边形见 halftone.tscleanup释放 GPU 资源texture、vbo、program、vaogl.deleteBuffer/deleteProgram/deleteVertexArray/deleteTextureschema声明 Studio 可视化编辑字段halftoneSchema含number、enum、color、嵌套 variants 等类型validateParams运行前参数校验抛出带明确子串的TypeErrorvalidateHalftoneParams含改名检测、跨字段约束setup阶段获取上下文的三个关键选项premultipliedAlpha: true、alpha: true、preserveDrawingBuffer: true与随后的gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true)是保证透明区域正确合成的基础apply中的flipSourceY由渲染管线传入控制源纹理上传时是否垂直翻转两个位置都要正确处理否则会出现画面上下颠倒。2.2 校验辅助函数与错误信息validate-effect-param.ts 提供assertEffectParamsObject非对象抛TypeError并附上实际值的 JSON 表示、assertRequiredFiniteNumber、assertOptionalColor、assertOptionalBoolean等断言color-utils.ts 则提供assertOptionalFiniteNumber、validateUnitInterval0–1 区间、validateNonNegative、validateSignedUnitInterval-1 到 1以及基于 1×1 Canvas 的parseColorRgba颜色解析。值得注意的是halftone.ts中的校验还包含跨字段约束colorMode: source时不允许设置dotColor与参数改名提示color has been renamed to dotColor新特效在参数演进时应保持同样的错误信息风格——这直接服务于第 4 步测试中对错误子串的断言。3. 注册包入口点实现文件写好后必须更新两处构建配置packages/effects/bundle.ts把新的src/effect-name.ts加入effectEntrypoints数组。该脚本用 Bun 的buildAPI 将每个入口打包为dist/esm/name.mjsremotion、react等被声明为 external漏加这一步ESM 子路径产物根本不会被构建packages/effects/package.json添加exports[./effect-name]同时给出types、module、import三个条件添加对应的typesVersions条目供 TypeScript 解析子路径类型。子路径导入remotion/effects/my-effect完全依赖这两个声明缺一个都会导致运行时或类型解析失败。若采用目录型实现需在顶层文件 re-export例如export {myEffect, type MyEffectParams} from ./my-effect/index.js;仓库中 chromatic-aberration.ts 对chromatic-aberration/目录、wave.ts 对wave/目录的 re-export 即为现成范例。4. 添加测试测试统一维护在 packages/effects/src/test/effect-params.test.ts。为每个新特效补充以下内容导入新特效函数加入「documentation link」统一测试断言effect().definition.documentationLink精确等于https://www.remotion.dev/docs/effects/slug当所有字段都是可选时测试零参数调用默认值路径存在必填参数时测试缺省必填参数会报错测试非法取值并断言错误信息的精确子串如must be a finite number、must be 1测试有意义的参数会产生不同的effectKey——这正是第 2 步calculateKey()必须纳入全部解析参数的原因。运行方式cd packages/effects bun test src/test bunx turbo make --filterremotion/effects其中bun test src/test对应 package.json 中的test: bun test src/test脚本bunx turbo make触发tsgo类型检查 bundle.tsESM 构建make: tsgo bun --env-file../.env.bundle bundle.ts。5. 编写文档页在packages/docs/docs/effects/effect-name.mdx新建文档页参照既有特效页结构Frontmatter 必须包含slug、title、sidebar_label、crumb: remotion/effectsimage:字段只允许在运行bun render-cards.ts生成卡片后再添加H1 格式为# effectName()AvailableFrom v... /紧跟一句_Part of the remotion/effects package._简短描述 EffectsDemo typeeffects-effect-name /交互 Demo提供带titleMyComp.tsx的 twoslash 示例每个选项单独用###小标题说明可选参数名带?后缀增加disabled?小节与 See also 小节。同步更新三个索引位置packages/docs/sidebars.ts——按字母序插入effects/effect-namepackages/docs/docs/effects/table-of-contents.tsx——在正确分类下添加卡片packages/docs/src/data/articles.ts——必须通过运行卡片生成器更新禁止手工编辑。文档措辞细节可配合仓库内writing-docs技能位于 .agents/skills/writing-docs/SKILL.md。6. 添加交互式文档 Demo创建packages/docs/components/effects/effects-effect-name-preview.tsx复用其他特效相同的预览源EFFECTS_PREVIEW_IMAGE_SRCimport {myEffect} from remotion/effects/my-effect; import React from react; import {CanvasImage} from remotion; import {EFFECTS_PREVIEW_IMAGE_SRC} from ./effects-preview-image; export const EffectsMyEffectPreview: React.FC{ readonly amount: number; } ({amount}) { return ( CanvasImage src{EFFECTS_PREVIEW_IMAGE_SRC} width{1280} height{720} fitcover effects{[myEffect({amount})]} / ); };要点文档特效预览必须使用fitcover让共享预览图填满 16:9 画布避免出现透明边条。随后在packages/docs/components/effects-demos/registry.ts中注册导入预览组件并导入真实特效 schema或从effect().definition.schema读取添加id: effects-effect-name的注册条目只有当 schema 中某必填字段的default为undefined时才提供initialValues。Demo 细节可参考docs-demo技能.agents/skills/docs-demo/SKILL.md。7. 渲染目录TOC预览合成目录卡片必须来自packages/docs中真实存在的 Remotion 合成不允许手写图片资源预览图一律渲染为 PNG。第一步在 packages/docs/src/remotion/Root.tsx 的effect-previews目录下追加一个StillStill ideffects-my-effect-preview component{EffectsMyEffectPreview} width{1280} height{720} defaultProps{{ amount: 1, }} /width/height必须与预览组件的CanvasImage保持一致预览组件若使用共享文档预览图CanvasImage保持fitcover——把 16:9 的预览渲染进不同宽高比的合成会在生成的 TOC 图中留下黑边。第二步在packages/docs下执行bunx remotion still src/remotion/entry.ts effects-my-effect-preview static/img/effects-my-effect-preview.png --overwrite --image-formatpng第三步同时提交两样东西Root.tsx中的合成条目以及渲染出的packages/docs/static/img/effects-my-effect-preview.png。8. 生成文档卡片cd packages/docs bun render-cards.ts提交生成的packages/docs/static/generated/articles-docs-effects-effect-name.png并给文档页补上新产生的image:frontmatter 行。注意render-cards.ts是「机会式」生成器可能顺带产出本次改动之外的缺失卡片——与本变更无关的图片必须删除保持提交聚焦。9. 同步 Remotion Agent 技能保持面向 Agent 的 Remotion 技能与新特效同步仅在新特效改变了通用使用机制、导入约定、安装指引或自定义特效建议时才更新 packages/skills/skills/remotion-markup/effects.md。该文件不应重复完整特效清单——官方文档的目录table of contents才是规范列表避免两处清单漂移。10. 格式化、构建与提交前检查cd packages/effects bunx oxfmt src --write cd ../.. bun run build bun run formatting说明若改动触及 docs 源码bun run formatting会覆盖packages/docs/src纯 MDX 文档页的修改不要跑格式化器避免污染文档。提交前最后执行git diff --check git status --short常见陷阱清单技能文档末尾的陷阱列表是整篇流程的风险摘要逐条对照仓库事实不要遗漏package.json的exports与typesVersionsremotion/effects/my-effect这类子路径导入完全依赖它们不要遗漏bundle.ts漏掉后 ESM 子路径dist/esm/*.mjs不会被构建不要在packages/docs/src/remotion留下临时渲染入口Root.tsx只保留正式合成不要用手写 SVG 充当 TOC 预览图卡片必须来自真实Still渲染的 PNG除非特效有意改变透明通道否则保持 alphacanvas 存储的是预乘 alphapremultiplied alpha像素计算时需知晓这一点WebGL 颜色计算的预乘问题在做亮度或阈值计算前通常要先对采样到的 RGB 做反预乘unpremultiply如halftone.ts中的vec3 rgb alpha 0.001 ? texColor.rgb / alpha : vec3(0.0);输出时再重新预乘。结语一次变更涉及的文件全景汇总上述步骤一次「新增特效」变更至少触碰以下仓库位置可作为自查清单类别路径特效实现packages/effects/src/effect-name.ts或目录 顶层 re-export构建注册packages/effects/bundle.ts、packages/effects/package.json参数测试packages/effects/src/test/effect-params.test.ts文档packages/docs/docs/effects/effect-name.mdx、packages/docs/sidebars.ts、packages/docs/docs/effects/table-of-contents.tsx、packages/docs/src/data/articles.ts生成器产出交互 Demopackages/docs/components/effects/effects-effect-name-preview.tsx、packages/docs/components/effects-demos/registry.ts预览合成与图片packages/docs/src/remotion/Root.tsx、packages/docs/static/img/、packages/docs/static/generated/Agent 技能packages/skills/skills/remotion-markup/effects.md仅在机制性变化时这套流程的精髓在于「单一事实来源」schema 同时驱动 Studio 可视化编辑、文档与 Demo 的注册calculateKey同时驱动渲染缓存documentationLink同时驱动 Studio 跳转与文档链接测试——只要每一步都严格对齐既有实现新特效就能以最小成本无缝融入整个 Remotion 生态。【免费下载链接】remotion Make videos programmatically with React项目地址: https://gitcode.com/GitHub_Trending/re/remotion创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表