Communitygithub.com

TaherZiad/montage-crew

自动检测并裁剪说话人头视频中的静音和冗余内容(如填充词、重复片段、假开头),在构建编辑之前使用 /auto-trim API 代替手写 ffmpeg,审查返回的候选片段,并完成只有人类/AI 能做的工作(识别重复的观点)。当指令启用“自动裁剪视频”功能或用户抱怨视频仍有冗余/静音时使用。

montage-crew 是什么?

该技能专注于在视频编辑流程的早期阶段自动裁剪静音和冗余内容,防止后续步骤(如字幕、缩放、音效)因时间戳偏移而打乱。它强调“先裁剪,后构建”的原则,通过一个分阶段的 API 工作流实现:分析(免费、可重复、不编码)、审查(人工/智能决定)、应用(通过渲染队列)。技能基于大量真实文件测量数据,发现固定阈值(如 -40dB)在不同文件上效果迥异,且仅凭音量无法区分“停顿”和“轻声说话”,因此将阈值选择交由服务器。同时,技能区分了机器可检测的静音、填充词、口吃等“内容死重”和只有人类能识别的“重复观点”,要求用户进行语义审查。最终输出裁剪后的视频和重映射的时间戳文件,并生成包含验证结果的报告,确保裁剪质量符合预设标准。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TaherZiad/montage-crew/tree/HEAD/skills/montage-crew/references/external/AIEV

在你喜欢的 AI 中提问

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

文档

自动裁剪 - 基于测量的静音与冗余内容修剪

原则

  1. 在构建场景/字幕之前裁剪。 之后裁剪会打乱所有时间戳(字幕、缩放、音效)。此步骤输出:assets/<source>.cut.mp4 + assets/transcript.cut.json - 后续每一步都使用裁剪后的版本。
  2. 当指令启用 autoCut 时,裁剪是强制性的 - 这不是一个建议。如果没有任何内容可裁剪,您必须在报告中说明具体原因(例如视频已经足够紧凑)。
  3. 阈值存在于服务器中,而非您的脑海中。 不要自己运行 silencedetect,也不要凭感觉选择 dB 阈值。两个经过测量的事实淘汰了这种工作流:
    • 正确的阈值是文件的属性,而不是常数。在一个真实文件上,-40dB 发现 0 个静音,-30dB 发现 13 个,-25dB 发现 21 个。硬编码的数字要么无用,要么会吞噬语音。
    • 仅靠响度无法区分“停顿”和“轻声说话”。在测量的源文件中,silencedetect 在 -30dB 时报告了 48.6 秒的“静音”,但其中只有 18.2 秒位于词语之间的真正间隙中;其他 30.4 秒在词语内部(音节边界、不发音的越南语尾音 c/t/p/ch)。仅根据音量进行裁剪会吞掉语音。 服务器负责测量(autoTrim.ts)和候选片段生成(deadWeight.ts)。您负责审查。 这种分工正是其核心所在。
  4. 两种类型的冗余内容会被裁剪:静音(机器测量,由字幕守卫)和内容死重(填充词、口吃、重述片段 - 由服务器提出,由您批准;加上重复的观点,只有您能发现 - 参见第 3 步)。

第 0 步 - 先决条件:包含单词时间戳的字幕

整个守卫功能依赖于它。服务器会查找 assets/transcript.raw.json,然后是 assets/transcript.json。如果没有字幕,分析仍然会运行,但返回的结果是 guarded: false,死重列表为空,并且数字在两个方向上都是猜测(它可能通过一个坏的裁剪,也可能拒绝一个好的裁剪)。请先转录 - 切勿在没有守卫的情况下修剪越南语说话人头视频。

第 1 步 - 分析(免费、可重复、不编码)

POST http://localhost:6869/api/projects/<id>/auto-trim/analyze
body: {}                                   # 或 { "source": "assets/face.mp4", "level": "tight" }

level 是 natural | default | tight,默认值为 brief.autoCutLevel。响应:

  • silence - durationSec,选择的 thresholdDb + thresholdNote(为什么该阈值胜出),测量的 noiseFloorDb,将要裁剪的 silences,keepRanges,removedSec,完整的 sweep 表,以及 wordGuard(字幕否决了多少秒)。
  • deadWeight - candidates[],包含 kind(filler | stutter | repeat-take | hesitation),start/end,text,confidence,reason,context;以及 totalSec 和 byKind。
  • guarded - 仅当找到字幕时为 true。如果为 false,请先修复此问题再裁剪。

