🎁 Get the FREE AI Skills Starter GuideSubscribe →
BytesAgainBytesAgain
🦀 ClawHub

auto-remotion

by @16miku

从已有录屏/产品演示视频生成官网宣传片的工作流。 当用户提到以下场景时触发: - "把录屏转成宣传片"、"用录屏做产品视频" - "把演示视频做成官网介绍" - "Remotion 切片"、"视频分镜" - "产品宣传视频生成"、"screen recording to promo video" - "多个视频合...

Versionv1.0.0
Downloads287
TERMINAL
clawhub install auto-remotion

📖 About This Skill


name: auto-remotion description: | 从已有录屏/产品演示视频生成官网宣传片的工作流。

当用户提到以下场景时触发: - "把录屏转成宣传片"、"用录屏做产品视频" - "把演示视频做成官网介绍" - "Remotion 切片"、"视频分镜" - "产品宣传视频生成"、"screen recording to promo video" - "多个视频合并成宣传片"、"产品视频剪辑" - 用户想用 Remotion 把长视频切成短片段做宣传片

本技能覆盖从原始录屏素材到完整 Remotion 宣传片的完整流程: 环境准备 → 目标确认 → 素材识别(人工/自动)→ 分镜策划 → 结构化规格 → Remotion 实现 → 字幕轨 → 中文配音(edge-tts)→ BGM → 渲染出片

每个阶段都有具体检查清单、常见问题和决策框架。

本 skill 不适用的情况(见"不适用场景"章节): - 从技术文档/幻灯片生成视频(无源视频素材) - 需要 AI 生成视频画面本身(仅处理已有素材的剪辑组合)


