Skip to content

Latest commit

 

History

History
209 lines (151 loc) · 16.7 KB

script.md

File metadata and controls

209 lines (151 loc) · 16.7 KB

脚本与配音

文案先负责把事情讲清楚,再成为制作的时间骨架。先确定问题、解释路径与章节推进,通读全文检查因果和语气;确认内容后再处理字幕、读法与配音时序。本文说明唯一源稿、多语言与配音的写法。

1. 脚本文件

人类阅读和逐句校对通过 script-review.md 的导出稿与意见记录进行。明确确认前不调用配音;主语言定稿后翻译。源稿只维护下面这一份,不另建手工同步的旁白全文。

先写自然连贯的正文,再拆制作字幕。导出的交审稿先给连贯阅读视图,再给带句号的逐句表;两者都由 script.js 生成,不新增一份手工维护的正文。按 F12 独立设计语义停顿、连读和专名读法;不要为了满足字幕长度把解释写成碎句。音色、断句与读音用实际代表段试听,不能只依据 TTS 参数或 ASR 字面吻合。

按 F13,陌生或历史题材的开场先交代对象是什么、观众为何值得了解、所处年代和本片路线;新版对照注明具体产品、版本与同一任务。背景服务于理解,不扩成漫长编年史。

按 F14,连贯文案只包含会被说出的正文。片尾名单在 project.json 的 credits,由片尾场景读出来;时间线用 ['credits', null, { pause: 8, credits: true }] 保留无旁白片尾。不能把“策划、模型、开源链接”或“片尾只显示……”放进 TTS。校对导出中若列出静默 cue,须明确标“无旁白”,不混进正文段落。

脚本在 src/js/script.js,浏览器与工具共用同一份。结构:

const RAW = [
  {
    id: 'open', chap: null, lead: 0.8, tail: 0.4,
    cues: [
      ['o1', { zh: '一个 Lua 脚本,写完了', en: 'A Lua script. Finished.' }, { gap: 0.55 }],
      ['o2', { zh: '要交给别人运行,对方得先装好 Lua', en: 'To run it, the other person needs Lua installed,' }, { gap: 0.3 }],
      ['oT', null, { pause: 3.0 }],
    ],
  },
  {
    id: 'what', chap: ['02', { zh: '它做什么', en: 'What it does' }], lead: 2.3, tail: 0.5,
    cues: [ … ],
  },
];

场景

字段 含义
id 场景号。场景文件里用 scene('<id>', …) 实现它
chap [编号, 标题],有章节卡;null 表示没有
lead 场景开始到第一句旁白之间的时间,章节卡就放在这段时间里(常用 2.3 秒;没有章节卡时 0.8–1.0 秒)
tail 最后一句旁白结束到场景结束之间的留白(缺省 0.6 秒)

cue:[句号, 字幕, 选项]

部分 含义
句号 全片唯一。习惯上每个场景用一个字母作前缀:o1、a3、h17
字幕 显示在画面底部的文本。*词* 标出术语(字幕上显示为强调),第一次出现时画面要有它的注解(scenes.md 第 7 节);只为加重语气的词不标。多语言时写成 { zh: '…', en: '…' }
tts 送去合成的文本。缺省时由字幕按读法表换算(见第 4 节)。也可写成 { zh, en }
gap 这句结束到下一句开始的停顿,缺省 0.3 秒。可写成 { zh, en }
pause 这一条不是旁白,而是纯画面的停顿(标题、转场),值为秒数;字幕写 null

2. 写法

交审前沿同一个具体例子通读:开头的问题是否值得回答,观众能否跟上「输入 → 状态变化 → 结果」,转折是否来自已取证的条件或反例,结尾是否回答开头并说明边界。章与章之间要有尚未回答的问题推动;能删掉而不损失解释的背景或术语,优先删掉。不要为套用「钩子—转折」结构制造夸张或未经证实的因果。

  • 每条制作字幕不超过一行:中文不超过 26 个字宽(汉字算 1,拉丁字母与数字算 0.5),英文不超过 44 个字宽(约 88 个字符)。上限在 project.json 的 check.caption_width 里按语言设定;scan.js 另量实际宽度。一个自然口播句可跨多条字幕,因果、条件和转折保持完整。
  • 单条非静默 cue 不超过 6 秒(check.max_cue_seconds)。超过时按语义边界拆 cue,连读处安排相应 gap;不强行把长句改成互不衔接的短句。
  • node kit/tools/stats.js <视频> 逐章给出语速、最快 cue、最长 cue、过快和停顿过短的候选。候选再用代表段试听判断,不把速度数字当作口播质量。
  • 停顿是节奏的一部分:结论句之后留 0.6 秒以上;一个场景里换话题的地方留 0.7–1.1 秒;镜头要移到下一站时,把上一句的 gap 留够镜头走完的时间。
  • 开头 5 秒要有钩子:一个具体的现象、一个反差、一个问题。
  • 语体见 standards.md 第 5 节。

