Communitygithub.com

real-sfx:为动态视频添加真实录音音效

从用户自己的声音库(包括主要音效包和备用库)中选取真实的录音,为动态视频进行音效设计。音效绝不使用合成声音,支持界面提示音以及用户自定义配置。

real-sfx:为动态视频添加真实录音音效 是什么?

real-sfx 是一个 AI 技能(适用于 Claude Code、Cursor、Codex 等平台),专门为动态视频提供真实的、非合成的音效设计。它从用户自己的声音库(主库和备用库)以及一个独立的 CC0 界面音效包中选取录音,覆盖了呼啸声、碰撞声、上升音效、咔嗒声、铃声、键盘声、拟音和环境音等类型。该技能的核心原则是“绝不合成”,这意味着没有匹配的录音时,相关时刻保持静音,并会记入报告。它支持多种输入源(项目事件列表、屏幕录制、仅视频文件),并提供了从瞬间检测、音效匹配、混音到回放和评论的完整工作流。real-sfx 尤其注重避免与原有合成音效或背景音乐产生“加倍”现象,并能分析视频中的语音和音乐成分,以决定保留哪些原生音轨,实现智能叠加。

兼容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/SallyRS/video-director/tree/HEAD/skills/video-director/real-sfx

在你喜欢的 AI 中提问

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

文档

real-sfx:为动态视频添加真实录音音效 是做什么的?

目标:让影片听起来像是拥有专业音效库的剪辑师制作的效果。为此:

  • 音效绝不使用合成。 音源来自:用户的音效库(config.json)和 uisfx(一个 CC0 许可的界面音效包,本身是合成的,这是唯一的例外,仅用于界面时刻;可通过 --ui library 关闭合成)。若没有适合的音效,则该时刻保持静音并记入报告。这会覆盖 motion-standards 中的“无音轨:合成”规则。
  • 你不能听到音效。 音效通过数字、文字和图片来读取(references/listening.md)。不要将某个被选中的音效描述为“听起来如何”,而应说明它通过目视和测量检查了什么,以及用户应聆听什么。
  • 保留音乐和人声,当它们承载影片时。最终输出始终是一个新的 MP4 文件 以及一个单独的 WAV 音轨。
  • 避免加倍。 渲染中内嵌的合成音效将被真实音效替换,而不是在其下方叠加(第一步)。评论会将其量化(doubling 轴)。
  • 不要修改项目或技能文件夹。 将所有工作文件放在自己的文件夹(work/、result/)中。

在 Video Director 中使用

(此副本在 Video Director 的副本中新增;Clipwing 的原版中没有。UPSTREAM.md 列出了所有更改。) 此副本位于 Video Director 技能中,并由其 Sound 阶段执行:../references/sound-stage.md,“声音工程”。该阶段决定哪些时刻需要音效,将仅这些时刻提供给本技能(build/audio/sfx/events.json),固定用户选择的录音(sound_handoff.py pins),并使用 --ui library、--no-loudnorm 及无纹理层、无背景底垫运行,最后仅取回效果音轨和已解析的提示(sound_handoff.py collect)。请遵循这些步骤,并仅就它们未涵盖的选项阅读本文件。将 REAL_SFX_CONFIG、REAL_SFX_INDEX、REAL_SFX_TASTE、REAL_SFX_RATINGS、REAL_SFX_STEADY 和 REAL_SFX_STYLES 设置为 ~/.config/real-sfx/ 下的路径(插件会将每个版本安装到一个新文件夹,因此写入此处的任何内容都会在下一次更新时被遗弃),并且不要使用 --remember(它会写入此文件夹,learn_style.py 也是如此,学习到的样式应复制到 ~/.config/real-sfx/styles/)。

快速路径

首先执行 python scripts/setup.py check(检查 ffmpeg、主库/备用库、索引、uisfx)和 python scripts/look.py FILM.mp4 --out work/look(生成带有时间和原始音轨的帧)。然后,根据你拥有的内容:

# 1. 项目有事件列表(docs/cues.json, scripts/cues.json)或有合成其音效的脚本(audio.cjs)
python scripts/from_cues.py PROJECT_FOLDER|docs/cues.json --video RENDER.mp4 --out work/cues.json
# 2. 屏幕录制,无列表:ui_events.py ...(参见 references/screencast.md),然后 from_cues.py work/ui/events.json
# 3. 仅视频:find_moments.py FILM.mp4 --out work/moments; suggest_cues.py work/moments/moments.json --out work/cues.json
# 3b. 柔和彩色动画,无列表(UI 预览、插图、动态图形):自动化能检测到 5-6 次移动,总共 40 次。
#     步骤 2,“无列表的静默动画”:find_moments.py FILM --out work/moments --fine; look.py FILM --at T --span 2.4
#     --step 0.1 --out work/at.png; 根据帧自行创建事件列表(参见 references/typed-cues.md)-> from_cues.py - --ui library
python scripts/mix.py work/cues.json --out result/film_sfx.mp4 --plan     # 预览每个音效的位置;然后不带 --plan 运行
python scripts/critique.py result/film_sfx_resolved_cues.json result/film_sfx_sfx_track.wav
python scripts/levels.py   result/film_sfx_resolved_cues.json result/film_sfx_sfx_track.wav --json work/edits.json
# 一部音效仅由 SFX 构成的影片(没有自己的音乐或人声):在空白处添加小音效,然后再次运行 mix.py(步骤 4,“小音效层”)
python scripts/texture.py work/cues.json --moments work/moments/moments.json
# 同一部影片:背景底垫(一个长的黑暗真实录音,铺满整个影片;步骤 4,“背景底垫”),然后再次运行 mix.py
python scripts/bed.py work/cues.json [--list]
# 与九个已完成 SFX 卷轴对比(步骤 6,“与基准对比”):不产生评分,不影响最终裁决
python scripts/critique.py RESOLVED.json WAV --style clean-sfx-refs
# 廉价的人类耳朵测试(步骤 6):生成一个包含评论问题和一个点击裁决的页面;以及遮罩模型
python scripts/listen_page.py build work/listen --moments result/film_sfx.mp4 --critique RESOLVED.json WAV
python scripts/listen_page.py serve work/listen [--lan]        # 然后:listen_page.py results work/listen --log
python scripts/mix.py work/cues.json --out result/film_sfx.mp4 --masking        # 被其余部分隐藏的音效(需要虚拟环境)

项目文件夹会自行查找其事件列表(docs/、scripts/、assets/);合成脚本仅在无列表时被读取。在编辑表格前选择所有 from_cues.py 标志:重新运行它会清除手动编辑(然后使用 sheet.py apply)。 影片中有语音:mix.py ... --voice-safe(深度 normal;当有许多轻柔纹理时使用 --voice-depth light,仅对罕见音效在暂停处使用 deep:它会将界面完全从混音中移除)。音乐承载影片:--duck。响度:默认重建的基底与原始匹配;自定义:--target-lufs NUMBER。 无索引,或库已移动:python scripts/build_index.py,然后 python scripts/listen.py tag-index。无 uisfx:setup.py init --uisfx。另一台机器:setup.py scan FOLDER,setup.py add-library NAME PATH [--tier main|extra] --index。从技能文件夹运行脚本;引号路径中包含空格或非拉丁字符;在 Windows 上使用你自己的 Python 及非拉丁路径:PYTHONUTF8=1。在 PowerShell 中,引号会破坏 JSON 参数:将它们放入一个文件中。

音效来源