不会进行编码,因此您可以随意调用(一个 217 秒的源文件大约在一秒内完成分析)。

第 2 步 - 审查每个候选片段(您的工作,而非机器的)

列表是确定性的:相同的字幕,相同的候选片段,相同的置信度。机器无法做到的是理解含义。请逐一检查它们,只保留您愿意为之辩护的那些:

  • 低置信度意味着“先阅读上下文”,而不是“可能没问题”。 越南语填充词几乎总是与真实词语冲突。đó,ấy,thế,mà,là 既是填充词,也是真实的指示词/连词。
  • 连接短语(hoặc là,tức là,bởi vì là,với lại là)是陷阱。 在一个真实字幕上测量:“…có thể là ok ứng dụng nó / Hoặc là / Tham khảo để tìm cách…” 是一个真正的替代方案 - 裁剪它会破坏句子的一支。但“Còn trường hợp mà mọi người có thể nghe / Hoặc là / Còn trường hợp mà người AI không ứng dụng được…” 是一个被放弃的句子,应该被裁剪。表面形式相同;只有含义将它们区分开。正是因为这个原因,这些候选片段会以低基础置信度返回,并附上写着“阅读上下文”的理由。
  • repeat-take 候选片段:在批准之前,检查后来的片段是否真的是更完整的版本。
  • hesitation 候选片段是词语之间的纯静音 - 通常安全,但请检查您是否没有移除一个笑话前的故意停顿。

自由地拒绝。保留一个填充词的成本是 0.4 秒;裁掉一个真实单词会使句子变得无意义,观众会立即察觉到。

第 3 步 - 重复观点(只有您能发现这些 - 强制性)

没有检测器能捕捉到这一点,而这是用户抱怨最多的冗余内容。将字幕作为一段口头语言阅读,并从语义上进行分析:

  1. 将表达相同观点的句子分组 - 词语不需要匹配,只需要内容相同。说话者经常将同一观点重述 2-3 次:先简短/结巴,后更完整。也要考虑非相邻句子(提出观点 A,离题,然后更详细地回到观点 A)。
  2. 每组只保留一个版本 - 最完整的那个:
    • 早期简短版本,后期更完整的重述 -> 保留后期版本,裁剪早期版本。
    • 后期句子只是一个简短的回声(“đúng vậy,như tôi nói…”)-> 保留早期版本,裁剪回声。
    • 两个等效版本 -> 保留更流畅的表达(更少的结巴,无填充词)。
  3. 检查裁剪后的流畅性:从头到尾重读保留的文本。如果一个保留的句子指回(“như vừa nói”)一个被裁剪的句子,要么两者都保留,要么选择没有反向指代的版本。
  4. 将每个决定转化为一个 {start, end} 范围,并在第 4 步中与批准的候选片段一起发送。
  5. 在裁剪前构建一个表格(将其放入报告中):时间戳 | 被裁剪的句子 | 原因 | 保留的句子 - 以便用户可以审查每一个决定。

第 4 步 - 应用(通过渲染队列)

POST http://localhost:6869/api/projects/<id>/auto-trim/apply
body: { "cutCandidates": [{ "start": 51.81, "end": 52.25 }, …] }   # 仅限您批准的内容
-> 202 { job }

如果您没有批准任何内容,则发送空列表 - 测量的静音仍然会被裁剪。然后轮询 GET /api/jobs/<jobId> 直到它完成。该任务:

  1. 使用字幕守卫重新分析,将静音范围与您批准的范围合并(重叠部分合并,因此不会重复计算)。
  2. 丢弃任何会吞掉单词中点的已批准范围 - 这是对您审查的最后一道安全网,并记录它拒绝的每个范围。日志中被拒绝的范围意味着您批准了位于真实语音上的内容;请返回并重新阅读该位置。
  3. 在一次 ffmpeg 过程中裁剪(trim/atrim + setpts/asetpts + concat),写入 assets/<stem>.cut.mp4。
  4. 将每个时间戳重新映射到裁剪后的时间线 -> assets/transcript.cut.json。
  5. 使用重新映射的单词验证输出,并写入 assets/auto-trim-report.json。

