Communitygithub.com

MuhammadToffaha/视频剪辑

将说话人头视频转化为高留存率的短视频(Reels/TikTok/Shorts),支持双语字幕、动态图形、信息图、品牌Logo以及多语言配音和唇形同步。

视频剪辑 是什么?

该技能是一个全自主的短视频编辑器,专为AI代理(如Claude Code)设计,能够将说话人头视频自动剪辑成适合Reels、TikTok或Shorts的高质量短视频。它使用ffmpeg、无头Chromium、GSAP和sherpa-onnx Whisper完全在离线沙箱中运行,无需网络依赖。编辑模式包括:自动转录(支持阿拉伯语/英语等)、单词级同步字幕、动画关键词标注、信息图/图表/UI卡片、缩放镜头、品牌Logo放置、音效和音量标准化。它还能处理带有Logo的图像,从中提取品牌色并进行统一视觉设计。该技能还提供高级配音模式,可将视频翻译成另一种语言,使用原说话人的音色(通过YourTTS零样本克隆)生成新语音,并使用Wav2Lip + GFPGAN实现唇形同步。所有处理都在云端完成,通常60秒视频需要15-25分钟。其核心设计原则是保留原说话人和语意,不发明新内容,每个图形元素都精确地与对应的口语词汇同步触发。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MuhammadToffaha/Video-editing/tree/HEAD/.claude/skills/short-form-video-editor

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

自动驾驶 - 当用户输入 /short-form-video-editor 时的操作流程

