上海话配音字幕成片
概述
输入:一个目录里的若干短视频(多为纯画面、无原声的手机竖屏素材)。
输出:每段一条成片 mp4(= 原画 + 上海话配音音轨 + 烧入画面的上海话字幕),另附该段的上海话配音 mp3 与上海话 srt。
适配场景:任意行业的推广素材要发上海话区(上海及吴语片区)时,批量做"上海话版"——门店、餐饮、美容美发、教育、电商、知识付费、产品推广、个人 IP 等;素材类型不限,只要是无原声的短视频。技能本身不预设行业口径,旁白写什么完全由当次素材与用户要求决定。
> ⚠️ 与粤语版的关系:本技能是「粤语配音字幕成片」的独立兄弟版,仅把配音引擎从 edge-tts(粤语)换成 Azure 语音(上海话 wuu-CN),其余逻辑(字幕样式、原声处理、BGM、拼合集、可视化菜单)完全一致。两套技能目录、脚本互不干扰,粤语版保持原样。
一、环境准备(Windows)
- ffmpeg:用 Python 包自带,省得找下载链接:
powershell & <venv>\Scripts\pip.exe install imageio-ffmpeg
二进制路径由imageio_ffmpeg.get_ffmpeg_exe()得到。该 build 已含libass(ass/subtitles过滤器)与libx264,足够烧字幕;但不含 ffprobe——时长/分辨率要靠ffmpeg -i的 stderr 正则解析。 - 上海话 TTS(Azure 语音):
pip install azure-cognitiveservices-speech。上海话(吴语)声线不在免费 edge-tts 里,必须用 Azure 语音服务:
- 女声wuu-CN-XiaotongNeural(默认推荐)
- 男声wuu-CN-YunzheNeural
- ⚠️ 这两个是 Azure 官方吴语 voice;若运行时报「voice 不存在」,到 Azure 语音库核对当前名称再填入 config 的voice字段。 - Azure 密钥:需要 Azure 订阅里的「语音服务」资源,拿到 密钥(key) 和 区域(region,如 eastasia / southeastasia / westeurope)。填进 config 的
azure块,或设环境变量AZURE_SPEECH_KEY/AZURE_SPEECH_REGION。没有 key 无法合成配音。 - 中文字体:烧中文字幕必须给 CJK 字体,否则方块。Windows 自带
C:\Windows\Fonts\simhei.ttf(黑体)。
二、关键实测参数(务必先算稿长)
- 上海话 TTS 语速 ≈ 3.0 字/秒(默认语速,含标点停顿);可通过 SSML
rate微调(如+8%≈ 3.24 字/秒)。 - 稿字预算 ≈ 视频秒数 × 3.2(配
rate=+8%)。旁白只能短不能长:短了补尾静音无所谓,长了要么加速(伤听感)要么被截断。 - 例:16s 视频 ≈ 50 字;82s ≈ 260 字;28s ≈ 90 字;24s ≈ 76 字;17s ≈ 55 字。
- 逐句合成后拼接,靠每句尾自然静音当停顿,不必另插空白;如需更清晰停顿再加 0.2–0.35s 静音。
三、字幕样式("大 + 红字白边 + 黑体"花字感)
生成 ASS(比 SRT+force_style 稳,PlayRes 可控):
[Script Info]
ScriptType: v4.00+
PlayResX: <视频宽>
PlayResY: <视频高>
WrapStyle: 0
ScaledBorderAndShadow: yes
[V4+ Styles]
Style: Default,SimHei,<fs>,&H000000FF,&H000000FF,&H00FFFFFF,&H80000000,-1,0,0,0,100,100,0.6,0,1,5,3,2,<ml>,<ml>,<mv>,1
fs(字号)= 视频宽 × 0.080(够大;一屏约 10–12 字,长句自动折成 2 行)- 位置:
Alignment=2(底对齐)+ MarginV 抬升,mv(MarginV)= 视频高 × 0.35 → 中下偏底(1080×1920 约 672px、720×1280 约 448px)。⚠️ 善思兄要求中下偏底,不要贴底;如需贴底则mv=高×0.097。 ml(左右安全边距)= 宽 × 0.05,防出安全区- 颜色:
PrimaryColour=&H000000FF(红)、OutlineColour=&H00FFFFFF(白边)、BackColour=&H80000000(半透明黑阴影兜底) Bold=-1、Outline=5(白描边)、Shadow=3(黑阴影)→ 花字感、任何底色都清晰- 文案规范:旁白稿用【上海话口语汉字】(如「头发缝」「汏头」「交关」「呒没」「转来」「阿拉」);字幕显示时去标点(
strip_punct,含全角括号「」『』()()【】等),但 TTS 输入保留标点以保停顿语感。 - ⚠️ 字幕要烧「原味沪语」,绝不可雅化成普通话:成片字幕=旁白稿原样(去标点后),像「蛮嗲」「好伐」「老明显个」「覅」「一眼勿出」这种上海话特色词必须原样保留在画面上,不要翻译成「很好」「好吗」「很明显」「不要」「看不出」——这正是上海话版跟普通话版的区别,也是本地味道的来源。
- 音量:配音用
-af "volume=1.8,alimiter=limit=0.99"放大,「再大一点」要求,alimiter防削波。
> ★ 以上样式全部可配置:通过 config 的 subtitle 块自定义,给用户自行设计空间——
> json
> "subtitle": {
> "color": "red", // 预设 red(红字白边,默认) / white(白字黑边) / yellow(黄字黑边) / custom
> "custom_color": "&H000000FF,&H000000FF,&H00FFFFFF,&H80000000", // color=custom 时填(主,次,描边,阴影)
> "font_scale": 0.08, // 字号=屏宽×此值(越大字越大)
> "font": "C:/Windows/Fonts/simhei.ttf",
> "font_name": "SimHei",
> "position": 0.35 // 距底比例(越小越贴底)
> }
>
> 也可在单个 clips[] 里覆盖(只对那一条生效)。不设则全部走上面默认值。
四、压片命令(烧字幕 + 加音轨)
关键坑:Windows 路径的冒号在 ffmpeg filter 里要转义很麻烦 → 直接把工作目录设为 cwd,用相对文件名:
# cwd = 工作目录(内含 subs.ass 与 fonts/simhei.ttf)
ffmpeg -y -i <原视频绝对路径> -i narration_fit.wav `
-vf "ass=subs.ass:fontsdir=fonts" `
-map 0:v -map 1:a `
-af "volume=1.8,alimiter=limit=0.99" `
-c:v libx264 -preset medium -crf 20 -pix_fmt yuv420p `
-c:a aac -b:a 192k -movflags +faststart <输出.mp4>
-af "volume=1.8,alimiter=limit=0.99":配音音量放大 + 防削波(成片与 mp3 都加)。fontsdir=fonts指向放着simhei.ttf的目录,确保 libass 找得到中文字体。- 画面分辨率不变(竖屏保持竖屏)。
五、时长对齐(防"音比画长")
- 逐句合成 → 转 wav → 量每句时长 → 求和
total。 total > 视频时长:atempo = min(total/vdur, 1.30),并加-t <vdur>兜底。total ≤ 视频时长:apad -t <vdur>补尾静音到视频长度。- 字幕时间轴按每句时长累加;句中按标点切分并按字数比例分配时间;末条
end ≤ vdur-0.05。
六、输入契约与提问规范(★必须遵守)
输入至少要有一样(两样都有最准):
| 输入 | 说明 |
|---|---|
| 视频素材(可选) | 有视频 → 抽关键帧看懂画面,据此写稿 |
| 文字说明(可选) | 没有视频也能做:只给 行业 / 场景 / 主题 / 目标时长 / 品牌名与引导语,照样写稿 |
看不懂、拿不准时——必须问,不许瞎猜
- 画面模糊、看不清是什么行业/产品/场景 → 先问,别硬编。
- 旁白口径不确定(是否点品牌名、是否引导到店/私信、面向哪种客户)→ 先问。
- 时长与稿量不确定 → 按"秒数×3.2"先算,落差大再确认。
- 原声怎么处理不确定 → 给选项问(抹掉/保留/压低做背景)。
提问方式:给选项让用户选,最后一项固定"其他"
用选择式提问(如 AskUserQuestion),每题给 2–4 个具体选项,让用户点选即可:
- ✅ 好:「这条片主要想讲:A 门店环境 / B 产品细节 / C 顾客案例 / 其他」
- ❌ 差:空泛地问「你想讲什么?」——用户还得自己想,等于没帮上忙。
「其他」留自由输入,兜住选项没覆盖的情况。能一次问清就一次问完(单次最多 4 题),别来回挤牙膏。
六之二、写稿方法论(★技能自带能力)
有视频就看懂画面再写;没视频就按用户给的行业/场景写。按下面五步出稿:
1. 先定三件事(拿不准就问,见上)
- 说什么:主题(门店/产品/案例/知识/日常…)
- 对谁说:客户画像(街坊、年轻人、求职者、宝爸宝妈…)
- 要他做什么:行动引导(私信/到店/留言/关注/无引导)
2. 结构:钩子 → 内容 → 引导
- 首句当钩子:3–6 秒内抓住注意力。用提问、反差、痛点开头。
- 提问式:「侬晓得戆度哪能……」 反差式:「迭个物事看看蛮普通……」 痛点式:「越来越疏,越来越阔……」
- 中段给实料:按画面/卖点分点讲,一句一个信息,别堆砌。
- 尾句给引导:一句行动号召(有品牌名就点品牌名)。
3. 语言:说人话、说上海话
- 口语化,写出来要顺口、听着不别扭;不写书面腔("本产品采用……" ✗)。
- 用上海话口语汉字(带特色词,才是上海味道)——下面分六类,成片里优先用前四类(语气/程度/夸赞/日常),把上海味道做足;第五类挑干净的词用;第六类是禁区,门店成片绝不碰。
- ① 句尾语气词(上海话灵魂,成片必带):
- 「伐」= 不/吗(问句尾,例:「晓得伐」「好看伐」「要伐」)
- 「好伐」= 好吗、行吗(征求意见、软糯,例:「想了解就私信阿拉,好伐」)
- 「一刚」= 居然、竟然(句尾惊叹语气词,上海话灵魂,例:「效果自然一刚!」)
- 「噢哟」= 哎呀、感叹(例:「噢哟,迭个灵得来」)
- ② 程度词("很"的 N 种说法,别只会写"很"):
- 「老」= 很(老明显个/老嗲/老灵)
- 「邪气」= 非常(邪气自然)
- 「交关」= 很多·非常(交交关关=非常多)
- 「瞎」= 很(瞎灵/瞎嗲)
- 「穷」= 很(穷开心)
- 「来得」= 挺·很(来得个好看)
- 「勿要忒……喔」= 好到无以复加(顶级夸法,例:「勿要忒灵光喔」)
- ③ 夸赞 / 正面(适合夸效果、夸门店,成片多用):
- 「嗲」= 好、美、赞(蛮嗲/老嗲)
- 「灵 / 灵光」= 好、行(蛮灵/灵光/勿要忒灵光喔)
- 「登样」= 体面、样子好(例:「弄好登样得来」)
- 「挺刮」= 到位、讲究(例:「做得挺刮」)
- 「腔调」= 有派头、有风格(例:「侬真有腔调」)
- 「弹眼落睛」= 惹人注目、吸睛(例:「效果弹眼落睛」)
- 「杀根」= 顶呱呱、最到位(例:「做得杀根」)
- 「适意 / 写意」= 舒服(例:「坐牢适意」)
- 「上路」= 靠谱、得体(例:「迭个师傅老上路」)
- 「来三 / 来塞」= 行、可以(否定「勿来塞」=不行)
- ④ 人称 / 时间 / 日常高频(口播顺口):
- 人称:阿拉(我们)/侬(你)/伊(他·她)/㑚(你们)/覅(不要)/勿·弗(不)
- 时间:今朝(今天)/明朝(明天)/辰光(时候)/日脚(日子,例「日脚蛮好」)/早浪向(早上)/夜到(晚上)
- 日常:白相(玩)/夜饭(晚饭)/难板(偶尔)/豪少(快点)/便当(容易)/一眼眼(一点点)/木佬佬(很多很多)/行情行事(一大堆)/晓得伐(知道吗)/勿搭界(没关系)
- ⑤ 状态 / 形容(讲体验,挑干净的词):
- 笃悠悠(悠闲安稳,例「弄好笃悠悠」)/清爽(清楚干净)/密密层层(茂密)/望上去(看上去)/汏头(洗头)/头发缝(发缝)/转来(回来·恢复)/呒没(没有)/哪能(怎么)
- ⑥ ⚠️ 禁区(门店成片绝不碰,粗俗或贬损人):册那、赤佬、小赤佬、戆大、寿头、洋盘、瘟生、阿木林、猪头三、脱底棺材、十三点(作骂人时)、卖野人头、捣浆糊、拆烂污、撬边模子、小巴子、下作胚、拿伊做脱 等。
- 注:「十三」善思兄指定保留——只取轻声俏皮的嗲怪语气(如「迭个小囡十三得来」),绝不作骂人;其余粗俗词一律不上字幕。
- ⚠️ 写稿时主动往稿里塞这些特色词,字幕一看就是上海话;能用「蛮嗲/好伐/一刚」就别写「很好/好吗/居然」。
- 少量英文术语可以(食材名、品牌英文名),但别整句英文。
4. 控字数(关键,写前先算)
- 预算 = 视频秒数 × 3.2 字(配
rate=+8%)。 - 只短不长:短了自动补尾静音;长了要被加速(伤听感)或截断。
- 拿 16s 视频举例:预算约 50 字 → 拆 4–5 句,每句 10–12 字最舒服。
5. 按画面切句(有视频时)
- 一个画面/一个动作配 1–2 句,别让一句话跨太多镜头。
- 关键画面(前后对比、产品特写)要给足句子,别一带而过。
6. 合规自检(写完后过一遍)
- 涉及医疗/药品/保健品/金融/教育/美容功效等行业时,按使用者行业与平台规则把关——不写疗效、收益、升学率、绝对化用语("最""第一""包治")。
- 技能不预设禁用词表,只提醒:发布前由使用者核对自己行业的红线。
六之三、原声处理(★技能自带能力)
素材本来有原声(说话声、环境音、BGM)也能用——配音时按需要处理原声:
| 模式 | 值 | 效果 |
|---|---|---|
| 抹掉原声(默认) | "original_audio": "off" |
成片只有上海话配音,原声完全去掉 |
| 保留原声 | "original_audio": "keep" |
原声 100% + 上海话配音并轨 |
| 原声压低做背景 | "original_audio": "duck" |
原声压到 20% 当背景,上海话配音为主 |
- 可写在全局(对所有片段生效)或单个片段里(覆盖全局)。
- 素材本身无音轨时自动按 off 处理,不会报错。
- 脚本用
-map 0:v -map 1:a只取画面+新配音实现"抹掉";keep/duck 走amix混音。 - 拿不准用户要哪种 → 给上面三个选项问。
- ⚠️ 实测要点:部分素材的音轨是空轨/近乎静音(实测见过 -91dB 的纯静音轨,也有 -26dB 的正常原声)。空轨素材下三种模式听感相同,不是功能失效——用
volumedetect看原素材mean_volume即可判断;或看输出码率(off≈14kb/s,duck/keep 明显更高)。
6.4 字幕样式 / 声线 / BGM 选项菜单(可选提问,★必含「原生默认」项)
生成视频前,若用户没明确指定样式/声线/BGM,可主动用 AskUserQuestion 给一个选项菜单,让用户自行设计;每个选项菜单都必须含「原生默认」项——不选就走下表默认配置,外观和旧版完全一致。
| 可选项 | 菜单选项 | 原生默认(不选时) |
|---|---|---|
| 字幕颜色 | 红字白边 / 白字黑边 / 黄字黑边 / 原生默认(red) | red(红字白边+黑阴影) |
| 字号 | 大 / 中 / 小 / 原生默认 | 屏宽×0.08(大) |
| 字体 | 黑体 / 用户指定字体 / 原生默认 | 黑体 SimHei |
| 字幕位置 | 中下 / 更贴底 / 原生默认 | 中下偏底(position=0.35) |
| 声线 | 女声 / 男声 / 原生默认 | 女声(wuu-CN-XiaotongNeural) |
| BGM | 无 / 轻柔(女) / 动感(男) / 原生默认 | 无 BGM |
- 各项映射到 config 的
subtitle/gender/bgm.by_gender(见 §三、§8.2、§8.3)。 - 原生默认 = 不填这些字段时脚本的自动行为:红字白边、中下偏底 0.35、女声、无 BGM。
- 用户挑了就写进 config 覆盖默认;没挑就不写,脚本走原生默认。
- ⚠️ 菜单提问一律用【普通话】:用这个技能的人(运营/店主)通常不会上海话也不会粤语,菜单是给他看的——绝不能用方言词或方言短句来问;选项标签、说明全部用简体普通话、通俗直白(写「字号要多大」,不要写「要几大」)。方言只用在成片内容里(旁白稿 + 字幕),不要用在跟用户的交互上。
-
提问时把「原生默认/(默认)」放在第一项并标注,用户可直接选默认跳过;用户一次没答完的项,不要反复追问第二遍,缺的项直接走原生默认,最后一句说明「其余按默认,要改随时讲」。
-
菜单做成可视化预览:给用户看选项时,优先用内联可视化图(手机预览 + 颜色/字号/字体/位置四项的字形样例 + 声线/BGM 一行)直接画出每项字幕长什么样,比纯文字卡片更直观;用户不读说明也能挑。可视化图里把「原生默认」项用醒目标记(如紫色框)标出。预览样句用上海话,如「头顶头发缝越来越阔」。
七、工作流
- (有视频)列素材目录 →
ffmpeg抽关键帧 → 多模态看懂画面;
(无视频)读用户给的行业/场景/时长。 - 拿不准先按"提问规范"发选项问(含原声如何处理);确认后按"写稿方法论"写上海话旁白稿。
- 确认 config 含
azure.key/azure.region(或已设环境变量),跑scripts/dub_shanghainese.py(读 JSON 配置)生成 mp3/srt/mp4。 - 抽帧复核字幕渲染(红字白边/大小/位置/无方框);确认音轨(原声是否按要求处理)。
八、扩展能力
8.1 自动拼合集(compile 配置块)
把各段成片用 xfade 转场串成一条合集,可选加片头/片尾纯色文字卡:
"compile": {
"enabled": true,
"title": "品牌名_上海话合集",
"order": null,
"transition": "fade",
"transition_dur": 0.6,
"intro": {"enabled": true, "duration": 2.5, "text": "品牌名", "sub": "副标题", "color": "0x111111"},
"outro": {"enabled": true, "duration": 3.0, "text": "引导语", "sub": "补充行", "color": "0x111111"}
}
- 转场
transition可选:fade/dissolve/wipeleft/wiperight/slideleft/slideright/fadeblack/circleopen等(对应 ffmpegxfade的 transition 名)。 - 实现要点:①各段先
scale+pad+setsar=1+fps=30统一规格,否则 xfade 报尺寸不符;②用xfade叠画面、acrossfade叠声音;③offset按累计时长 − 转场时长递推。 - 片头/片尾卡用
lavfi color源 +drawtext生成。⚠️drawtext不吃fontsdir,字体必须给绝对路径(Windows 盘符冒号要转义成C\:/...),否则中文渲染成白色方框(已实测踩到)。脚本已按此处理。 - ⚠️⚠️ 更隐蔽的一坑:
drawtext的字体路径不能含非 ASCII 字符。若out_dir是中文名,沿用work/fonts/simhei.ttf这种带中文的路径会照样渲染成方框,而 libass 烧字幕却不受影响(所以字幕正常、只有卡片方框,极易误判为"卡片功能坏了")。判据:同样内容输出 PNG,方框版体积明显偏小。脚本已加_ascii_font_path():路径含非 ASCII 时自动把字体复制到纯 ASCII 临时目录再用。
8.2 背景音乐(bgm 配置块)
"bgm": {"file": "C:/music/bgm.mp3", "gain_db": -18}
- BGM 自动
-stream_loop -1循环铺满全长,按gain_db压低(默认 −18dB)后用amix与人声混合,不抢人声。 - 只作用于配音音轨(成片与导出的配音 mp3 都带 BGM)。
8.3 换声线(voice 字段)
| 声线 | 说明 |
|---|---|
wuu-CN-XiaotongNeural |
上海话女声(默认) |
wuu-CN-YunzheNeural |
上海话男声 |
改 voice 字段即可整批切换;也可只写 gender: female/male 让脚本自动选。
8.4 自动读视频分析画面(脚本内置,可选)
适用于「有视频、懒得自己写稿」:clip 只要给 file + title(不写 sentences),脚本会:
1. ffmpeg 均匀抽 vision.frames 帧;
2. 调视觉大模型(OpenAI 兼容接口,可接 OpenAI / DeepSeek / 通义千问VL / 智谱GLM-4V 等)看懂画面;
3. 自动写出带上海话特色词的旁白稿(按 §三 / §六之二 规范),继续走配音→烧字幕→拼片。
"vision": {
"key": "视觉模型API密钥",
"base_url": "https://api.openai.com/v1", // 各家填对应地址
"model": "gpt-4o", // 支持视觉的模型名
"frames": 6 // 抽帧数
}
- 也可在单个 clip 写
"script_hint"给视觉模型额外提示(如行业、要突出的点)。 - 缺
vision配置且 clip 没写sentences→ 脚本给清晰中文报错,不会瞎编。 - ⚠️ 无视频时不能自动:没视频就必须手动写
sentences或给文字说明(见 §六)。自动分析依赖画面帧,纯文字需求走手动写稿。 - ⚠️ 视觉接口非免费:需自备 key,且画面理解质量取决于所用模型——复杂画面(如多产品对比)建议仍人工看帧写稿,或先用
script_hint兜底。
九、容易踩的坑
- 抽关键帧拼图:单张 PNG 输出必须加
-frames:v 1 -update 1,否则报 "does not contain an image sequence pattern"。 drawtext(片头尾卡/水印)字体路径不能含中文:输出目录是中文名时,字体路径也会带中文 → 中文渲染成方框(libass 字幕不受影响)。脚本已自动转 ASCII 临时路径;手工写 ffmpeg 命令时也要注意,或直接把字体放 ASCII 目录。- 输出目录要先建:ffmpeg 不会自动建目录,写进不存在的目录报 "Could not open file"。
- 合规(交给使用者拿捏,技能不预设行业限制):本技能泛行业通用,不写死任何行业的禁用词表。旁白用词由当次素材所属行业与投放平台法规决定——例如医疗、药品、保健品、金融、教育培训、美容功效等在多数平台有专门限制(如不得宣称疗效、收益、升学率等),产出前须由使用者按自身行业与平台规则把关。技能只负责"配音准确、字幕规范、成片合规交付",不对内容做行业化删改。
- 本机有"批量删除确认"拦截(safe-delete hook):脚本里
shutil.rmtree(工作目录)会触发SAFE_DELETE_BULK_CONFIRM_REQUIRED并中断整个脚本(EXIT=1)。→ 不要 rmtree,改覆盖式写入(同名文件被-y覆盖即可)。 - Azure 配额/限流:免费层有并发与字符数上限,批量跑时某句可能超时/限流抛异常。→ 单条重跑(传单个 clip)即可,已成功的文件不受影响;多用付费层可提并发。
- 本机 PowerShell 工具 stdout 不回显 → 所有命令把结果写日志文件再 Read。
- Git Bash 在本机不可用(
dirname/which缺失)→ 一律走 PowerShell。
十、脚本用法
# 1) 准备配置 config.json(src_dir / out_dir / azure{key,region} / voice / rate / clips[];可选 bgm / compile)
# 2) 运行
& <venv>\Scripts\python.exe scripts\dub_shanghainese.py config.json
clips[].sentences 是逐句上海话旁白;脚本自动完成 配音→拼接→对齐→(BGM混音)→ass/srt→压片→(拼合集)。
⚠️ 运行前必须配好 Azure key(config.azure 或环境变量),否则合成配音这步会直接报错提示,不会产出成片。
十一、技能头像(品牌标识)
- 头像名:
沪语剪辑 - 规格:512×512 px,≤500KB,JPG/PNG(符合常见平台头像上传要求)。
- 获取:本技能包不含图片文件,头像在展示侧通过
iconUrl配置;需要时按下面的设计稿重新生成。 - 设计:深红主标题「沪语剪辑」+金色上海天际线(东方明珠/外滩钟楼/中式楼阁)+胶片播放键+声波,米白底、金色圆角边框。
- 用途:本技能在技能列表/介绍页的头像;也可作为上海话成片的片头署名或品牌角标直接引用该 PNG。