如果没有任何值得裁剪的内容,该任务故意不会生成 .cut.mp4(重新编码的相同副本只会损失画质)- 报告中的 output 为 null,您继续使用源文件。

第 5 步 - 阅读报告(直到您阅读报告,任务才算完成)

assets/auto-trim-report.json 包含:裁剪前后的时长,removed.silenceSec 与 removed.approvedSec,选择的阈值及其原因,被拒绝的候选片段,以及 verification。

  • verdict: "pass" - 结果符合该级别的配置文件。
  • verdict: "fail" - 任务仍然完成,文件可用,但不符合配置文件。日志会明确说明。批准更多的死重(第 2/3 步)并再次运行 apply,或者在最终报告中说明您接受此结果的原因。切勿在忽视失败的情况下报告裁剪已完成。

通过标准不是旧的“无静音 > 0.8s”规则 - 测量表明该规则过于宽松。一个真实文件通过了该规则,同时携带了 13 个持续 0.45-0.67 秒的残留静音,总共 6.7 秒(运行时长的 4.2%),听起来明显拖沓。现在的配置文件同时限制了最长单个静音和总比例(default:0.5 秒 / 3%)。

第 6 步 - 在所有地方使用裁剪后的版本

从此以后,字幕、关键布局、音效时间和缩放都读取 assets/transcript.cut.json 和 .cut.mp4。QC 检查 dead-air 会重新测量组装后的视频与字幕的对比,并且当 brief.autoCut 开启且死空气仍然超过配置文件时失败 - 这是后盾,而不是计划。

最终报告必须包含:第 3 步的裁剪表格,按静音与批准的死重分割的已移除秒数,以及验证结果。数字取自 auto-trim-report.json。

已知问题

  • 裁剪后使用旧字幕 -> 字幕在结尾处同步偏差越来越大。始终切换到 transcript.cut.json。
  • 仅裁剪静音而忽略重复观点 - 用户所说的“冗长内容”大部分是第 3 步。
  • 裁剪渲染后的草稿而不是源文件 -> 质量因第二次编码而下降。始终从源文件裁剪(服务器拒绝覆盖源文件,并在选择默认值时跳过已命名为 *.cut.* 的文件)。
  • 分析 .cut.mp4 而唯一的字幕是原始字幕 -> 守卫与错误的时间线对齐。确保源文件与描述它的字幕匹配。
  • 带有自身前导静音的音效/旁白文件 -> 使用 data-media-start 在 HyperFrames 中进行修剪(参见 noti-tiktok-vn 技能中的“音效响度和前导静音”),不要仅仅为了 0.3 秒的前导静音而重新编码音频文件。
  • 连接裁剪段时没有淡入淡出 -> 在每个连接处产生咔嗒声。已在 autoTrim.ts 中修复;规则如下,适用于任何裁剪或连接音频的新代码。

音频:在每个裁剪边缘淡入淡出 30 毫秒(硬性规则)

一个裁剪落在波形中间。一个片段的最后一个样本和下一个片段的第一个样本没有关联,因此连接处是一个垂直台阶,而一个台阶就是一个咔嗒声。原因不在于编码器,也不在于源文件 - 而在于连接本身,因此它会在下游任何重新编码中幸存。

它的重要性取决于裁剪落在何处,并且差异很大。 在一个真实的 278 秒说话人头视频上以无损方式测量,比较相同裁剪有无淡入淡出的效果(连接处最大的样本间台阶;任何高于约 0.02 都是可听的):

连接类型之前之后
静音修剪,40 个连接(balanced)中位数 0.0040,最差 0.0113 - 无一听得见中位数 0.0000
语音中间,4 个连接(死重 / 重复观点)0.1195, 0.0744, 0.0232, 0.0064 - 4 个中有 3 个听得见所有 ≤ 0.0008

作为参考,在这些文件中的正常语音中,任何地方最大的台阶是 0.06-0.13。因此,没有淡入淡出的语音中间连接可能比内容本身产生的任何跳变都大,而静音连接则远不可听。