用户上传视频(以及可选的Logo图片)并输入命令。完整执行整个任务,无需提问;仅在遇到真正阻塞的问题时停止(未找到视频、没有ffmpeg)。命令后的额外文本视为风格/品牌说明,请加以应用。

  1. 查找输入:会话上传中最新的视频文件(ls -t /root/.claude/uploads/*/*.{mp4,mov,webm} 或消息中给出的路径);Logo = 附件中的图片(如有)(无Logo则跳过水印/片头/片尾Logo,使用干净的无文本片尾)。语言 = 使用 asr_chunks.py ... auto 自动检测。
  2. 定位工具包:本技能文件夹(包含此SKILL.md的目录)下有 template/。在新的项目文件夹中工作:当该仓库在会话中时,在Video-editing仓库克隆内创建为 projects/<slug>-<YYYYMMDD>/,否则在暂存区中。执行 cp -r template/. <project>/。
  3. 检查/安装依赖(一次性操作):ffmpeg、Node + Playwright Chromium(位于 /opt/pw-browsers,切勿运行 playwright install)、pip install numpy pillow sherpa-onnx、scripts/fetch_asr_model.sh。HuggingFace无网络连接;GitHub releases、npm、PyPI可正常工作。
  4. 端到端运行下面的工作流,自行做出设计决策(品牌色从Logo提取;否则使用珊瑚/青绿科技调色板;场景从 reference/scene-patterns.md 中选择,以匹配实际说的内容)。
  5. 交付:使用 SendUserFile 发送mp4(展示渲染结果),然后提供简短摘要:规格、添加了哪些图形、需要人工听校的低置信度转录片段、原始分辨率说明、“音频未经验听”。将项目目录(不含 work/)和最终mp4保存到仓库中,并推送到会话指定的分支(若无则推送到 main)。除非被要求,切勿创建PR。
  6. 预计60秒视频耗时约15-25分钟(转录约3分钟,渲染约4分钟,编码约2分钟)。开始时用一句话告知用户,然后静默工作直到完成。

配音模式 - 翻译 + 新语音 + 唇形同步(在Glow片段上测试过一次:阿拉伯语 -> 英语)

当用户希望视频以另一种语言出现“并且嘴唇跟台词同步”时使用。

  1. 脚本:像编辑模式一样转录并验证原文,然后自行撰写翻译并保存为 data/phrases.<lang>.json = [[win_start, win_end, "text with *key words and DISPLAY|spoken overrides (NBSP inside multi-word tokens)"], ...]。保留原始短语窗口,以便摄像机/图形节拍保持不变;可以合并相邻窗口。每个窗口大约设定2.5-3个词/秒(英语)——浓缩而非赶时间;保留原意,不添加新主张。口语覆盖示例:*COSRX|Cosrex、Axis-Y|Axis\u00a0Y。
  2. 模型:运行 scripts/fetch_dub_models.sh(以及用于验证的 fetch_asr_model.sh)。
  3. 语音(默认 = 克隆说话人的声音):构建 work/ref.wav = 4-5个干净的无音停顿片段(共约15秒)的说话人原始语音(16k单声道,拼接而成)。执行 python3 -I scripts/tts_clone.py data/phrases.en.json work/ref.wav 8 <total_seconds> -> 生成 work/voice_en.wav + 包含实际语音片段的 data/transcript.source.json。YourTTS(coqui,由 fetch_dub_models.sh 下载)进行零样本音色克隆;该脚本每行生成N个候选,保留Whisper回读与脚本最匹配的候选,然后进行时间拉伸(0.72-1.25倍,保持音高)以填充约90%的原始窗口时长。在Glow片段上的验证数据:中位音高144 Hz vs 说话人154 Hz(Kokoro基础语音123 Hz),长期频谱相似度0.96 vs 0.90,每行回读正确。通过 DISPLAY|spoken 按音标拼写品牌名称(并自动将其排除在评分之外)。后备方案 tts_phrases.py = 使用Kokoro基础语音(清晰但不匹配说话人)。口音:模型传递的是音色/音高,不是母语口音——不要承诺埃及口音的英语;要说明实际达到的效果。
  4. 在原始分辨率帧上进行唇形同步:ffmpeg -t <end> -i src -vf fps=30 work/raw/%05d.png;ffmpeg -i work/voice_en.wav -ac 1 -ar 16000 work/en16k.wav;MODELS=work/models python3 -I scripts/lipsync2.py work/raw work/en16k.wav work/ls --model wav2lip_gan_96.onnx --enhance 0.7(先用 --range a b 测试;1700帧在4个CPU上完整运行约25分钟:Haar框、每帧的2dfan4地标、然后Wav2Lip + GFPGAN逐帧处理)。lipsync2 = 基于地标的FFHQ-512裁剪、平滑地标、在地标面部框上的Wav2Lip、0.7混合的GFPGAN修复、嘴部形状遮罩(绝不触及鼻子)、粘贴回去。然后运行 scripts/01b_upscale_lipsynced.sh。不要使用旧的 lipsync.py(粗糙的Haar裁剪:嘴唇模糊、舌头状伪影——用户称之为“非常差”)。EDTalk-256也曾试用过,效果更差(嘴部鬼影)。模型:来自facefusion-assets GitHub release的2dfan4、gfpgan_1.4、wav2lip_gan_96。
  5. 视觉同步验证:制作嘴部裁剪图的联系表,每帧下方显示音频包络线——嘴部在静音间隙必须闭合,在音频条上升时张开并有变化。像素相关性指标在此过于嘈杂,不要依赖它们。
  6. 图形:执行 python3 -I scripts/build_transcript.py work/en16k.wav(在源json中将 max_chars 设置为约22(英语)),重新生成 composition/transcript.js,然后重写 scene.js 复制和触发词(使用新语言:LTR方向下 .row/.chunk 方向为ltr,使用Inter字体,起点居左,流向箭头从左到右)。多词标记在转录中作为单独的词处理:查找单个词(ts('skin',0,43.5)),切勿使用 ts('your skin')。
  7. 像往常一样渲染(LAST_SRC_FRAME=<n> scripts/02_render_all.sh、提示、音效)并与 VOICE=work/voice_en.wav OUT=out/name-en.mp4 scripts/03_mix_and_encode.sh 混合。
  8. 在摘要中诚实说明:Wav2Lip在大约100像素的面部上会产生柔软、略微平滑的嘴部(近看可见),头部和手部动作仍然是原说话人的,语音是合成的,说话人应批准其形象的配音版本,建议标记为AI配音。注明任何源转录置信度较低的翻译短语。

短视频编辑器(字幕 + 动态图形 + 音效)

两种模式:编辑(保持语言,添加字幕/图形/音效)和配音(翻译成另一种语言,新语音,嘴唇随新音频重新动画化——当用户提到英语/翻译/配音/唇形同步时触发)。流水线已在57秒的埃及阿拉伯语药店宣传片(Glow Cosmetics)上验证。输出:1080x1920 @30fps、H.264/AAC、-14 LUFS。 已完成的示例项目:projects/glow-kbeauty-reel/ 在 https://github.com/MuhammadToffaha/Video-editing

定义“专业,而非模板”的规则

  • 保持说话人、语音和原意不变。绝不虚构声明(数字、“100%”、价格)。如果图形需要文本而原语音中并未说出,则保持通用(类别名称、标签文字)。
  • 每个视觉元素支持一句口语,并在该词上触发(ts('word')),而非短语开头。卡片在下一个进入前退出;无重叠残影。
  • 单一视觉语言:品牌色(从Logo采样) + 白色 + 深墨色玻璃面板,拉丁标签用Inter字体,标题/字幕用Cairo字体(阿拉伯语)。仅薄荷色用于成功状态。
  • 布局区域(1080x1920,说话人面部约y 790-1110):卡片y 235-735(绝不覆盖面部,即使1.15倍缩放后),字幕y约1545,保持底部220像素和顶部130像素无关键内容(平台UI)。需为每个源重新检查面部位置。
  • 留存手段,适度使用:句子开始时1.12-1.15倍缩放快切,其间缓慢漂移,每2-4秒一个图形,活动单词高亮字幕,划线/勾选/计数微动画,品牌名称出现时的片头Logo时刻,品牌片尾卡片。
  • 音效:卡片进入时的嗖声,元素上的噼啪/滴答声,成功时的铃声,Logo上的重击声。音量低(比语音低约-10 dB)。除非用户提供,否则不使用音乐。

工作流

  1. 检查:ffprobe,联系表(ffmpeg -vf "fps=1/6,scale=239:-1,tile=5x2"),查找片尾卡片(WhatsApp/CapCut黑帧)并记录说话人位置。原始源通常分辨率较低(手机/WhatsApp):使用lanczos升采样,告知用户画面会偏软而图形保持清晰。
  2. 项目:cp -r <skill>/template/. my-project/ && cd my-project;cp <logo> assets/;python3 -I scripts/extract_logo.py assets/logo_original.png assets/logo_white.png(打印品牌十六进制颜色)。在 composition/style.css 和 #wm/#outro 中更新 --coral/--brand。
  3. 准备:END=<trim_seconds> scripts/01_prepare.sh input.mp4(帧、16k wav、语音)。
  4. 转录(沙箱中无HF访问;GitHub releases可工作):运行 scripts/fetch_asr_model.sh;然后
    • 运行 python3 -I scripts/asr_chunks.py work/asr16k.wav <lang|auto> 3.2 a,重复使用2.4和4.5。Whisper会截断片段尾部;自己合并3个假设并利用自己的语言知识修正。
    • 不确定的词/品牌名:运行 python3 -I scripts/asr_probe.py work/asr16k.wav ar,en 14.0-16.8 14.5-16.6 ...(en 通道拼写拉丁品牌名称)。只信任跨重叠窗口一致的内容;其余的在最终消息和README中列为低置信度。绝不要基于猜测的名称构建图形。
  5. 时间点:运行 python3 -I scripts/pauses.py work/asr16k.wav -> 停顿是可靠的短语边界。将 data/transcript.source.json 写为 [start, end, "text"] 短语(参见 data/transcript.source.example.json;*word = 重点标注;多词拉丁名称内使用NBSP;RTL文本中的拉丁品牌:避免阿拉伯语 و 前缀粘附到它们上,写成 و Brand)。然后运行 python3 -I scripts/build_transcript.py work/asr16k.wav 和 echo "window.TRANSCRIPT=$(cat data/transcript.json);" > composition/transcript.js。该脚本通过音节权重在每个短语内分配词的时间并匹配能量谷点,然后生成2-4个词的平衡字幕块。合理性检查:无声间隙内无词起点。
  6. 在 composition/scene.js 中设计场景(参见 reference/scene-patterns.md)。使用 card(t0,t1,{y,h,html})、pop、fade、draw、cue、ts。将示例场景作为模式使用:钩子卡片、品牌芯片(说出名称时填充的骨骼槽)、类别磁贴、A->B匹配图(带移动圆点和勾选)、划掉芯片、流程节点、星级评分、清单行、路线图、条形图、信任环、片头Logo揭示、品牌片尾。设置 finish(<seconds>) = 语音结束 + 约1.7秒片尾。
  7. 渲染与质量保证:首先渲染几个测试帧(node scripts/render.mjs <f> <f+1> work/test),使用Pillow制作联系表,查看它们。然后运行 scripts/02_render_all.sh(4个worker,总计约8 fps)、node scripts/render.mjs cues work/cues.json && python3 -I scripts/sfx.py work/cues.json work/sfx.wav、OUT=out/name.mp4 scripts/03_mix_and_encode.sh。如果源视频以片尾卡片结束,传递 LAST_SRC_FRAME=<n> 以冻结最后一帧干净的画面。
  8. 交付:发送mp4(SendUserFile),注明规格、低置信度转录片段、原始分辨率限制,以及音频未经人耳听校(你无法听到)——仅通过响度计和起点vs能量测试检查。

已解决的陷阱(无需重新学习)

  • Python的 str.split() 会在NBSP上分割——使用 split(' ')(已在 build_transcript.py 中修正)。
  • 使用CSS scaleY 动画化SVG <rect> 在无头Chromium中会导致翻转/偏移问题——改为补间 attr:{y,height}。路径描边动画:使用 draw(path,t,d)。
  • 初始隐藏的元素需要CSS opacity:0(类 hid)和设置 immediateRender:false 的补间;每个补间必须可寻址(worker直接跳转到其起始帧)。
  • 使用 backdrop-filter 的卡片仅在视频帧位于同一页面(#bg img)时才能模糊——这就是为什么帧会在页面内合成。
  • 空的模糊卡片看起来有问题:要么在触发词上开始卡片,要么显示暗淡的占位行/插槽,在讲到时点亮。
  • 阿拉伯语需要真实字形整形:Chromium + Cairo woff2(按unicode范围分割阿拉伯语/拉丁语)可行;Pillow/ffmpeg drawtext不行。
  • sherpa-onnx中的Whisper没有词时间戳且会截断尾部;因此使用短窗口+停顿锚定。
  • opencv 5.x没有 CascadeClassifier(请锁定4.10.0.84版本);Haar人脸框会在手/衬衫上产生误报并遗漏约30%的帧 -> 中值框离群值剔除 + ROI二次检测 + 插值(已在 lipsync.py 中实现)。
  • Kokoro/Whisper风格的TTS会把 COSRX 作为字母逐个读出:使用 DISPLAY|spoken 覆盖。
  • GitHub MCP的 create_repository 可能返回403——请让用户创建仓库,然后使用 add_repo + 克隆(如果路径已存在则克隆到新目录)。

相关技能