需要什么来源
基础:呼啸声、碰撞声、上升音效、咔嗒声、铃声、键盘声、纸张、拟音、环境音主音效库(tier: main,路径在 config.json 中)。一个带有 catalog.json / catalog.csv 的分类包,为每个音效提供类型和源录音,避免仅凭文件名猜测
主库缺少的:低音下落、硬币声、短时故障音备用音效库(tier: extra,结果中标记为 ~):仅当主库中少于三个匹配音效时使用
具有自身特定角色的设计包在自动选择中不会请求角色 granular、atmosphere、power、music_transition、voice 的音效:显式使用它们(--role、"pick": {"role": ...})
界面时刻:点击、滴答声、窗口、通知uisfx(--ui auto)当列表本身命名了界面类型(点击、铃声等)时:from_cues 会说明原因和位置(routes: key -> library:click, pop -> uisfx:select)
打字音始终使用音效库的真实键盘,即使使用 --ui auto;from_cues 自身会将连续 8 个以上间隔 35–170 毫秒的 click 事件识别为打字(--no-typing-detect)
物理接触:球、脚步、珠子、物体始终使用音效库:例如球落在地板上是沉闷的撞击声,而不是 select(配方如下)

尚无音效库:仅使用 setup.py init --uisfx 可提供 78 个 CC0 界面提示。值得检查的免费真实录音来源(阅读各许可):Freesound(CC0 过滤器)、Sonniss GDC bundles、Mixkit、Pixabay 音效。

“来自我的库”、“无合成”或“声音听起来很合成”:使用 --ui library。在带有 uisfx 界面音效的项目中强调标志或“cha-ching”声:使用 --from-library pop,bell(类型名称来自列表);对于单个音效:sheet.py set --at T --label bell id=65。在有调性音乐下:

  • uisfx 重复音调以及音效库中有调性音效(铃声、砰砰声、玻璃声、硬币声)的音高步进会在项目有乐谱时自动关闭(--ui-pitch off|cycle);
  • 真实音效的音高会与音乐音符对齐:mix.py 会获取表格中的 music_ref(无效果的背景底垫、音乐主干)或 --music-ref FILE,并将一个有调性音效移动最多 2 个完整半音加上使它与音符对齐的百分音(总共最多 2.5 个半音);噪音将被忽略(--no-tonal-fit;scripts/tonal.py SOUND --music FILE --at T 显示音符);
  • 作者自己频率的间隔(tick(t, 1800 * 2 ** (4 * i / 12)))会成为替换音效的音高步进(melody:)。

工作流程

1. 现有音轨中已有什么

look.py 显示原生音轨的频谱(语音是短语带、音乐是带节拍的地毯、静默是黑色);listen.py voice FILM.mp4 给出语音和音乐的占比。三种情况:

  • 作者的音乐或语音:它们被保留,SFX 叠加在上面(--duck / --voice-safe)。 例外(某人对真实影片的答复,2026-10-19):影片被送来“进行音效设计”,其原生音轨仅包含音乐(listen.py voice:语音 0%),并且此人希望 去掉 音乐,就像他们自己的干净 SFX 卷轴一样。制做一个无音乐版本(from_cues.py ... --ui library --drop-original,然后 bed.py --id ... --level -46,使用一个喜爱的氛围音效),如果有用,再制做一个有音乐版本,并说明哪个是哪个。在三者的盲选(原始 / 音乐上叠加效果 / 仅效果)中,此人选择了最后一个,没有任何不满。尽管没有烘焙的合成音(语音 0%,音乐 84%,攻击点与事件不匹配:7% 对 9% 的随机概率),from_cues 仍会在这样的影片上打印 BAKED::这是误报。
  • 烘焙在音轨中的合成音(项目是为合成配乐编写的):在合成音上叠加真实音效会造成加倍。from_cues.py 会自行检查这一点(BAKED:、unbake:),并在不触动语音和音乐的情况下从基底中移除合成音;具体方法以及当脚本失败或合成音位于音乐主干内时该怎么做(--extra-synth):请参阅 references/project-audio.md(一旦输出中出现 BAKED、WARN stems、unbake: not possible 或项目使用脚本合成其音效,就阅读它)。构建后,critique.py 会打印 doubling 轴:该层与原始音轨和新影片的相关性(应约为 0)。
  • 屏幕录制窗口中播放视频片段的声音:原生音轨,保留;这些窗口内的事件将被丢弃。

