mcpField
P
papercut-voice

papercut-voice

github.com/0xs4n4tg创意与媒体9952 次安装2 周前更新
代码仓库

关于 papercut-voice

papercut-voice 是 Papercut 视频流程中的旁白制作技能,面向制作短视频的创作者。它支持本地 Qwen3-TTS、自有录音或其他 TTS,以及占位音频,并生成词级时间、字幕和场景计划。

主要功能

  1. 01支持三种旁白制作路径
  2. 02生成并筛选逐行旁白 WAV
  3. 03通过 ASR 生成词级时间戳
  4. 04构建字幕和场景计划
  5. 05支持占位音频后续替换

适用场景

  1. 01为脚本生成并整理旁白音频
  2. 02为旁白字幕校准词级时间
  3. 03先用占位音频搭建视频,再替换配音

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/0xs4n4tg/papercut-explainer --skill papercut-voice

安装后在 Claude Code 中输入/papercut-voice确认已加载。

详细介绍

Papercut 语音

后续每个阶段都需要叙述文件夹中包含两项内容:voice/final_narrator/<id>.wav(每行脚本对应一个 WAV)和 timing_narrator.js(每个词的起止时间)。此技能通过三种路径之一生成这些文件,然后构建字幕和场景计划。脚本的完整参考文档见 library/voice/README.md。

预检

  • 库路径:使用 $PAPERCUT_LIB;否则使用 ~/.config/papercut-explainer/config.env 中的 PAPERCUT_LIB= 行;再否则询问一次。导出该路径,然后执行 . "$PAPERCUT_LIB/env.sh",将 ASR_PY、QWEN_TTS_PY 和其他配置值加载到 shell 中。
  • 已搭建脚手架的项目(papercut-build,步骤 1),其中包含 narration/script.json 和含有 scenes 的 papercut/episode.json。new_episode.sh 会将 build_timing.py 复制到 narration/。
  • 如果用户已经安装了 TTS,请直接使用,不要重装(路径 B;如果是 Qwen3-TTS,则使用路径 A)。询问一次 TTS 是什么,以及在哪里运行。否则询问要使用哪条路径,并说明所需条件:
路径所需条件安装模式
A. 本地 Qwen3-TTSlibrary/voice/setup_tts.sh 中的语音 venv(模型下载量为 2.3-4.2 GB)完整
B. 自行录音或其他 TTS一个 ASR 后端(mlx-whisper 或 faster-whisper),以及 ASR_PY 和 QWEN_TTS_PY 所指向的 Python 中的 librosa + numpy,用于音高处理完整安装,或手动安装这些软件包
C. 占位音频ffmpeg;使用 --say 需 macOS标准

如果所选路径需要的内容超出当前安装范围,请运行 ./install.sh --doctor,然后交由 papercut-setup 处理。没有 ASR 时,build_timing.py 只会按每秒 2.75 个词估算,因此字幕会与实际音频错位。

路径 A:本地 Qwen3-TTS

在系列文件夹中运行:

cp $PAPERCUT_LIB/voice/voice.example.json voice/voice.json     # once per series; edit it
$PAPERCUT_LIB/voice/narrate.sh voice/voice.json episodes/NN-slug/narration
$PAPERCUT_LIB/voice/finalize.sh voice/voice.json episodes/NN-slug/narration episodes/NN-slug/narration/voice/takes/narrator [num.json]
  • voice.json:包含 speaker(CustomVoice:Aiden、Dylan、Eric、Ryan、Serena、Vivian、Sohee、Ono_anna、Uncle_fu)和 instruct。推荐设置:CustomVoice 1.7B,Ryan 或 Aiden;instruct 使用 "友好、自然、口语化,像在给朋友讲述;句子之间停顿清晰;强调每行的关键词"。takes_per_line 默认为 3。tempo 保持 1.0(其他值需要 rubberband)。qa_targets 用于设置音高范围和 ASR 匹配度(0.9)。
  • 脚本行可以包含 tts(用于改善发音的改写文本;字幕仍使用 text)和单独的 instruct。num.json 将数字映射为读出的词语({"13,000": "thirteen thousand"}),避免 ASR 匹配数字失败。
  • 一次只运行一个 TTS 进程;1.7B 模型非常占用内存。
  • finalize.sh 会对每条候选音频运行 ASR 和音高检测,每行选取一条,进行裁剪、响度归一化至 -16 LUFS,在最终音频上重新运行 ASR,并写入 timing_narrator.js。试听后,将修正内容写入 voice/picks_override.json({"l3_name": 2}),然后使用 SKIP_PICK=1 重新运行。
  • Voice Design(用文字描述声音)是 Qwen3-TTS 的一种模式,narrate.py 不会调用此模式。请在其他地方使用该模式生成音频,然后采用路径 B。

