diff --git a/docs/sop/tts-narration.md b/docs/sop/tts-narration.md index 8e4c05d..a661a54 100644 --- a/docs/sop/tts-narration.md +++ b/docs/sop/tts-narration.md @@ -2,7 +2,8 @@ ## 工具 -- [MiniMax TTS](https://www.minimax.chat/) — AI 语音合成 +- [MiniMax TTS](https://www.minimax.chat/) — speech-2.8-hd 模型 +- API: `https://api.minimaxi.com/v1/t2a_v2` ## 流程 @@ -11,28 +12,71 @@ - 从脚本中提取旁白文字 - 添加标点控制停顿节奏 - 长句拆短,每句 < 30 字为宜 +- **每个场景单独生成一段 TTS**(便于后续对齐) ### 2. 音色选择 -- 根据视频类型选择音色: - - 宣传视频 → 沉稳大气的男声/女声 - - 知识点视频 → 清晰自然的讲解音色 -- 试听 2-3 种音色,选最匹配的 +| voice_id | 风格 | 适用场景 | +|----------|------|---------| +| vincent_wenxing_v1 | 闻星克隆声(偏年轻男声) | 机智流日报/产品视频 | +| presenter_male | 播音员男声(中性正式) | 品牌中性版本 | -### 3. 合成参数 +### 3. 合成代码 -- 语速:1.0x(默认),知识点视频可 0.9x -- 输出格式:WAV(高质量)或 MP3(轻量) -- 采样率:≥ 24000 Hz +```python +import requests, os -### 4. 后处理 +payload = { + 'model': 'speech-2.8-hd', + 'text': '旁白文本', + 'voice_setting': { + 'voice_id': 'vincent_wenxing_v1', + 'speed': 1.0, # 0.95-1.05 范围 + }, + 'audio_setting': { + 'sample_rate': 32000, + 'format': 'wav', # ⚠️ 必须用 wav,mp3 格式有解码问题 + } +} -- 检查发音准确性(专有名词、英文缩写) -- 裁剪首尾静音 -- 必要时手动分段,匹配画面时长 +r = requests.post('https://api.minimaxi.com/v1/t2a_v2', + headers={'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'}, + json=payload, timeout=60) -### 5. 注意事项 +resp = r.json() +if resp.get('data') and resp['data'].get('audio'): + # ⚠️ 关键:audio 是 hex 编码,不是 base64! + audio = bytes.fromhex(resp['data']['audio']) + with open('output.wav', 'wb') as f: + f.write(audio) + # 转 mp3 + os.system('ffmpeg -y -i output.wav -c:a libmp3lame -ar 44100 -q:a 2 output.mp3') +``` -- 中英混合文本可能发音不准,建议分开合成再拼接 -- 数字、日期建议写成中文("二零二六年"而非"2026年") -- 保留原始 WAV,最终渲染时再压缩 +### 4. 拼接(多段 TTS + gap) + +```bash +# 生成静音间隔 +ffmpeg -y -f lavfi -i anullsrc=r=44100:cl=stereo -t 0.8 -q:a 2 gap.mp3 + +# 拼接 +printf 'file s00.mp3\nfile gap.mp3\nfile s01.mp3\nfile gap.mp3\nfile s02.mp3\n' > concat.txt +ffmpeg -y -f concat -safe 0 -i concat.txt -c:a libmp3lame -ar 44100 -q:a 2 narration.mp3 +``` + +### 5. Silencedetect(找段落边界) + +```bash +ffmpeg -i narration.mp3 -af silencedetect=noise=-30dB:d=0.7 -f null - +# >1s 的静默 = 段落边界 +# 用于精确设置 Remotion Sequence 的 from/durationInFrames +``` + +### 6. 注意事项 + +- ⚠️ audio 字段是 **hex 编码**(`bytes.fromhex()`),不是 base64 +- ⚠️ 输出格式必须用 **wav**(mp3 有解码问题) +- MiniMax API key 分两种:sk-cp(Token Plan,推荐)和 sk-api(标准) +- 语速 speed: 产品视频用 0.98-1.0,日报用 1.0-1.05 +- TTS 输出偏轻,合并时需要 `volume=2.0` 增益 +- Fallback:`python3 -m edge_tts --voice zh-CN-YunyangNeural --text "..." --write-media output.mp3` diff --git a/docs/sop/video-production-pipeline.md b/docs/sop/video-production-pipeline.md index 1d88091..4cef1a6 100644 --- a/docs/sop/video-production-pipeline.md +++ b/docs/sop/video-production-pipeline.md @@ -1,55 +1,184 @@ # 视频制作全流程 SOP +> 基于 anet.sh 产品视频 20 轮迭代实战经验(5.85 → 8.18/10) + ## 流程概览 ``` -选题 → 脚本 → AI素材生成 → 语音合成 → 视频合成 → 渲染 → QA → 发布 +选题 → 脚本 → TTS 配音 → 视觉素材 → Remotion 排版 → 渲染 → 合并音频+BGM → 质检 → 上传 ``` ## 1. 选题 -- 在 GitHub Issue 中创建选题,标注视频类型(宣传/资讯 or 知识点) +- 在 GitHub Issue 中创建选题,标注视频类型(宣传/资讯/知识点) - 明确目标受众、时长、发布平台 +- **单篇专题比填充式多条新闻效果好**(Vincent 实测反馈) +- 时长建议:15s(社交传播)/ 45-65s(官网)/ 90-120s(B站/YouTube) ## 2. 脚本撰写 -- 确定视频结构:开场 → 正文(分段) → 结尾 CTA -- 每段标注:画面描述 + 旁白文字 + 时长预估 -- 脚本模板见 templates/ +### 口语化原则 +- ❌ 流水账新闻播报、模板式开场 +- ✅ 直接问问题开头、用人话解释术语、给出判断 +- ✅ 结尾必须有**反问**(引发转发表态) + +### 产品视频结构(8 段模板) +``` +Hook(10s) → Install(15s) → Architecture(20s) → Features(20s) +→ Demo(15s) → Dashboard(15s) → Security(15s) → CTA(10s) +``` + +### 资讯视频结构(术语视觉化) +``` +s00: "你知道 XXX 是什么吗?简单说,就是…" +s01: "具体发生了什么。这说明什么?" +s02: "某人说了一句话:不只是加速旧工作" +s03: "你今天还觉得 AI 只是帮你打字快一点吗?" +``` + +## 3. TTS 配音(MiniMax) + +```python +# MiniMax speech-2.8-hd +payload = { + 'model': 'speech-2.8-hd', + 'text': '旁白文本', + 'voice_setting': { 'voice_id': 'vincent_wenxing_v1', 'speed': 1.0 }, + 'audio_setting': { 'sample_rate': 32000, 'format': 'wav' } +} +# ⚠️ audio 是 hex 编码:bytes.fromhex(resp['data']['audio']) +# ⚠️ 输出用 wav(mp3 有解码问题) +``` + +各段 TTS 生成后用 ffmpeg 拼接(0.8-1.0s gap): +```bash +printf 'file s00.mp3\nfile gap.mp3\nfile s01.mp3\n...' > concat.txt +ffmpeg -f concat -safe 0 -i concat.txt -c:a libmp3lame narration.mp3 +``` + +用 silencedetect 找段落边界,确定 Remotion 场景时间轴: +```bash +ffmpeg -i narration.mp3 -af silencedetect=noise=-30dB:d=0.7 -f null - +``` + +## 4. 视觉素材 + +### 优先级(实测经验) +1. **真实截图**(Playwright HiDPI)— 最真实,无 AI 感 ⭐推荐 +2. **即梦概念图**(Dreamina 5.0)— 适合抽象概念,但有 AI 感 +3. **录屏**(Playwright recordVideo)— 最真实但依赖服务器在线 + +### Playwright HiDPI 截图 +```javascript +const page = await browser.newPage({ + viewport: { width: 1920, height: 1080 }, + deviceScaleFactor: 2 // 关键!出图更清晰 +}); +await page.waitForTimeout(5000); // 等数据加载完 +await page.screenshot({ path: 'output.png' }); +``` + +### Dreamina 文生图 +```bash +dreamina text2image \ + --prompt="描述(中文最佳,300-400字)" \ + --ratio=16:9 --model_version=5.0 --resolution_type=4k \ + --poll=60 +``` +⚠️ 必须加「不要文字 no text」否则出乱码 + +## 5. BGM 生成(MiniMax music) + +```bash +mmx music generate \ + --prompt "Clean minimal electronic ambient, tech product demo" \ + --instrumental --genre "ambient electronic" \ + --mood "professional, clean" --bpm 100 \ + --model music-2.6 --out bgm.mp3 +``` + +BGM 加入对评分提升 +0.4(D4 节奏感 + D5 完成品感)。 -## 3. AI 素材生成(Dreamina) +## 6. Remotion 排版 -- 根据脚本中的画面描述生成图片/视频片段 -- 使用 text-to-image 或 image-to-video -- 小批量生成,验证质量后再批量扩展 -- 注意 credits 余量:生成前 `dreamina user_credit` 检查 +### 横屏双列布局(推荐) +```tsx +const DualCol = ({ left, right }) => ( +