Communitygithub.com

beachyphotoandfilm-arch/video-skills

将摄像机素材与独立的领夹麦克风或外置录音机音轨(如 Tascam DR-10L 等)同步,并在 DaVinci Resolve 中搭建时间线。它会合并录音机的分段文件,通过文字匹配和波形对齐精确定位每个片段,为每个片段裁剪出独立的领夹音轨,检查削波,并在新的 Resolve 项目中构建同步时间线。

video-skills 是什么?

此技能专门用于后期制作中的音频同步流程,特别适用于使用独立录音设备(如 Tascam DR-10L)录制高质量音频,而摄像机仅录制环境音的场景(如现场演讲、活动、工作坊)。技能首先合并录音机产生的分段 WAV 文件,然后利用 Whisper 对音频双方进行转写,通过独特的短句匹配算法获得候选偏移量,再通过波形互相关进行精确到亚帧级别的校准(通常精度在 20 毫秒以内)。它为每个摄像机片段裁剪出精确对齐的领夹音轨,并输出与 DaVinci Resolve 兼容的音频文件及 JSON 元数据。最后,通过 Resolve MCP 服务器自动构建包含视频画面和纯净领夹音频的同步时间线,并应用 LUT。该技能支持多平台,依赖 ffmpeg、whisper.cpp 和 Python,能够处理垂直或水平素材,并对录音机时钟漂移、削波等问题进行了妥善处理,是进行后续粗剪(如 paper-edit 技能)和最终视频制作的基础。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/beachyphotoandfilm-arch/video-skills/tree/HEAD/skills/lapel-sync

在你喜欢的 AI 中提问

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

文档

领夹麦克风同步

输入:摄像机片段 + 独立录音机音轨。输出:每个片段的独立领夹音轨 + 同步的 DaVinci Resolve 时间线。首次测试于一场现场演讲:5 个摄像机片段对应一段 59 分钟的录音机音轨。每个片段的对齐精度在 20 毫秒以内,远低于一个帧的时长。

为何重要: 在活动现场,摄像机麦克风通常摆放在房间的另一端,其录制的音频无法使用,而领夹麦克风是唯一清晰的声音来源。使用本技能后,<工作目录>/<片段名>.wav 和 <片段名>.json 将指向纯净的领夹音轨,因此后续的纸面剪辑(paper-edit)和视频成片(video-reels)技能可以直接读取到干净的音频和转录文本,无需任何额外调整。

设置:填写以下内容

占位符说明示例
<FOOTAGE_DRIVE>原始素材所在驱动器,每个视频一个文件夹,录音机文件在 audio/ 子文件夹内/Volumes/MyWorkDrive
<SYNC_OUT>全质量领夹音轨切片的输出目录~/Movies/<视频名称>-sync
<LUT_PATH>可选的 LUT 文件路径,相对于 Resolve 的 LUT 文件夹MyLuts/SLog3-to-709.cube
WHISPER_MODEL (环境变量)whisper.cpp 模型文件默认 ~/.cache/whisper-models/ggml-small.en.bin

需求:ffmpeg、ffprobe、whisper-cli(whisper.cpp)、Python 3(numpy 和 scipy 会自动安装到 ~/.cache/lapel-sync-venv)、DaVinci Resolve(需运行 Resolve MCP 服务器以暴露 execute_resolve_code),以及 paper-edit 技能(用于获取 ensure_resolve.sh)。

运行

工作目录:会话暂存区,例如 <暂存目录>/<视频名称>。以下技能目录指 <暂存目录>/.claude/skills/lapel-sync。全质量切片输出至 <SYNC_OUT>。

zsh 陷阱: 在内联 shell 中,$ss:end_sample 会解析 :e 作为修饰符并静默吞掉文本。务必写成 ${ss}。

1. 查找素材和音频

<FOOTAGE_DRIVE> 上每个视频一个独立文件夹。录音机文件位于 audio/ 子文件夹:

find "<FOOTAGE_DRIVE>" -maxdepth 4 -iname "*<关键词>*" -not -path "*/.*"
ls "<文件夹>" "<文件夹>/audio"

例如,一台 Tascam DR-10L 会生成 000_YYMMDD.wav、001_... 等文件,每 15 分钟分段,并伴有 _D 后缀的双轨安全音轨(安全音轨音量约低 20 dB)。使用主音轨文件;保留 _D 文件用于修补削波位置。

2. 合并录音机分段文件

bash <技能目录>/scripts/stitch.sh "<文件夹>/audio" "<SYNC_OUT>/lav-master.wav"

它会读取每个文件的 BWF time_reference(自午夜起的样本数),并检查每个文件是否恰好从前一个文件的末尾开始。如果样本连续,则进行无损数据流复制。如果存在间隙,则会插入等量的静音,使主音轨保持墙上时钟时间,并提示间隙大小。

3. 转写两边音频

bash <技能目录>/scripts/transcribe_sources.sh "<文件夹>" "<SYNC_OUT>/lav-master.wav" "<工作目录>"

所有结果存放在 <工作目录>/sync/ 中,避免干扰 <工作目录> 本身(防止 paper-edit 技能的 sentences.py 误读)。摄像机音频首先会被强力增益(highpass=f=120,volume=40dB,alimiter,16k 单声道),因为其音量通常低至 -65 dB。已完成的转写任务会被跳过,因此可以安全地重复运行。

领夹音轨的转写速度约为每 8 分钟处理 1 小时音频。可在后台运行。Whisper 会将词级时间戳流式输出到 <工作目录>/sync/lav.log,当 lav.json 尚未写入时,align.py 会读取该日志,因此对齐过程可以在领夹音轨转写完成前开始。对于超出已转写范围之外的片段,仅会提示“仅匹配到 N 个单词”;待转写完成后重新运行即可。

4. 对齐

python3 <技能目录>/scripts/align.py "<工作目录>"

输出 <工作目录>/sync/sync.json。首次运行会创建 ~/.cache/lapel-sync-venv 并安装 numpy 和 scipy(系统自带的 python3 通常缺少这些库);之后会在该虚拟环境中运行自身。

工作原理(了解后可以信任或质疑其结果):

  • 单词匹配优先。 寻找两个转录文本中共同出现的独特四单词组合。偏移量 = 领夹音轨时间减去摄像机时间。每个片段有数百个匹配点;在 0.5 秒内找最密集的簇,取中位数。精度可达约 0.1 秒。
  • 波形精调。 针对每个 20 秒的摄像机音频块(短于 40 秒的片段使用 6 秒块),在 300-3000 Hz 范围内进行带通滤波(8 kHz 采样率),然后与领夹音轨在 ±0.6 秒的单词偏移范围内进行互相关计算。峰值超过中位数的 6 倍才被视为有效。如果多个块给出的偏移量在 20 毫秒内一致,则采用;对于超过 5 分钟的片段,会通过线性拟合得出偏移量和漂移量。

阅读其打印的每一行输出:偏移量、达成一致的块数、离散程度、漂移量。任何标记为 请通过听感检查 的片段(少于 3 个达成一致的块)可能存在高达 0.1 秒的误差;请在 Resolve 中手动检查其同步情况。如果漂移量在一个片段内超过一帧,也会被标记。

5. 为每个片段裁剪领夹音轨

python3 <技能目录>/scripts/slice.py "<工作目录>" "<SYNC_OUT>/lav-master.wav" "<SYNC_OUT>"

为每个片段输出:

  • <SYNC_OUT>/<片段名>_lav.wav:24-bit,源采样率,与片段时间精确到样本级别,因此领夹音轨时长等于片段时间
  • <工作目录>/<片段名>.wav(16k 单声道)和 <工作目录>/<片段名>.json(该切片的 Whisper 转写):供 paper-edit 和 video-reels 读取
  • <工作目录>/clips.ndjson,其中 "audio" 字段指向切片文件