3. 多语言

缺省只做中文。策划者原话(2026-10-24):

另外, 之后视频默认只有中文.

需要英文版的片子在片单条目(或系列)的 languages 写明 ["zh", "en"],project.json 随之一致;此前的双语片已在片单上逐条写明。本节以下各条适用于有英文版的片子。

  • 以中文为底本:先定稿中文,再按中文的语气与用词译成其他语言。译文写成该语言里自然、克制的句子,不逐字对译。新增第三种语言时同样从中文译,不从英文转译。
  • 各语言的句号一一对应、数量相同;时长各不相同,时间轴各自排布。
  • 语言的选择:浏览器取地址里的 ?lang=,工具取 --lang;script.js 里的 pick() 把 { zh, en } 取成当前语言的值。
  • 画面里的文字用 tr('中文', 'English');时间点用 T('c5', { zh: '读', en: 'reads' }) 按语言取词。场景代码只有一套。
  • 版面先按较长的那种语言排(通常是英文),再看另一种。
  • 每种语言各有一份 src/js/timing.<语言>.js、audio/<语言>/、out/<语言>/,成片文件名带语言。
  • 字幕内嵌在成片里:字幕条由引擎渲染进画面,各语言的成片自带本语言的字幕,交付与投稿不依赖外挂字幕文件;finish.js 另导出同文同步的 .srt,只是附属文件。
  • 只做一种语言的片子把 languages 写成 ["zh"],脚本里的字幕直接写字符串。

4. 读法

字幕写产品的正式拼写;读法统一放在 script.js 的 SAY 表里,按语言各一组正则替换,长词写在前面:

const SAY = {
  zh: [ [/luainstaller/g, 'lua installer'], [/月相/g, '月象'], [/SHA-256/g, 'S H A 二五六'] ],
  en: [ [/luainstaller/g, 'Lua installer'], [/\bluai\b/g, 'lua-eye'], [/\bELF\b/g, 'E L F'] ],
};

已知的规律:

  • 连写的英文专名常被读错或被逐字母拼读。luainstaller 会被读成「low installer」,拆成 lua installer 才对;MyISAM 要写成 My ISAM。
  • 多音字换成同音的单音字:数据「行」会被读成 xíng,合成文本里换成「航」(「执行」「进行」除外);「月相」换成「月象」。
  • 缩写要逐字母读的,字母之间加空格:S R lua、L G P L。
  • 版本号、选项名写成读得出来的样子:5.1 到 5.5 → 五点一到五点五;--file → file 选项(英文 dash dash file)。

读法拿不准时先试再定:

node kit/tools/tts_probe.js <视频> --lang zh "luainstaller 是一个工具" "lua installer 是一个工具"

它把每种写法各合成一句,用语音识别回听,并列出词边界。音频留在 audio/probe/,可以直接试听。

5. 合成

node kit/tools/tts.js <视频>            # 全部语言
node kit/tools/tts.js <视频> --lang en  # 只做英文
  • 用 edge-tts 逐句合成,取回每句的时长与词边界,写成 src/js/timing.<语言>.js(入库),并打印各场景的起止时刻与总长。需要联网。
  • 音色与语速在 project.json 的 voices、rates 里按语言设定。缺省音色:中文 zh-CN-YunyangNeural,英文 en-US-AndrewNeural。语速写成 "+5%"、"-4%"。Yunyang 在 −4% 时约每秒 5.3 字(含标点的合成文本口径)。
  • 以(音色、语速、文本)的哈希做缓存,放在 audio/<语言>/(不入库)。改了哪句只重新合成哪句;脚本里删掉的句子,音频一并清掉。
  • 改了 script.js 的任何文本之后必须重新运行 tts.js,否则时间线用的是旧时长。
  • 换一台没有缓存的机器时,tts.js 会重新合成全部句子。在线服务的输出可能随时间变化,时长随之略有不同;画面的时间点都由 T() 推出,会自动跟着走,但已渲染的画面与已混好的声音要重做。