路径 B:自行录音或使用其他 TTS

  • 每行录制一个 WAV 文件,放入 voice/final_narrator/<id>.wav;或者将原始录音放入 voice/takes/narrator/<id>_<k>.wav,然后按上述方式运行 finalize.sh。
  • 对于已完成的台词,先转录,再将 voice/chosen_narrator.json 写为 {id: "voice/final_narrator/<id>.wav"},然后在 narration/ 中运行:
$ASR_PY $PAPERCUT_LIB/voice/asr.py voice/final_narrator/*.wav > voice/asr_narrator_final.json
CHOSEN=voice/chosen_narrator.json TIMING_OUT=timing_narrator.js python3 build_timing.py voice/asr_narrator_final.json

路径 C:占位音频

在 narration/ 文件夹中运行:

python3 $PAPERCUT_LIB/tools/placeholder_vo.py [--wps 3.0] [--say [VOICE]]

此命令仅根据 script.json 生成无声 WAV 文件(或使用 --say 生成 macOS say 语音)和 timing_narrator.js,并按词长分配每个词的时间。使用 --wps 3.5 到 4 可近似达到目标语速(默认为 3.0)。可以先构建并调整视频节奏,之后再重新录制语音:替换 WAV 文件,重新运行 finalize.sh,再运行 build_vo.py,词级提示点会随之更新。

交付规则

朗读要自然、从容,并有所强调。观众必须第一次听就能跟上每一句。

  • 留出呼吸空间。 每句结束时,以及列表各项之间(“Fine. Fine. Fine.”)都要有明显停顿。先将每行之间的间隔设为 0.3-0.4 s(episode.json 中的 gap,默认值为 0.22;gaps 会在指定行后额外增加一个节拍),再听效果判断。停顿只放在句子或分句边界:在短语中间停 0.2 s,例如 “copied it, | by taking...”,听起来会像卡顿。宁可利用 30 s 的时长上限留出空隙,也不要删减停顿;绝不要通过放慢语速来实现。
  • 强调。 每行着重强调的一两个词(数字、转折词、结论)来自脚本的舞台调度表。将它们作为每行单独的 instruct 传入。
  • 语气。 像日常交谈,略带笑意,不要像播音员。疑问句听起来要像真实提问,点睛句要带有好奇感,CTA 要温暖。旁白仍然不讲笑话;画面才负责逗趣。
  • 克隆模型(无指令)。 使用克隆音色(ref_audio + ref_text,Base 模型)时,可调节的手段是文本和录制效果。通过标点写出停顿(列表项之间用句号,简短问句单独成句)。使用多个种子生成一条连续录音(SEED_BASE、takes_per_line),选出目标词语音调变化最明显且 ASR 达到 0.9 或更高的一条;若某行听起来平淡,就单独重录(ONLY=l4_peak),并在句子边界处拼接。只克隆你有权使用的音色。
  • 一次性生成整篇脚本能保持韵律一致:生成一条录音,用 split_take.py 按行切分,然后在 episode.json 中将 "gap": 0。如果用户更喜欢按场景生成,也可以。
  • 完整录制前,先向用户播放前三行:ONLY=l1_hook,l2_...,l3_... narrate.sh ...。

字幕和时间安排

在 papercut/ 中,episode.json 包含 scenes 后:

python3 $PAPERCUT_LIB/tools/build_vo.py     # public/vo/voiceover.wav, public/vo/captions.json, src/plan.json
python3 $PAPERCUT_LIB/tools/timing_md.py    # Timing section of STORYBOARD.md

captions.json 是 Remotion 的 Caption[];场景边界取自单词时间戳;合成时长为 plan.json 的 durationInFrames。build_vo.py 会标记时长不足 1.2 s 的场景。如果没有库,请使用 Remotion 字幕技能(whisper.cpp)或任何能返回单词时间戳的语音转文本工具转写 WAV。

字幕要像撕下来的标签一样,每个词一张;每页 1-3 个词,语速为每秒 3.5-4 个词(../papercut-explainer/references/style-guide.md,第 11 和第 13 节)。

交接

接下来是 papercut-build(占位内容、场景、声音、渲染)。它会读取 src/plan.json 和 papercut/STORYBOARD.md 的 Timing 部分。之后若更改任何语音,都要重新运行 build_vo.py 和 timing_md.py;随后场景缓存会重新渲染所有内容。

评论

支持 Markdown