如果录音机在某个片段开始时启动较晚或提前停止,相应部分会填充为静音并给出警告。切片的 Whisper 转写需要几分钟;之后不要再运行 paper-edit 的 transcribe.sh(它也会因为 JSON 文件已存在而跳过)。

6. 检查削波

slice.py 会计算每个切片中采样值达到或超过 0.99 满量程的样本数,并打印最长连续运行长度。数百个短运行时(几十个样本)通常是录音机的限制器捕捉到的峰值,而非失真。只有当列出需要一听的片段(运行时达到 1 毫秒或更长),或用户反应声音听起来刺耳时,才从 _D 安全音轨中修补这些时刻(时间相同,音量提升约 20 dB)。

7. 在 Resolve 中构建时间线

bash .claude/skills/paper-edit/scripts/ensure_resolve.sh

写入 <工作目录>/sync/params.json:

{"project":"<视频名称> - YYYY-MM-DD","work":"<工作目录>","name":"Synced - Full Talk",
 "lut":"<LUT_PATH>"}

lut 是可选的;不使用则省略。然后调用一次 execute_resolve_code:

PARAMS = "<工作目录>/sync/params.json"
exec(open("<技能目录>/scripts/resolve_sync_timeline.py").read())

它会创建项目(如果名称已存在则打开),导入摄像机片段和领夹音轨切片,并构建名为 Synced - Full Talk 的时间线:每个片段在 V1 轨上仅视频(mediaType: 1),其对应的领夹音轨切片在 A1 轨上仅音频(mediaType: 2),入点和出点相同。recordFrame = 时间线起点 + round((偏移量 - 最早偏移量) * 24000/1001),从而保留片段间的实际间隙。LUT 应用于节点 1。摄像机的原始音频被保留。时间线分辨率:如果片段是竖屏则为 1080x1920,否则为 1920x1080(可通过 width/height 覆盖)。如果时间线名称已存在,则添加 v2 后缀,而不会修改现有时间线。

请让用户在几个片段中检查有清晰辅音(如“p”或“t”)的位置。这是最可靠的同步检查方式。

8. 交接

告知用户时间线已创建、第 4 步中每个片段的同步数据(每行一个片段)、任何被标记的片段以及削波检查结果。然后继续:paper-edit(跳过其转写步骤,因为 <工作目录> 已准备就绪)或 video-reels。

值得记住的事实

  • 仅靠波形相关性失败了。 在摄像机麦克风平均音量约为 -65 dB 的混响房间内,对整个片段和 20 秒块进行宽窗口波形相关性计算得到的结果不一致且杂乱。先词对齐,再窄窗口波形搜索,是有效的方法。
  • 摄像机时钟通常不准。 测试中,摄像机比录音机慢了约 149 秒。部分相机(如索尼)写入的 creation_time 是 UTC(以 Z 结尾),而录音机的 BWF time_reference 是本地时间。creation_time 最多只能作为粗略参考。单词匹配不需要它。
  • 漂移可忽略不计:在测试的设备上,约为 0.5 毫秒/分钟,一个 21 分钟的片段累计漂移 11 毫秒。无需进行时间拉伸。较短片段报告为 0,因为几秒内的拟合仅包含噪声。
  • 重新运行脚本生成的手动切片差异在 6 毫秒以内。
  • 竖屏素材: 例如,一台索尼相机拍摄的竖屏视频会以 23.976 fps 记录为 4K,并带有 rotation=90 的显示矩阵。Resolve 会将其识别为 2160x3840,无需额外旋转修正。
  • 示例录音机,Tascam DR-10L: 48k 24-bit 单声道 BWF 格式,每 15 分钟生成一个新文件,_D 安全音轨音量低约 20 dB。
  • paper-edit 的 resolve_build.py 仍会从摄像机文件中获取音频。 在领夹麦克风场景下,它构建的时间线会包含摄像机的原始音频,直到它学会读取 "audio" 字段。在此之前,告知用户,或将 A1 轨重新链接到 _lav.wav 切片;由于切片时间等于片段时间,所以剪辑点是一致的。
  • Whisper 运行时使用 -oj -ml 1 -sow 参数以启用词级时间戳。