6. 时间点:T()

T('c5')              // c5 这句开始的时刻
T('c5', '读')        // c5 里「读」字被读到的时刻
T('c5', '读', -0.2)  // 同上,再提前 0.2 秒
T('c5', { zh: '读', en: 'reads' })   // 多语言
Tend('c5')           // c5 结束的时刻
  • 词在合成文本里找(引擎先用 SAY 表把词换成读法再找),取首次出现的位置。同一句里一个词出现两次、想取第二个时,换一个只出现一次的相邻词。
  • 查某句可用的词与各自的时刻:node kit/tools/timeline.js <视频> c5。
  • 找不到词时页面日志里有 word not in cue,scan.js 把它报为 PAGE 错误。
  • 时间点一律写成 T(句号, 词) 的形式,不写死秒数:旁白改了,画面才能自动跟着走。

7. 回听

混音之后:

node kit/tools/asr.js <视频>

用 Whisper 转写仅旁白的音轨,逐句并排打印「合成文本」与「听到的文本」。读法:

  • 同音错字、英文大小写与拼写偏差属于识别误差,不算错。
  • 要看的是:有没有漏词、有没有把英文单词逐字母拼读、数字读法是否正确。
  • 多音字读没读对,ASR 查不出:Whisper 把 cháng、zhǎng 都转成「长」。对着交审稿的「多音字清单」(script-review.md 第 2 节)逐条用耳朵听(F12)。
  • 读错了就改 SAY 表或该句的 tts,重新合成、重新混音、再回听。

8. 音色与响度

不同音色的峰值与均值之比差别很大(Yunyang 与 Andrew 相差约 7 dB)。混音按响度对齐旁白,不按峰值归一;成片增益按实测响度计算。两种语言的成片因此响度一致。

9. 音色记录

9.0 怎么选

策划者原话(2026-10-24):

原则上, 每个视频和上一个之前配音音色, 除非特别说明.

之后,视频加入固定流程, 定稿后, 选取合适, 尽可能和之前不同的10个配音(5中文5英文), Demo片段, 我来选择具体用哪个, 然后到正式制作. 除非我特别说明自己选择配音, 不要问我.

文案定稿之后,给出 5 个配音候选供策划者选:用本片同一段代表句做成 Demo,音色契合本片的对象,尽可能和前几部不同;读法平实清楚,不做史诗腔。默认只有中文;片子有英文版时,英文另给 5 个。策划者原话(2026-10-24,P67,更正了 P65 的误读):「这三个都不好 这是配音, 要五个, 我说的是配乐史诗感」。「3 个调调」与质感、史诗感说的是配乐,见声音第 2 节。选定后再合成全片。策划者在会话里直接点名音色时,就用点名的,不再做 Demo,也不再问。没有这句特别说明时,不要问「用哪个音色」。

上一部已选定的音色(下一部避开,除非策划者要求沿用):

日期 片子 中文 英文 模型
2026-10-24 《256 秒搞懂 SSH》(已选定,尚未合成) Chinese (Mandarin)_Radio_Host(电台男主播) Friendly_Person(Friendly Person) MiniMax speech-2.8-hd,语速 1.0
2026-10-24 《一个数据库引擎是如何实现的?——从 MyISAM 说起》新版 Chinese (Mandarin)_Gentleman(温润男声) (只有中文) MiniMax speech-2.8-hd,语速 1.1

再往前已进成片的,同样不要当作默认可重复:Tmux 用过 Chinese (Mandarin)_Reliable_Executive 与 English_Trustworthy_Man;HTTP 状态码用过 Chinese (Mandarin)_News_Anchor 与 English_ConfidentWoman。停用音色见下表,不再进入这 10 段。

9.1 试听库

选音色之前先真的听一遍:

node kit/tools/voices.js                       # edge-tts 与 MiniMax 的全部中英文音色
node kit/tools/voices.js --engine minimax --lang zh --only Mandarin   # 只看一部分
node kit/tools/voices.js --zip                 # 另打成 out/voices-<日期>.zip,带评价表,交给策划者离线试听

