Install
openclaw skills install auto-video-editorAutomated video editing skill for talk/vlog/standup videos. Use when: cutting video, splitting video into sentences, merging video clips, extracting audio, t...
openclaw skills install auto-video-editor根据语音内容,将口播/脱口秀类视频按句子自动切分,然后按用户选择合成带字幕的最终视频。
在执行任何操作之前,先运行环境检测:
python3 scripts/utils.py
这会自动检测平台(macOS/Linux/WSL/Windows)、GPU 类型、可用编码器、Whisper 引擎,并给出诊断报告。
如果缺少依赖,提示用户安装:
brew install ffmpeg(macOS)或 apt install ffmpeg(Linux/WSL)或下载 Windows 版本pip install faster-whisper(推荐,速度快 4 倍)或 pip install openai-whisperpip install faster-whisper -i https://pypi.tuna.tsinghua.edu.cn/simple如果项目根目录有 .venv 虚拟环境,运行 Python 脚本前先激活:
source .venv/bin/activate # macOS/Linux/WSL
# Windows: .venv\Scripts\activate
/mnt/c/Windows/Fonts/)--mirror 参数强制启用首次使用时,帮助用户建立素材目录结构:
python3 scripts/media_library.py init [project_dir]
这会创建以下目录结构:
media/
├── raw/ — 原始素材(摄像机/手机直出的视频)
├── broll/ — B-roll 素材(城市街景、产品特写等)
├── bgm/ — 背景音乐(MP3/WAV/M4A)
├── assets/ — 叠加素材(水印 PNG、Logo 等)
└── output/ — 输出目录
询问素材来源:
media/raw/ 目录media/raw/扫描并建立索引:
python3 scripts/media_library.py scan [project_dir]
索引系统会自动:
media_index.json)media_index.db)python3 scripts/media_library.py upgrade查看素材库状态:
python3 scripts/media_library.py status
搜索素材:
python3 scripts/media_library.py search "关键词"
对每个输入视频文件,使用 extract_audio.py 提取音频:
python3 scripts/extract_audio.py "<video_path>"
输出:与视频同目录下的 <video_name>_audio.wav 文件。
使用 transcribe.py 对音频进行语音识别,生成带时间戳的逐句文本:
python3 scripts/transcribe.py "<audio_path>" --model auto --language zh --detect-fillers
--model auto:根据硬件自动选择最佳模型(NVIDIA GPU → large-v3,Apple Silicon → large-v3-turbo,集成显卡 → medium,纯 CPU → small)tiny, base, small, medium, large-v3, large-v3-turbo--engine auto:自动检测 faster-whisper(推荐)或 openai-whisper--mirror:中国用户使用镜像源下载模型--language:zh(中文),en(英文),ja(日文)等,也可省略让 whisper 自动检测--silence-threshold 1.0:静音检测阈值(秒),默认 1.0。设为 0 关闭--word-timestamps:启用逐词时间戳(卡拉OK字幕必需)--detect-fillers:检测填充词(中文:嗯/呃/那个/就是说;英文:um/uh/like/you know),标记纯填充词片段为建议跳过输出:与音频同目录下的 <video_name>_transcript.json 文件,格式如下:
{
"segments": [
{"id": 1, "start": 0.0, "end": 2.5, "text": "大家好"},
{"id": 2, "start": 2.5, "end": 5.1, "text": "今天我们来聊一个话题"}
],
"silences": [
{"start": 15.2, "end": 18.5, "duration": 3.3, "before_segment": 5, "after_segment": 6}
],
"filler_words": [
{"segment_id": 3, "text": "嗯那个", "fillers_found": ["嗯", "那个"], "is_filler_only": true},
{"segment_id": 7, "text": "就是说我觉得这个方案", "fillers_found": ["就是说"], "is_filler_only": false}
]
}
静音检测:transcribe.py 会自动分析相邻语音片段之间的间隙。超过阈值(默认 1 秒)的间隙会被标记为静音并输出到 silences 字段中。这些静音通常是说话人的停顿、卡壳或口误,在构建 render_config.json 选片时应注意避开这些区域。
转录完成后,必须对所有 transcript.json 中的文字进行逐条审查,修正以下两类问题:
1. 语音识别错误(ASR errors): Whisper 常见的识别错误类型:
2. 口误标记(Speaker errors):
校验流程:
注意:此步骤必须在 Phase 5(渲染)之前完成,因为字幕文字来源于 transcript.json。修正后再渲染,才能保证最终视频中的字幕文字正确。
展示片段列表给用户,格式如下:
视频片段列表:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# | 时间区间 | 内容
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1 | 00:00.0 - 00:02.5 | 大家好
2 | 00:02.5 - 00:05.1 | 今天我们来聊一个话题
3 | 00:05.1 - 00:08.3 | 这个话题非常有意思
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
请选择要合成的片段(示例):
- 连续范围:1-10
- 多个片段:1,3,5,7
- 混合选择:1-4,6,8-10
如果有多个视频文件,分别展示每个视频的片段列表,让用户跨视频选择。
在展示片段列表时,AI agent 应基于以下维度为每个片段提供推荐评分(1-5 星):
吸引力评分维度:
自动跳过建议:
is_filler_only: true 的片段(纯填充词)长视频自动拆短片(视频 > 3 分钟时): AI agent 应分析 transcript 识别话题转换点(语义断裂、过渡词如"接下来"、"另外"),将片段按话题分组为独立短视频(每个 30-90 秒),并为每组计算整体吸引力评分:
推荐短视频拆分方案:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
方案 | 片段范围 | 时长 | 主题 | 推荐指数
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
A | #1-#8 | 45s | 痛点引入 | ★★★★★
B | #9-#18 | 62s | 核心方法 | ★★★★☆
C | #19-#25 | 38s | 实操演示 | ★★★☆☆
D | #1-#25 | 2m25s | 完整版 | ★★★★☆
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
等待用户回复选择后,进入 Phase 4。
根据用户的选择,生成 render_config.json 配置文件:
{
"clips": [
{"video": "path/to/video1.MOV", "segment_id": 4, "transcript": "path/to/transcript1.json"},
{"video": "path/to/video1.MOV", "segment_id": 5, "transcript": "path/to/transcript1.json"},
{"video": "path/to/video2.MOV", "segment_id": 1, "transcript": "path/to/transcript2.json",
"broll": "path/to/cityscape.mp4", "broll_start": 5.0}
],
"title": "封面标题文字",
"subtitle": "副标题/情感钩子(可选)",
"cover_style": "news",
"cover_duration": 2.0,
"cover_image": "path/to/custom_cover.png",
"cover_use_frame": false,
"video_overlay": "path/to/overlay.png",
"rec_blink": {
"dot_image": "path/to/dot.png",
"x": 55, "y": 66,
"period": 1.0
},
"end_cards": [
{"text": "感谢观看\n更多内容敬请期待", "duration": 3.5}
],
"bgm": "path/to/background_music.mp3",
"bgm_volume": 0.15,
"bgm_fade_out": 3.0,
"subtitle_style": "karaoke",
"subtitle_highlight_color": "#FFFF00",
"chapters": [
{"title": "章节名", "start": 0.0, "end": 30.0}
]
}
B-roll 替换(broll 字段):
"broll": "path/to/video.mp4" 可替换该片段的画面,同时保留原始音频broll_start 指定从 B-roll 视频的哪个时间点开始截取(默认 0.0)自定义封面(cover_image):
持续叠加层(video_overlay):
闪烁圆点(rec_blink):
dot_image:圆点 PNG 路径(建议 12-16px,RGBA 格式)x, y:圆点在视频画面中的像素坐标period:闪烁周期(秒),默认 1.0(0.5 秒亮 + 0.5 秒灭)结尾卡片(end_cards):
text:卡片文字内容,用 \n 换行duration:每张卡片显示时长(秒),建议 3.0-4.0背景音乐(bgm):
bgm_volume:BGM 音量(0.0-1.0),默认 0.15(人声为主,BGM 为辅)bgm_fade_out:结尾淡出时长(秒),默认 3.0字幕风格预设(subtitle_style):
| 风格 | 效果 | 适用场景 |
|---|---|---|
normal | 白字黑描边(默认) | 适合所有场景 |
karaoke | 逐词高亮 | 音乐/节奏感内容 |
bold_pop | 粗描边高对比 | MrBeast/Hormozi 风格 |
neon | 霓虹灯青紫色 | 科技/潮流内容 |
minimal | 极简无描边 | 文艺/安静内容 |
yellow_pop | 黄字黑描边 | 高可见度,户外/嘈杂画面 |
卡拉OK字幕 / 逐词高亮(subtitle_style: "karaoke"):
"subtitle_style": "karaoke" 启用逐词高亮字幕--word-timestamps 参数进行语音识别,获取逐词时间戳subtitle_highlight_color:当前词高亮颜色,默认 "#FFFF00"(黄色)subtitle_base_color:未说到的词底色,默认 "#FFFFFF"(白色)subtitle_base_alpha:底色透明度 hex,默认 "80"(半透明)--subtitle-style karaoke 覆盖 config# 1. 转录时开启逐词时间戳
python3 scripts/transcribe.py audio.wav --model auto --language zh --word-timestamps
# 2. 渲染时选择 karaoke 字幕风格
python3 scripts/render_final.py --config render_config.json --output final.mp4 --subtitle-style karaoke
音频源替代(M4A/独立音频):
ffmpeg -f lavfi -i "color=c=black:s=1080x1920:r=30:d=60" -i audio.m4a -c:v libx264 -c:a aac -shortest audio.mp4
"video": "audio.mp4" 提供音频源,用 "broll" 提供画面封面标题:
subtitle 可选,用于补充情感钩子或关键信息。封面文字排版规则:
AI、GPT-5 之类不应把整行宽度挤爆。subtitle 字号默认按标题的约 50% 处理,只承担补充信息,不和主标题争抢视觉中心。封面风格(cover_style)— 根据视频内容选择最合适的风格:
| 风格 | 适用场景 | 视觉效果 |
|---|---|---|
bold | 教程、科普、技术 | 黑底 + 大号白色粗体字,简洁有力 |
news | 热点、观点、争议 | 深色渐变底 + 白色标题 + 黄色副标题,冲击力强 |
frame | Vlog、实拍、场景 | 视频首帧做背景 + 暗色遮罩 + 描边白字 |
gradient | 生活、情感、艺术 | 紫粉渐变底 + 发光白字,温柔优雅 |
minimal | 思考、文化、深度 | 纯黑底 + 细体白字,极简克制 |
white | 教程、产品、品牌化内容 | 纯白底 + 深色字,现代感更强 |
techcard | 屏幕录制、软件教程、AI 工具演示 | 左侧大标题 + 右侧画面卡片,兼顾信息量和可读性 |
AI agent 应根据视频主题和内容语气自动选择:
bold 或 newsnews(白标题+黄副标题效果最抢眼)framegradientminimaltechcard 优先;如果画面太杂,就退回 bold / white背景取帧规则:
bold / white / minimal 这类纯底风格。scripts/generate_cover_image.py --frame-timestamp 00:10:00 指定取帧时间。封面时长(cover_duration):
--cover-duration 命令行参数覆盖章节划分:
使用 render_final.py 从原始视频一次编码生成最终视频:
python3 scripts/render_final.py --config render_config.json --output final.mp4 --speed 1.25 1.5
核心原理:
select/aselect + between() 表达式一次性筛选所有保留片段,FFmpeg 解码完整源视频但只编码选中的帧,配合 -crf 18 -preset medium 只编码一次trim/atrim 裁切 + concat 拼接(自动降级)tpad 冻结第一帧 + adelay 添加静音,字幕时间自动偏移,全部在一次编码中完成参数说明:
--config:渲染配置 JSON 路径--output:输出文件路径--speed 1.25 1.5:同时输出变速版本(每个变速版本也是从原始视频直接编码,不是从已编码视频二次压缩)--cover-duration 2.0:封面冻结时长(秒),覆盖配置中的 cover_duration--font-path:自定义字体文件--font-size:字幕字号(默认 48,基于 1080p 自动缩放)--no-subtitles、--no-cover:跳过对应功能输出:
final.mp4(原速)final_1_25x.mp4(1.25 倍速)final_1_5x.mp4(1.5 倍速)多平台格式导出:
python3 scripts/render_final.py --config render_config.json --output final.mp4 \
--formats vertical square horizontal
同时输出:
final_vertical.mp4(9:16 抖音/小红书/TikTok)final_square.mp4(1:1 Instagram)final_horizontal.mp4(16:9 YouTube/B站)裁切策略为中心裁切(center-crop),保持画面主体不变。
自动功能:
-shortest),避免平台上传时的时长不匹配问题渲染完成后,对最终视频执行验证流程:
6a. 音频重复检测:
6b. 字幕文字最终校验:
字幕校验结果:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# | 问题类型 | 原文 → 建议修正
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
3 | 识别错误 | "检映" → "剪映"
7 | 口误 | "先说了结果" → 建议删除此片段
12 | 名称不一致 | "opencloud" → 统一为 "OpenClaw"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
render_final.py 的 select/aselect + between() 方案(单视频)或 trim/atrim + concat 方案(多视频),在一条 ffmpeg 命令中完成裁切、拼接、字幕、封面的全部操作。--speed 1.25 1.5 的变速版本在 filter_complex 中集成 setpts + atempo,直接从原始视频一步到位,不要从已编码的 1x 视频再次压缩。-b:v 12M)而非质量参数(如 -q:v)。固定比特率可以精确控制文件大小和质量,避免 -q:v 在不同编码器上表现不一致。参考原始视频比特率(通常 8-15 Mbps)设定。split_video.py、burn_subtitles.py、merge_clips.py、generate_cover.py、add_chapter_bar.py 仍可单独使用,但最终输出必须使用 render_final.py。旧脚本适合快速预览单个片段效果。utils.get_video_info() 统一检测 rotation 并自动交换宽高,确保获取正确的显示尺寸。检测视频信息时必须首先检查 rotation。large 模型,base/small 模型中文识别率较低。large 模型约需 2.9GB 下载空间。libass 和 libfreetype。macOS 可通过 brew install ffmpeg 获取。当用户只有语音(或音频文件)但没有画面时,使用 Remotion 生成配合语音的视频画面。
详细的 Remotion API 参考、模板样式、组件结构见 REMOTION_VOICEOVER.md。
extract_audio.py 提取音频,或直接使用用户提供的音频文件transcribe.py 生成 transcript.json(逐句时间戳)timeline.json:
npx remotion render 根据 timeline.json 渲染最终视频render_final.py 与其他视频片段合并| 风格 | 适用场景 | 视觉效果 |
|---|---|---|
tiktok | 短视频口播、知识分享 | 渐变背景 + 关键词卡片 + TikTok 风格逐词字幕 + 进度条 |
tutorial | 教程、科普、产品介绍 | 图文分栏 + Ken Burns 图片 + 要点逐行淡入 + 底部字幕 |
kinetic | 情感类、激励类、文案 | 全屏大号文字逐行弹入 + 弹性动效 |
podcast | 播客、访谈、对话 | 头像 + 音频波形可视化 + 引用文字 |
news | 新闻播报、行业资讯 | 顶部横幅 + Lower Third 信息条 + 滚动字幕 |
slideshow | 产品介绍、旅行、相册 | 多图 Ken Burns + 转场效果 + 说明文字 |
# 需要 Node.js 18+ 和 npm
node --version # >= 18.0.0
npm --version
# 安装 Remotion standup 项目依赖
cd remotion-standup
npm install
当用户有一段脱口秀音频(或任何纯语音内容)但没有画面时,可以生成带文字动效的视频:
Step 1: 语音识别
python3 scripts/transcribe.py audio.wav --model auto --language zh
Step 2: 生成时间轴
# 默认风格
python3 scripts/generate_standup_timeline.py transcript.json \
--audio audio/standup.wav \
--output remotion-standup/public/timeline.json
# 活力风格(更多夸张动效)
python3 scripts/generate_standup_timeline.py transcript.json \
--audio audio/standup.wav \
--style energetic \
--output remotion-standup/public/timeline.json
# 选择特定片段 + 自定义字体
python3 scripts/generate_standup_timeline.py transcript.json \
--audio audio/standup.wav \
--segments 1-10,12,15-20 \
--font "LXGW WenKai, sans-serif" \
--output remotion-standup/public/timeline.json
Step 3: 预览和渲染
cd remotion-standup
# 把音频文件复制到 public 目录
cp /path/to/audio.wav public/audio/standup.wav
# 开发预览
npx remotion studio
# 渲染最终视频
npx remotion render StandupVideo out/standup.mp4 --codec=h264 --crf=18
脚本会自动:
12 种文字动画效果:
| 动画 | 效果 | 适合场景 |
|---|---|---|
fadeIn | 渐显 | 平稳叙述 |
springIn | 弹性入场 | 正常对话 |
scaleUp | 由小放大 | 强调 |
scaleDown | 由大缩小 | 砸入感 |
typewriter | 打字机 | 引述/对话 |
bounce | 弹跳 | 活泼/搞笑 |
shake | 抖动 | 笑点/吐槽 |
slam | 急速砸入 | 重磅笑点 |
wave | 逐字波浪 | 开场/结尾 |
glitch | 故障闪烁 | 意外/反转 |
rotateIn | 旋转入场 | 切换话题 |
splitReveal | 中间展开 | 揭示/揭晓 |
3 种风格预设:
| 风格 | 说明 |
|---|---|
default | 均衡混合所有动画,适合大多数内容 |
calm | 只用平缓动画(fadeIn/springIn/typewriter),适合讲故事/深度内容 |
energetic | 偏重夸张动画(slam/shake/bounce/glitch),适合脱口秀/搞笑内容 |
{
"fps": 30,
"width": 1080,
"height": 1920,
"audioSrc": "public/audio/voiceover.wav",
"style": "tiktok",
"font": {
"family": "Noto Sans SC",
"titleWeight": "700",
"bodyWeight": "400",
"titleSize": 72,
"bodySize": 48
},
"colors": {
"background": "#1a1a2e",
"text": "#ffffff",
"highlight": "#FFD700",
"accent": "#e94560"
},
"scenes": [
{
"id": 1,
"startMs": 0,
"endMs": 5000,
"type": "title",
"title": "今天聊一个话题",
"background": { "type": "gradient", "colors": ["#667eea", "#764ba2"] },
"transition": { "type": "fade", "durationMs": 500 }
}
],
"captions": {
"enabled": true,
"style": "tiktok",
"fontSize": 56,
"highlightColor": "#FFD700"
}
}
项目内置了一套可下载的免费字体目录,覆盖中文和英文视频制作常用字体。
# 查看环境报告(包含已缓存字体列表)
python3 scripts/utils.py
# 在 Python 中使用字体 API
python3 -c "
from scripts.utils import list_available_fonts, download_font
# 列出所有可用字体
for f in list_available_fonts():
status = '✓' if f['cached'] else '○'
print(f\"{status} {f['id']:25s} {f['name']:25s} {f['use_case']:8s} {f['description']}\")
# 下载指定字体
download_font('lxgw-wenkai')
download_font('inter')
"
| 字体 ID | 名称 | 风格 | 用途 | 许可证 |
|---|---|---|---|---|
noto-sans-sc | Noto Sans SC(思源黑体) | 万能黑体 | 全场景 | SIL OFL |
noto-serif-sc | Noto Serif SC(思源宋体) | 正式宋体 | 文化/古典/深度 | SIL OFL |
lxgw-wenkai | LXGW WenKai(霞鹜文楷) | 手写楷体 | 文艺/文化/情感(~24MB) | SIL OFL |
lxgw-wenkai-lite | LXGW WenKai Lite(轻便版) | 手写楷体 | 同上,体积更小(~13MB) | SIL OFL |
lxgw-wenkai-bold | LXGW WenKai Medium | 手写楷体粗 | 标题 | SIL OFL |
zcool-kuaile | ZCOOL KuaiLe(站酷快乐体) | 圆润可爱 | 轻松/娱乐标题 | SIL OFL |
zcool-qingke-huangyou | ZCOOL QingKe HuangYou(庆科黄油体) | 手写潮流 | 时尚/年轻标题 | SIL OFL |
zcool-xiaowei | ZCOOL XiaoWei(站酷小薇体) | 清秀端正 | 正文/字幕 | SIL OFL |
| 字体 ID | 名称 | 风格 | 用途 | 许可证 |
|---|---|---|---|---|
inter | Inter | 现代无衬线 | 全场景 | SIL OFL |
montserrat | Montserrat | 几何无衬线 | 标题 | SIL OFL |
poppins | Poppins | 圆润几何 | 标题 | SIL OFL |
roboto | Roboto | 中性现代 | 全场景 | Apache 2.0 |
oswald | Oswald | 窄体无衬线 | 新闻/头条标题 | SIL OFL |
playfair-display | Playfair Display | 优雅衬线 | 文艺/高端标题 | SIL OFL |
| 视频类型 | 推荐中文字体 | 推荐英文字体 |
|---|---|---|
| 科技/教程 | Noto Sans SC | Inter / Roboto |
| 新闻/资讯 | Noto Sans SC | Oswald / Montserrat |
| 文化/深度 | LXGW WenKai / Noto Serif SC | Playfair Display |
| 娱乐/轻松 | ZCOOL KuaiLe | Poppins |
| 时尚/潮流 | ZCOOL QingKe HuangYou | Montserrat |
| 正式/商务 | Noto Sans SC | Inter |
# 下载字体后,通过 --font-path 参数指定
python3 scripts/render_final.py --config render_config.json --output final.mp4 \
--font-path fonts/LXGWWenKai-Regular.ttf
// 方式 1: @remotion/google-fonts(英文字体推荐)
import { loadFont } from "@remotion/google-fonts/Inter";
const { fontFamily } = loadFont();
// 方式 2: @remotion/fonts(本地/CJK 字体推荐)
import { loadFont } from "@remotion/fonts";
loadFont({
family: "LXGW WenKai",
url: staticFile("fonts/LXGWWenKai-Regular.ttf"),
format: "truetype",
});
// 方式 3: @remotion/google-fonts 加载 CJK
import { loadFont } from "@remotion/google-fonts/NotoSansSC";
const { fontFamily } = loadFont("normal", {
weights: ["400", "700"],
subsets: ["chinese-simplified"], // 重要:指定子集减小体积
});
@remotion/google-fonts 时务必指定 subsets: ["chinese-simplified"] 减小体积fonts/ 目录,.gitignore 已排除遇到错误时,先运行环境诊断:
python3 scripts/utils.py
No such filter: 'drawtext' 或 No such filter: 'ass'原因:ffmpeg 编译时未包含 libfreetype(drawtext 所需)或 libass(字幕所需)。
诊断:
ffmpeg -hide_banner -filters 2>/dev/null | grep -E "drawtext|ass|subtitles"
如果无输出,说明缺少对应滤镜。
解决:
brew install ffmpeg 可能不包含这些库。使用第三方 tap 安装完整版:
brew tap homebrew-ffmpeg/ffmpeg
brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-fdk-aac
该 tap 默认启用 --enable-libfreetype --enable-libass --enable-libfontconfig。apt install ffmpeg 通常已包含。如果缺少,安装开发依赖后从源码编译:
sudo apt install libfreetype6-dev libfontconfig1-dev libass-dev
Undefined constant or missing '(' in 'iw*0.5-tw/2'原因:ffmpeg drawtext 的 x 表达式中使用了 tw(text width),但某些 ffmpeg 版本中 tw 在 x 参数的上下文中不可用。
解决:脚本已修复此问题(使用像素值 {pixel_x}-text_w/2 代替 iw*{frac}-tw/2)。如果你修改了脚本并遇到此错误,请使用 text_w 而非 tw,并确保 x 表达式中不包含 iw* 动态计算。
Invalid alpha value specifier '%{eif:...}' (drawtext fontcolor)原因:试图在 fontcolor 参数中嵌入 %{eif} 表达式来实现透明度渐变,但 ffmpeg 不支持在颜色值中使用此语法。
解决:使用 drawtext 的 alpha 参数(独立于 fontcolor),而非试图在 fontcolor=white@'%{eif:...}' 中嵌入表达式。正确写法:
drawtext=text='hello':fontcolor=white:alpha='if(lt(t,1),t,1)'
错误写法(会报错):
drawtext=text='hello':fontcolor=white@'%{eif:if(lt(t,1),t,1):d:2}'
h264_videotoolbox / h264_nvenc / h264_qsv 报错)原因:检测到的硬件编码器不支持当前的视频参数(如特殊分辨率、色彩空间),或驱动版本不兼容。
诊断:
ffmpeg -encoders 2>/dev/null | grep -E "nvenc|videotoolbox|qsv|amf"
解决:在 scripts/utils.py 中临时修改 get_ffmpeg_encoder() 函数,让它直接返回 ("libx264", ["-preset", "fast", "-crf", "18"])。
原因:系统中没有可用的中文字体文件。
诊断:
python3 -c "from scripts.utils import find_chinese_font; print(find_chinese_font())"
如果返回 (None, ...),说明未找到中文字体。
解决:
sudo apt install fonts-noto-cjk
/mnt/c/Windows/Fonts/msyh.ttc(微软雅黑),前提是 Windows 已安装该字体。--font-path /path/to/your/font.ttf 参数。fonts/ 目录。原因:网络问题,尤其是中国用户无法访问 HuggingFace。
解决:
--mirror 参数:python3 scripts/transcribe.py audio.wav --mirror --model autoexport HF_ENDPOINT=https://hf-mirror.com
HF_ENDPOINT 后会自动走镜像。pip install faster-whisper 安装失败 / 超时解决:中国用户使用清华镜像:
pip install faster-whisper -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn
诊断:
which ffmpeg && ffmpeg -version | head -1
解决:
sudo apt update && sudo apt install ffmpeg
如果系统源的 ffmpeg 版本过旧(< 4.0),使用 PPA:
sudo add-apt-repository ppa:savoury1/ffmpeg4
sudo apt update && sudo apt install ffmpeg
原因:视频经过了多次重编码,每次编码都有质量损失。
解决:必须使用 render_final.py 单次编码。检查是否在流程中使用了 split_video.py + burn_subtitles.py + merge_clips.py + generate_cover.py + add_chapter_bar.py 的旧流程(会导致 4-5 次重编码)。改用 render_final.py --config 一步到位。
brew install ffmpeg