相关技能

  • paper-edit:粗剪,在本技能之后运行
  • video-reels:读取 clips.ndjson;"audio" 字段指示其从切片中获取音频(如果已安装)

Individual skills in this repo

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

beachyphotoandfilm-arch/video-skills

Turn raw talking-head footage into an assembled rough cut inside DaVinci Resolve. Pulls the clips off your footage drive, transcribes them locally, removes failed takes, restarts, asides and dead air, then creates a new Resolve project with two paper-edit timelines ready for your fine trim. Trigger on "paper edit", "cut my raw footage", "make a rough cut", "clean up this video", or when the user points at a folder of raw camera files for a YouTube video.

beachyphotoandfilm-arch/video-skills

Design a unique Instagram cover for each reel in your house style. Reads what the reel is about, writes a short hook headline, picks one of your own photos from a tagged photo library, lays it out like your existing covers, and proofs it in grid view at phone size. Renders locally, never with AI image generation. Can be called by a scheduling skill before reels are scheduled. Trigger on "make covers", "reel covers", "cover photo for this reel", "design the IG covers".

beachyphotoandfilm-arch/video-skills

Render finished reels out of DaVinci Resolve, write captions in the creator's voice, attach a custom Instagram cover from reel-covers, and schedule them to Instagram, TikTok and YouTube Shorts through Metricool. Handles the Drive upload hop, collision checks against the existing calendar, and cleanup. Trigger on "schedule the reels", "post these", "put these on the calendar", or after reels are approved.

beachyphotoandfilm-arch/video-skills

Build animated brand overlays (motion graphics) for a talking-head video, timed to the speaker's exact words, plus a DaVinci Resolve import file. House style is in-scene type (text beside and behind the speaker's head) plus diagrams. Transcribes the rough cut locally, picks the moments, renders transparent .mov clips, and writes an FCPXML that drops every clip onto the timeline already in position. Trigger on "make animations for this video", "add overlays/motion graphics", "animate this", "b-roll graphics for my YouTube video", or when the user shares a rough cut and asks for graphics.

beachyphotoandfilm-arch/video-skills

Cut vertical Instagram reels out of a long-form talking-head video, hook first. Picks the strongest standalone moments from the transcript, opens each reel on its punchiest line, builds vertical timelines in DaVinci Resolve framed on the speaker's face with the LUT applied, and finishes them: a hook (a held text card, or a word-by-word "build" hook with punch-in) and burned-look captions on V3; this-or-that reels get product graphics and a comment-keyword CTA card. You trim and render, nothing to import. Trigger on "make reels", "clip this for Instagram", "cut some verticals", or after a YouTube video is cut.

beachyphotoandfilm-arch/video-skills

Design YouTube thumbnails and titles for a talking-head video. Pulls graded full-res frames out of the raw footage, renders brand-styled variants in two proven layouts, and proofs them at phone size where the click actually gets decided. Trigger on "make thumbnails", "thumbnail for this video", "title and thumbnail", or after a video is cut.

beachyphotoandfilm-arch/video-skills

Run the whole YouTube video pipeline end to end, one stage at a time, stopping for the creator's approval at every gate. Paper edit, punch-ins, reels, reel covers, scheduling the reels, overlays, thumbnail and title, then scheduling the long-form video, all through Metricool. Keeps state per video so you can stop anywhere and pick up later. Trigger on "/youtube", "let's do the whole video", "run the video pipeline", "continue the <name> video", or when handed raw footage for a YouTube video.

相关技能