2. 查找时刻(从最佳到最差来源)

  • 项目的事件列表或合成脚本 → from_cues.py(见下文)。详细信息:references/typed-cues.md。
  • 屏幕录制 → references/screencast.md(ui_events.py 区域,将按键与字符匹配,片段声音)。
  • 带有 data-start 的 HyperFrames 且无列表:from_hyperframes.py PROJECT --out work/moments.json。如果输出“1 moments”但包含 18 个元素,则表示运动不遵循 data-start:寻找合成脚本。
  • 仅视频:find_moments.py FILM --out work/moments [--roi x,y,w,h] [--from A --to B] [--fine];类型有 cut、burst、onset、settle(settle 也会在空白帧或静止循环上触发:查看帧);look.py --moments ... 绘制时刻的帧。骨架:suggest_cues.py(references/recipes.md);草稿是起点,不是最终答案。--fine 用于柔和彩色动画(渐变、发光、改变颜色而非亮度的柔和形状):它还会读取色度变化,时刻会获得 src=chroma|luma;在三部这样的影片上,它找到了代理从帧中记录的事件的 33–69%(在 80 毫秒内),而单独使用亮度只能找到 13–25%;候选项数量多 3–4 倍(每 10 秒 15–25 个)。这些是候选项:帧决定最终选择。
  • 音乐下:beats.py FILM --out work/beats.json --plot work/beats.png;如果 usable: true,则 mix.py --snap-beats(±50 毫秒)。拍点网格 会与底鼓对比检查(低频 < 125 Hz 部分单独处理):它会打印在 40 毫秒内落在底鼓上的拍点数量。落在底鼓旁边的网格(轨道捕捉到镲片上,“偏离 0.22 秒”)会被移动到拍点上;落在空处的网格会被标记为 usable: false,并且 --snap-beats 会忽略它。--plot 绘制频带、底鼓(绿色标记)和网格(红色线条):标记应位于线条上,否则不要信任网格。如果音乐属于你并且可以匹配画面:beats.py FILM --suggest-offset work/moments.json 指示应将音乐移动多少以使剪辑和碰撞点落在拍点上(仅供参考;音乐本身不会被触动)。

from_cues.py:python scripts/from_cues.py LIST|PROJECT_FOLDER|SCRIPT.cjs|- --video RENDER.mp4 --out work/cues.json(- 从 stdin 读取列表;PowerShell 的 BOM 能被理解)。它自行执行和说明的内容:

  • 是否为正确的渲染:列表与画面不匹配(VERDICT);一个设计时列表与一个根据语音时间调整的渲染:从项目的锚点构建时间映射(包含 anchors 或 WARP 的 timing.json、src/timing.js),或从合成主干的开端点构建,每个事件落在自己的开点上(time map);--time-map FILE、--warp off|stems|audio;
  • 列表下的合成音:一个呼啸声落在合成音的开点上,其长度从该点测量(retime:);如果该开点属于另一个声音(咔嗒声、铃声)或列表时间已经是呼啸声的中心,则不移动:以原因命名;没有对应列表事件的合成开点会被列出(--add-unlisted tick 将它们转换为事件);
  • 音色:被替换的呼啸声的亮度(合成层的质心)会输入音效选择(timbre:);--tone airy|dark 手动设置;
  • 未知类型(bead、soft):它会显示项目如何定义它。用一行说明,无需文件:--kind bead=click,--kind soft=pop,一个带有限制的角色 --kind bead=role:click,max_dur=0.3,onsets_max=1,--kind bead=slices:740,763(来自这些录音的单个音效;最安静的那些,音量低 12 dB,不会被选用),--map '{"glass":{"ids":[65,54],"role":"chime"}}'(ids 轮流使用;一个元素 {"id":800,"slice":[0.78,0.12]});--remember 保存它。摘要:declared N events: M voiced, K silent;评论会将静默类型计为...

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能