云端链接

  • GitHub: https://github.com/16Miku/auto-remotion
  • ClawHub: https://clawhub.ai/16miku/auto-remotion

  • 核心理念

    这条工作流的核心不是"让 AI 替代人工",而是:

    > 把人工判断和自动化工具各自放在最合适的位置。 > 人工判断哪些画面有价值,工具负责把价值组合成视频。

    执行顺序很重要: 1. 先锁定素材区间 2. 再锁定段落结构 3. 再锁定总时间线 4. 最后才叠加字幕、配音、BGM、包装

    违反这个顺序,会导致大量返工。


    快速启动(3 分钟理解全局)

    对于 AI Agent / 自动化脚本,使用非交互式创建

    npx create-video --yes --blank --no-tailwind my-video
    

    对于手动操作

    npx create-video@latest
    

    交互式选择 Blank 模板

    典型对话节奏

  • 用户:录屏 20 分钟 → 宣传片 60 秒
  • 执行顺序:先看素材定结构,再动手写代码

  • 阶段零:环境准备

    0.1 创建 Remotion 项目

    交互式创建(手动操作时):

    npx create-video@latest
    

    选择模板:Blank(空白模板)

    非交互式创建(AI Agent / 脚本时):

    npx create-video --yes --blank --no-tailwind my-video
    

    可用模板 flags: | Flag | 模板 | |------|------| | --blank | 空白画布(推荐) | | --hello-world | Hello World 动画 | | --javascript | 纯 JavaScript 版 | | --recorder | 录屏工具 | | --still | 静态图片模板 | | --overlay | 视频叠加层 | | --audiogram | 音频可视化 | | --prompt-to-video | AI 文字生视频 |

    重要 flags

  • --yes / -y:跳过所有交互提示(AI Agent 必须)
  • --no-tailwind:不安装 TailwindCSS
  • --tmp:在临时目录创建
  • 0.2 安装依赖

    cd my-video
    npm install
    

    0.3 启动开发服务器

    npm run dev
    

    同时在另一个终端启动 Claude Code:

    cd my-video
    claude
    

    0.4 安装 ClawHub CLI(可选)

    如需发布技能或管理注册表认证,可安装独立 clawhub CLI:

    npm i -g clawhub
    

    pnpm add -g clawhub

    0.5 安装 remotion-video-toolkit skill(可选)

    本 skill(auto-remotion)与 remotion-video-toolkit 是不同的 skill:

  • auto-remotion:本 skill,专注"从录屏到宣传片"的完整剪辑工作流,覆盖需求确认→素材识别→Remotion 实现→配音字幕→BGM→渲染出片
  • remotion-video-toolkit:ClawHub 上的另一个 skill,29 条规则,专注 Remotion API 使用、动画特效、渲染管道等技术细节
  • 两者可互补使用。如果需要 remotion-video-toolkit 辅助开发:

    方式一:使用 openclaw 原生命令(推荐)

    openclaw skills install remotion-video-toolkit
    

    方式二:使用 clawhub CLI

    npx clawhub@latest install remotion-video-toolkit --force
    

    该 skill 包含 29 条规则,覆盖:

  • 动画、时序、渲染(CLI/Node.js/Lambda/Cloud Run)
  • 字幕、3D、图表、文字特效、转场、媒体处理
  • 注意npx skills add remotion-dev/skills 是安装 remotion-best-practices skill 的方式,与 remotion-video-toolkit 是完全不同的 skill。

    方式三:从本地路径安装(安装 remotion-best-practices

    npx skills add remotion-dev/skills
    

    安装时选择:

  • Agent 类型:Claude Code 或当前使用的 Agent
  • 安装范围:全局安装(global)
  • 注意npx skills add remotion-dev/skills 安装的是 remotion-best-practices,与 auto-remotion 和 remotion-video-toolkit 都是完全不同的 skill。

    0.6 环境检查清单

    | 检查项 | 命令 | 预期结果 | |--------|------|---------| | Node.js | node --version | ≥ 18 | | npm | npm --version | ≥ 9 | | Remotion CLI | npx remotion --version | 显示版本号 | | 开发服务器 | npm run dev | localhost:3000 可访问 |


    阶段一:明确目标与约束

    在动手之前,先对齐:

    1. 输入是什么:录屏、直播录屏、剪辑素材包,还是多段演示视频? 2. 输出是什么:官网宣传片、产品介绍、销售演示,还是社媒短视频? 3. 时长目标:严格 60 秒、可浮动到 70 秒,还是优先完整表达? 4. 核心价值:产品能力、用户体验、结果展示,还是品牌感? 5. 哪些后置:字幕、配音、BGM 放到第二阶段?

    如果约束不先说清楚,后面会在"要不要保留完整结果""能不能接受更长"这类问题上反复拉扯。


    阶段二:建立结构化中间产物

    不要直接写代码。先建立以下文件:

    2.1 剪辑执行稿(.md

    按 Segment 分解,每段包含:

  • 目标 / 画面描述 / 屏幕文案 / 旁白 / Remotion 对接建议
  • 这是讨论和审阅的基础
  • 2.2 分镜表(storyboard.json

    {
      "compositionId": "MyPromoV1",
      "fps": 30,
      "durationInFrames": 1800,
      "canvas": "1920x1080",
      "segments": [
        {
          "segmentId": "SegmentIntro",
          "segmentIndex": 0,
          "startFrame": 0,
          "durationFrames": 150,
          "goal": "片头引入,30字内概括价值",
          "text": { "eyebrow": "", "title": "", "body": "" },
          "narration": "产品名,让 AI 完成真实任务。",
          "clip": null,
          "overlay": "top-bar"
        }
      ]
    }
    

    2.3 编辑规格(edit-spec.json

    帧级时间线,包含真实素材区间和速度:

    单视频源

    {
      "compositionId": "MyPromoV1",
      "fps": 30,
      "durationInFrames": 1800,
      "sourceVideo": { "path": "./public/source.mp4" },
      "segments": [
        {
          "segmentId": "SegmentIntro",
          "startFrame": 0,
          "durationFrames": 150,
          "clips": []
        }
      ]
    }
    

    多视频源clips[] 中指定 src):

    {
      "compositionId": "MyPromoV1",
      "fps": 30,
      "durationInFrames": 1800,
      "sourceVideos": [
        { "id": "video-a", "path": "./public/product-demo.mp4" },
        { "id": "video-b", "path": "./public/user-review.mp4" }
      ],
      "segments": [
        {
          "segmentId": "SegmentIntro",
          "startFrame": 0,
          "durationFrames": 150,
          "clips": [
            { "src": "video-a", "start": 10.5, "end": 15.2, "playbackRate": 1 }
          ]
        },
        {
          "segmentId": "SegmentFeature",
          "startFrame": 150,
          "durationFrames": 300,
          "clips": [
            { "src": "video-b", "start": 0, "end": 8.5, "playbackRate": 1 }
          ]
        }
      ]
    }
    


    阶段三:识别母视频时间点

    这一步是整个链路的核心桥梁。

    不要跳过。即使有 AI 视频理解能力,在 MVP 阶段人工识别仍然最快。

    推荐做法: 1. 用户(或你引导用户)观看原视频,给出粗粒度内容分区 2. 在粗粒度分区中细化为可剪辑时间点 3. 区分"价值展示片段"和"过程等待片段" 4. 用结构化表格记录所有时间点

    关键原则

  • 对话类片段要确保"输入→发送→回复出现"的因果链完整
  • 长任务演示不要只靠整体快进,要拆成"发起/执行/结果/成果展示"多个叙事节点
  • 真实切片时间点以为单位记录(4:16 而不是 4.267

  • 阶段三补充:自动视频理解(可选)

    > 本章节借鉴 video-use 项目。如需实现 Agent 自动化剪辑,建议启用本流程。

    3.1 核心思想:让 LLM 读视频,而不是看视频

    传统方式(纯人工):

    人工看视频 10-20min → 人工标记时间点 → 人工判断价值 → 人工规划分镜
    

    自动化方式(基于转录):

    视频 → 转录文本(1-2min)→ LLM 阅读转录(10s)→ 自动识别有价值片段 → 自动生成分镜
    

    关键洞察:用转录文本把视频"文本化",LLM 擅长处理文本,就能自动化原本需要人工判断的决策。


    3.2 两段式视频理解架构

    | 层 | 方式 | 代价 | |----|------|------| | 音频转录层 | ElevenLabs Scribe 词级时间戳 | ~12KB/小时视频 | | 视觉合成层 | 按需生成 filmstrip + waveform PNG | 仅在决策点生成 |

    LLM 从不直接处理视频帧,而是读取"文本化的视频信息"。这样把 ~45M tokens(逐帧 dump)压缩到 ~12KB + 少量 PNG。


    3.3 转录管道

    依赖安装

    pip install -e video-use/helpers
    

    或独立安装

    pip install requests librosa matplotlib pillow numpy

    核心脚本

    | 脚本 | 功能 | |------|------| | transcribe.py | ElevenLabs Scribe 转录,输出词级时间戳 JSON | | pack_transcripts.py | 把 JSON 打包成 takes_packed.md(phrase 级) | | timeline_view.py | 按需生成 filmstrip + waveform PNG |

    转录命令

    # 单文件
    python helpers/transcribe.py 

    批量(4 并行)

    python helpers/transcribe_batch.py

    打包成 takes_packed.md

    python helpers/pack_transcripts.py --edit-dir


    3.4 takes_packed.md 格式

    这是 LLM 阅读视频内容的主要 artifact。格式示例:

    # Packed transcripts

    C0103 (duration: 43.0s, 8 phrases)

    [002.52-005.36] S0 Ninety percent of what a web agent does is completely wasted. [006.08-006.74] S0 We fixed this.

    生成规则

  • 按静音 ≥ 0.5s 或说话人切换切分 phrase
  • 每个 phrase 带有 [start-end] 时间戳
  • 包含音频事件标记:(laughs)(sighs)(applause)

  • 3.5 LLM 自动分镜

    给定 takes_packed.md,LLM 可直接生成分镜:

    [
      {"source": "C0103", "start": 2.42, "end": 6.85,
       "beat": "HOOK", "quote": "Ninety percent...", "reason": "Cleanest delivery"},
      {"source": "C0103", "start": 14.30, "end": 28.90,
       "beat": "SOLUTION", "quote": "We fixed this", "reason": "Only take without false start"}
    ]
    

    Editor sub-agent prompt 要点

  • 输入:takes_packed.md + 用户上下文 + 目标时长
  • 输出:JSON 数组,带 source/start/end/beat/quote/reason
  • 规则:切点必须在词边界、30-200ms pad、优先 ≥400ms 静音

  • 3.6 timeline_view:按需可视化

    在 LLM 判断模糊时,生成可视化确认:

    python helpers/timeline_view.py 

    输出:filmstrip + waveform + word labels PNG

    使用原则:只在决策点使用,不是全程扫描工具。


    阶段四:Remotion 骨架搭建

    4.1 项目结构约定

    remotion-app/
    ├── public/              ← 所有源素材放这里(视频、音频、图片)
    │   ├── source.mp4      ← 源视频(单视频场景)
    │   ├── video-a.mp4     ← 多视频场景:来源视频 A
    │   ├── video-b.mp4     ← 多视频场景:来源视频 B
    │   ├── voiceover.mp3   ← 配音
    │   └── bgm.mp3         ← BGM
    ├── src/
    │   ├── Composition.tsx  ← 主 composition(含所有 Segment 组件)
    │   └── Root.tsx        ← composition 注册
    └── package.json
    

    所有源素材必须放 public/,用 staticFile("文件名") 引用。

    4.2 视频切片工具函数

    单视频源(默认):

    type ClipSpec = {
      trimBeforeFrames: number;
      trimAfterFrames: number;
      playbackRate: number;
    };

    const clip = ( startSeconds: number, endSeconds: number, playbackRate = 1 ): ClipSpec => ({ trimBeforeFrames: Math.round(startSeconds * 30), trimAfterFrames: Math.round(endSeconds * 30), playbackRate, });

    // 高倍速片段务必 muted

    多视频源:传入视频文件标识符:

    type ClipSpec = {
      trimBeforeFrames: number;
      trimAfterFrames: number;
      playbackRate: number;
      src?: string;  // ← 可选:指定来源视频(默认为主视频)
    };

    // 不同 Segment 使用不同来源视频 const clipA = clip(10, 15, 1); // 来自 source-a.mp4 const clipB = clip(5, 12, 1, "source-b.mp4"); // 来自 source-b.mp4

    4.3 Sequence 嵌套与时长管理

    父子 Sequence 时长是关键原则

    > 外层 Sequence 的 durationInFrames 必须足够容纳所有子片段的总时长。

    如果子片段时长总和超过父级,会发生截断(子片段被砍掉尾部)。

    // 正确示例
      {/* ← 必须 ≥ 所有子片段之和 */}
      
    
    

    4.4 TypeScript 踩坑清单

    | 错误写法 | 正确写法 | |---------|---------| | | | | | | | playbackRate={0} | 不支持,改为纯色背景 | | import JSON from "./data.json" | 内联为 TypeScript 常量数组 |


    阶段五:字幕轨接入

    5.1 字幕数据结构

    字幕 cue 用左闭右开区间 [startFrame, endFrame)

    type SubtitleCue = {
      cueId: string;
      segmentId: string;
      startFrame: number;  // 包含
      endFrame: number;    // 不包含
      text: string;
    };

    const activeCue = subtitleCues.find( (cue) => frame >= cue.startFrame && frame < cue.endFrame );

    5.2 渲染组件

    const SubtitleTrack: React.FC = () => {
      const frame = useCurrentFrame();
      const activeCue = subtitleCues.find(
        (cue) => frame >= cue.startFrame && frame < cue.endFrame
      );
      if (!activeCue) return null;

    return (

    {activeCue.text}
    ); };


    阶段六:中文配音(edge-tts)

    6.1 流程

    voiceover-script.json(结构化旁白文本)
        → edge-tts 生成各段 MP3
        → ffmpeg 合并(每段后加静音填充对齐目标帧时长)
        → 放入 public/
        → 

    6.2 静音填充是关键

    不能假设配音自然时长等于目标帧时长。

    edge-tts 按自然语速生成,每句实际时长和目标帧时长必然有偏差(可能 ±0.5-2 秒)。直接合并会导致:

  • 配音总时长比视频短
  • 后半段 Segment 没有配音
  • 字幕和配音完全错位
  • 正确做法:每段配音后测量实际时长,用 anullsrc 生成静音填充到目标秒数:

    # 生成静音
    ffmpeg -f lavfi -i anullsrc=r=24000:cl=mono -t 2.5 -q:a 9 silence.mp3
    

    合并

    ffmpeg -f concat -safe 0 -i concat_list.txt -acodec libmp3lame output.mp3

    6.3 配音生成脚本示例

    实际项目中使用的 Python 脚本结构(generate_voiceover_v2.py):

    import asyncio
    import edge_tts
    import subprocess
    import json
    import os

    FFMPEG = "A:/study/AI/LLM/browser-use-cli-test/remotion-app/node_modules/@remux/compositor-win32-x64-msvc/ffmpeg.exe"

    async def generate_segment(seg: dict, output_dir: str): """生成单段配音 + 静音填充""" target_sec = seg["targetSec"] output_path = os.path.join(output_dir, f"vo_{seg['id']}.mp3")

    # 1. 生成配音 communicate = edge_tts.Communicate(seg["text"], "zh-CN-XiaoxiaoNeural") seg_path = os.path.join(output_dir, f"seg_{seg['id']}.mp3") await communicate.save(seg_path)

    # 2. 测量实际时长 probe = subprocess.run([ FFMPEG, "-i", seg_path, "-hide_banner" ], capture_output=True, text=True) # 解析输出获取时长,或使用 ffprobe 精确测量 actual_dur = measure_duration(seg_path) # 自定义函数

    # 3. 计算静音填充 silence_sec = target_sec - actual_dur if silence_sec > 0.05: silence_path = os.path.join(output_dir, f"silence_{seg['id']}.mp3") subprocess.run([ FFMPEG, "-f", "lavfi", "-i", f"anullsrc=r=24000:cl=mono", "-t", str(silence_sec), "-q:a", "9", silence_path ]) # 4. 合并配音 + 静音 concat_file = os.path.join(output_dir, f"concat_{seg['id']}.txt") with open(concat_file, "w") as f: f.write(f"file '{seg_path}'\n") f.write(f"file '{silence_path}'\n") subprocess.run([ FFMPEG, "-f", "concat", "-safe", "0", "-i", concat_file, "-acodec", "libmp3lame", output_path ]) else: os.rename(seg_path, output_path)

    async def main(): with open("voiceover-script.json") as f: segments = json.load(f) for seg in segments: await generate_segment(seg, "output_dir") # 最后用 ffmpeg concat 合并所有段 subprocess.run([FFMPEG, "-f", "concat", "-safe", "0", "-i", "final_concat.txt", "-acodec", "libmp3lame", "remotion-app/public/voiceover.mp3"])

    asyncio.run(main())

    6.4 中文语音选项

    | Voice | 特点 | 适用场景 | |-------|---|---| | zh-CN-XiaoxiaoNeural | 专业女声,清晰流畅 | 产品介绍(本次选用) | | zh-CN-YunxiNeural | 年轻男声,有点活泼 | 科技产品演示 | | zh-CN-YunjianNeural | 阳刚男声 | 强技术感,专业工具 |

    6.5 配音与时间线匹配策略

    微调顺序: 1. 先调文字内容长度 2. 次调语速(rate 参数) 3. 最后才改 Segment 时长(因为改时长会影响所有子片段基准)


    阶段七:BGM 接入

    7.1 来源

    Pixabay Music(商用免费,无需署名) 关键词:"light technology""corporate tech"

    7.2 动态音量接入

    7.3 音量原则

    配音清晰度优先:BGM 必须作为背景,不能盖过人声。

  • 配音密集段:0.15-0.25
  • 无配音段(片头/片尾):0.3-0.5
  • 本次实践最终值:峰值 0.4,正常段 0.2

  • 阶段八:渲染出片

    8.1 渲染命令

    npx remotion render MyCompositionV1 --fps=30 --frames=0-{N-1} --output="output.mp4"
    

    帧范围是左闭右开 0, N),总帧数 N 意味着最后一帧是 N-1。

    8.2 磁盘空间要求

    Remotion 渲染需要:

  • webpack bundle 缓存(~400MB)
  • Chromium headless(~100MB)
  • 临时帧文件
  • 渲染前确保 C 盘有 5-10GB 可用空间%TEMP% 中的 remotion-webpack-bundle-* 可提前清理。

    8.3 Studio 预览 ≠ 最终渲染

  • Studio 预览受浏览器解码限制,高倍速(>10x)可能卡顿
  • 最终渲染用 ffmpeg 硬解码,流畅得多
  • Studio 只做节奏判断,最终质量以渲染出片为准

  • 关键设计决策框架

    Hard Rules(生产正确性铁律)

    > 以下规则来自 [video-use 项目的生产验证。违反这些规则会导致静默失败或输出损坏,务必遵守。

    | # | 规则 | 说明 | |---|------|------| | 1 | 字幕 LAST | 字幕必须在滤镜链最后应用,否则叠加层会遮住字幕 | | 2 | 分段提取 → 无损 concat | 有叠加时用 -c copy concat,避免双重编码 | | 3 | 30ms 音频淡入淡出 | 每个分段边界加 afade=t=in:st=0:d=0.03,afade=t=out:st={dur-0.03}:d=0.03,否则有 pop 音 | | 4 | 叠加层 PTS 偏移 | 用 setpts=PTS-STARTPTS+T/TB 偏移叠加层帧 0,否则动画窗口显示错误帧 | | 5 | Master SRT 用输出时间线偏移 | output_time = word.start - segment_start + segment_offset,否则 concat 后字幕错位 | | 6 | 不在词中间切割 | 所有切边必须对齐到转录词的边界 | | 7 | 切割边缘留 pad | 工作窗口 30-200ms,Scribe 时间戳漂移 50-100ms,pad 吸收漂移 | | 8 | 词级 verbatim ASR | 不用 SRT/phrase 模式(丢失亚秒级间隙数据) | | 9 | 按源缓存转录 | 不重新转录,除非源文件本身变了 | | 10 | 多动画并行子代理 | 用 Agent 工具并行生成,总耗时 ≈ 最慢那个 | | 11 | 执行前确认策略 | 在用户确认计划前不进行任何切割 | | 12 | 输出到 /edit/ | 不在 skill 目录写任何输出 |

    Option A vs Option B 决策

    当某个 Segment 时长问题无法通过调速解决时:

    | 选项 | 做法 | 适用条件 | |-----|------|---------| | Option A(压缩) | 强制缩短时长,裁剪内容 | 甲方严格卡时长 | | Option B(接受更长) | 让叙事完整,接受更长总时长 | 优先内容完整 |

    决策原则:官网宣传片的核心目标是"把产品价值讲清楚",而非"严格卡 N 秒"。压缩到不完整,反而失去意义。

    冻结帧实现

    不要用 Img src="video.mp4#t=1.0"(依赖 HTTP 服务器)或 playbackRate={0}(不支持)。改用纯色背景或预渲染图片。


    不适用场景(重要)

    本 skill 不适用于以下场景,识别到时请明确告知用户:

    | 场景 | 原因 | 建议 | |-----|------|------| | 技术文档/幻灯片 → 视频 | 本 skill 需要已有录屏视频作为输入,没有源视频无法切片 | 先用 Screen Studio/OBS/Keynote 录制幻灯片演示,再走本工作流 | | AI 生成视频画面 | 本 skill 仅处理已有素材的剪辑组合,不生成新画面 | 需要 Text-to-Video / AI 视频生成工具(如 Sora、Pika) | | 从零构建动画视频 | 本 skill 假设有现成素材,只是剪辑重组 | 需要纯动画/图形动画工具(如 After Effects、Canva) |

    回归路径:如果用户有技术文档但没有录屏 → 引导用户先录制幻灯片演示(Screen Studio/OBS)→ 再回到本工作流。


    决策树

    用户描述任务时,按以下顺序判断:

    用户描述任务
        │
        ├─ 有录屏/产品演示视频(.mp4)?
        │       ├─ 是 → 走完整工作流(本 skill)
        │       └─ 否 → 跳转到"不适用场景"处理
        │
        └─ 目标是官网宣传片/产品介绍?
                ├─ 是 → 本 skill 适用
                └─ 否 → 说明本 skill 专注场景,建议其他方案
    


    项目结构总览

    project/
    ├── work/                          ← 工作流与资产层
    │   └── projects/{project-id}/
    │       ├── edit-script.md          ← 剪辑执行稿
    │       ├── storyboard.json         ← 分镜表
    │       ├── edit-spec.json         ← 编辑规格(帧级时间线,支持多视频源)
    │       ├── subtitle-track.json      ← 字幕时间轴
    │       ├── voiceover-script.json   ← 配音脚本
    │       ├── generate_voiceover.py  ← 配音生成脚本
    │       ├── process_bgm.py         ← BGM 混合脚本
    │       ├── takes_packed.md         ← 自动视频理解:打包转录文本
    │       ├── transcripts/             ← 自动视频理解:原始转录 JSON
    │       │   └── .json
    │       ├── timeline_view/          ← 自动视频理解:可视化确认 PNG
    │       └── animations/            ← 动画叠加层(如有)
    └── remotion-app/                  ← Remotion 实现层
        ├── public/
        │   ├── source.mp4            ← 源视频(单视频场景)
        │   ├── video-a.mp4            ← 多视频场景:来源视频 A
        │   ├── video-b.mp4            ← 多视频场景:来源视频 B
        │   ├── voiceover.mp3         ← 配音
        │   └── bgm.mp3               ← BGM
        └── src/
            ├── Composition.tsx        ← 主 composition
            └── Root.tsx              ← 注册
    


    常见问题速查

    | 问题 | 原因 | 解决方案 | |-----|------|---------| | 子片段被截断 | 父级 Sequence durationInFrames 不够 | 检查并扩大父级时长 | | Studio 预览高倍速片段卡顿 | 浏览器解码压力大 | 设置 muted: true,Studio 只判断节奏 | | 配音和字幕错位 | 配音总时长 ≠ 视频时长 | 每段后加静音填充对齐 | | 渲染报 ENOSPC | C 盘空间不足 | 清理 %TEMP%,确保 5-10GB 可用 | | 渲染时 FreezeFrame 报错 | #t=playbackRate=0 不支持 | 改用纯色背景 | | 渲染报错 "frame range 0-N is not inbetween..." | 帧范围写错(应为左闭右开) | 改为 --frames=0-{N-1} | | 某 Segment 时长不够 | 素材本身内容少 + 加速已到极限 | Option B:接受更长;或压缩其他 Segment | | BGM 盖过人声 | BGM 音量过大 | 降低 BGM 音量至 0.15-0.25,配音段更低 | | edge-tts 生成失败 | 网络或认证问题 | 检查 edge-tts --list-voices 是否正常 |