它用同一段范例文本(写在 kit/tools/voices.py 开头),把本机能用的每个音色各合成一遍,放进仓库根的 out/voices/(不入库),并生成试听页 out/voices/index.html:每个音色一行,可以逐个播放或整组连续播放,列出时长、语速和下表里已有的评价。范例文本覆盖配音最容易出问题的几样:解释句与长句、年份、英文缩写与版本号(HTTP/3、QUIC)、数字(404、500)、问句与结论句。语速一律用引擎缺省值(edge +0%、MiniMax 1.0),只比较音色本身;片子里实际用的语速记在各片的 project.json。

音色由服务方提供,列表会变:以试听页上实际列出的为准,合成失败的标「不可用」。MiniMax 的音色列表接口只列出少数英文音色,voices.py 另带一份实测可用的英文音色 id。

9.2 评价

选音色前先看这张表。标「停用」的不再选用(F17);其余评价针对当时那一片的气质或整体配音语气,再用时照样按 F17 先试听代表段。策划者听过试听库之后的评价也记在这里,原话照录、注明日期。

音色 引擎 用在 WaterRun 的评价 以后
Chinese (Mandarin)_Radio_Host MiniMax speech-2.8-hd 《256 秒搞懂 SSH》中文,语速 1.0。2026-10-24 从试听库点选,尚未合成 点名使用,没有另写听感 本片用。下一部避开,除非特别说明沿用
Friendly_Person MiniMax speech-2.8-hd 《256 秒搞懂 SSH》英文,语速 1.0。同上 点名「Friendly Person」,没有另写听感 同上
English_Aussie_Bloke MiniMax Web 登录英文(语速 1.08) 「英文配音很一般,之后不要用这个音色了」(2026-10-20,P38) 停用
Chinese (Mandarin)_Reliable_Executive MiniMax Tmux 中文、OpenCart 中文 配音太「懒洋洋」(2026-10-19,P29) 评价针对整体语气,未停用音色;再用须先试听
English_Trustworthy_Man MiniMax Tmux 英文 同上(P29) 同上
Chinese (Mandarin)_News_Anchor MiniMax PostgreSQL 试听(语速 0.95);HTTP 状态码中文(语速 1.2) PostgreSQL:「这个配音太老气了,换一个」(2026-10-19)。HTTP 状态码:整片看片后「没问题了」(2026-10-21),没有单独评价音色 两次的语速与片子的气质都不同,评价也不同;再用须先试听
female-yujie MiniMax PostgreSQL 试听 「太妩媚」 未用;针对 PostgreSQL 的气质
Chinese (Mandarin)_Male_Announcer MiniMax PostgreSQL 中文(语速 1.1);MyISAM 新版「史诗·纪录片」调调试听(语速 1.1) PostgreSQL:试听成片后「都没问题」(2026-10-19)。MyISAM:与 Lyrical_Voice、Wise_Women 一起「这三个都不好」(2026-10-24,P67),评价针对按史诗腔挑的读法 可用,先试听
Chinese (Mandarin)_Lyrical_Voice MiniMax speech-2.8-hd MyISAM 新版「抒情·讲故事」调调试听(语速 1.25) 「这三个都不好」(2026-10-24,P67) 未用;评价针对史诗腔的挑法,再用须先试听
Chinese (Mandarin)_Wise_Women MiniMax speech-2.8-hd MyISAM 新版「阅历·知性」调调试听(语速 1.1) 同上 同上
Chinese (Mandarin)_Gentleman MiniMax speech-2.8-hd MyISAM 新版中文,语速 1.1 5 个候选(另有 male-qn-jingying-jingpin、Chinese (Mandarin)_Sincere_Adult、female-chengshu-jingpin、Chinese (Mandarin)_Mature_Woman)中点选,没有另写听感 本片用。下一部避开,除非特别说明沿用
male-qn-jingying(精英青年) MiniMax Web 登录中文(语速 1.05) 没有单独评价 可用,先试听
English_ConfidentWoman MiniMax HTTP 状态码英文(语速 1.25) 整片看片后「没问题了」(2026-10-21),没有单独评价音色 可用,先试听
zh-CN-YunyangNeural edge-tts 缺省中文音色,早期片子 没有单独评价 先在试听库里听
en-US-AndrewNeural edge-tts 缺省英文音色,早期片子 没有单独评价 先在试听库里听