不要因为第一行数据就跳过淡入淡出。仅静音修剪是它碰巧无关紧要的情况;第 3 步(重复观点)和片段提取直接穿过语音进行裁剪,而这些正是会产生咔嗒声的连接。

修复:在每个片段的两边淡入淡出 30 毫秒。足够长以消除台阶,又太短以至于无法被听为淡入淡出。使用 apps/server/src/util.ts 中的 audioCutFade();不要手动编写滤镜。

[0:a]atrim=start=S:end=E,asetpts=PTS-STARTPTS,afade=t=in:st=0:d=0.030,afade=t=out:st=D-0.030:d=0.030[aN]

三件事会让它不起作用:

  • 顺序。 afade 必须在 asetpts=PTS-STARTPTS 之后。afade 从流自身的时钟读取 st;在原始时间戳上,st=0 已经过去,淡入永远不会触发。
  • 长度。 D 是片段持续时间,因此淡出的开始是 D - 0.030。将淡出限制为 D/2,否则两个淡入淡出会在短片段上重叠并吞没它。
  • 提取一个片段,而不仅仅是连接。 从一个较长视频中裁剪出的片段具有相同的两个原始边缘,即使没有东西被连接 - reframe.ts 通过 -af 对它们进行淡入淡出。

关于自行测量的一个说明:不要比较两个 AAC 编码。重新编码会在各处扰动样本,这会将 40 个真实连接淹没在 294 个虚假差异区域中,并在两个文件之间产生 54 毫秒的偏移。相反,将两个变体直接渲染为 pcm_s16le - 然后这两个文件样本对齐,连接正好位于累积的片段长度处。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

TaherZiad/montage-crew

Membangun motion graphic sinematik di browser (promo video, opener, intro, bumper, kinetic typography, explainer/video penjelasan bergambar 16:9 atau 9:16) memakai HTML + CSS + GSAP (+ Three.js bila perlu), dengan hasil yang bergerak seperti video sungguhan — bukan slide presentasi. Gunakan skill ini setiap kali user meminta "video promo", "opener", "intro animasi", "motion graphic", "bumper", "kinetic typography", "animasi teks sinematik", "explainer", "video penjelasan" (jurnalisme visual, kartun edukasi, kolase), atau menunjukkan referensi video promosi/explainer dan ingin dibuatkan versi web-nya — bahkan bila mereka tidak menyebut kata "motion graphic" secara eksplisit. Juga gunakan bila user mengeluh hasil animasi web "seperti PPT/presentasi" dan ingin lebih sinematik, atau ingin merender animasi web menjadi file video MP4, atau ingin explainer kartun/animasi dibangun LANGSUNG di After Effects lewat bridge/MCP Higgsfield.

TaherZiad/montage-crew

Agent 2 of the video editing pipeline. Finds and removes spoken mistakes — stutters, repeated words, false starts, and retakes (re-recorded lines) — from a talking-head recording. Use after cut-silences, when asked to cut mistakes, remove stutters / repeats / filler restarts, clean up flubs, or keep the best take. Works review-gated: it proposes every cut with context and a reason for approval, then renders only the approved cuts via ffmpeg. Requires a word-level transcript.

TaherZiad/montage-crew

Arabic short-video editor (any dialect). Edits talking-head videos and screen recordings, or builds an MG-led video from an idea with no footage - retakes and silences cut, Arabic RTL captions and hook, premium motion graphics, SFX, music, -14 LUFS master, cover - for 9:16, 16:9 or both. Delivers the MP4 plus a project for Resolve, Premiere, After Effects, CapCut or Final Cut. Asks a few questions on first use, keeps the user's brand kit, offers style cards, learns styles from videos, links and MG sites the user shows it, and learns the user's rules after each video. Use when the user asks to edit a video («منتجلي هذا الفيديو», «سوّي مونتاج», «أضف ترجمة», «قص الصمت», «بستايل …», "edit my video"), make a video from an idea («ما عندي فيديو، عندي فكرة», «فكرة فيديو عن…»), learn a style («تعلّم من هذا الفيديو», «هذا الموشن يعجبني»), save a brand («احفظ هويتي», «اقترح لي هوية») or change settings («غيّر إعداداتي»).

相关技能