在Google Colab用ffmpeg/MoviePy烧录字幕时显示方框的问题
问题:Colab中印地语字幕硬编码显示为方框(本地运行正常)
我正在编写Python脚本,通过FFmpeg将印地语字幕硬编码到视频中,已指定支持天城文的自定义字体(NotoSansDevanagari-Regular.ttf,重命名为font.ttf)。本地机器运行时字幕显示正常,但在Google Colab中执行时,字幕变成了矩形方框,无法正常显示印地语字符。
已尝试的操作:
- 确认字体本身支持印地语字符
- 将字体上传至Colab并指定了完整路径
- 验证字幕文本以正确的Unicode格式传递
代码片段:
def add_subtitles(video_path, subtitles_path, output_path): """Adds subtitles using FFmpeg with proper path escaping.""" # Convert to absolute paths and normalize video_path = os.path.abspath(video_path) subtitles_path = os.path.abspath(subtitles_path) output_path = os.path.abspath(output_path) # Subtitle path font_path = "input_files/font.ttf" font_path = os.path.abspath(font_path).replace("\\", "\\\\") subtitles_path_escaped = os.path.abspath(subtitles_path).replace("\\", "\\\\") # Escape backslashes in paths subtitles_path = subtitles_path.replace("\\", "\\\\") # Remove all files in final_videos [os.remove(os.path.join(base_dir, "final_videos", f)) for f in os.listdir(os.path.join(base_dir, "final_videos")) if os.path.isfile(os.path.join(base_dir, "final_videos", f))] os.makedirs(os.path.dirname(output_path), exist_ok=True) escaped_path = subtitles_path.replace(':', '\\:').replace('\\', '\\\\') cmd = [ "ffmpeg", "-i", video_path, "-vf", f"subtitles={escaped_path}:force_style='FontFile={font_path}'", "-c:v", "libx264", "-c:a", "copy", "-preset", "fast", "-crf", "22", output_path ] # Debug: Print the exact command being executed print("Executing:", " ".join(cmd)) try: subprocess.run(cmd, check=True, capture_output=True, text=True) print(f"✅ Success! Output saved to: {output_path}") except subprocess.CalledProcessError as e: print(f"❌ FFmpeg failed with error:\n{e.stderr}")
原因分析
- 环境路径逻辑不匹配:Colab基于Linux系统,路径分隔符为
/,但代码中沿用了Windows的反斜杠转义逻辑,过度转义导致FFmpeg无法识别字体路径。 - FFmpeg参数格式错误:
force_style的引号嵌套方式不符合Linux下FFmpeg的参数解析规则,导致字体路径未被正确读取。 - Colab默认字体缺失:FFmpeg在找不到指定字体时会 fallback 到系统默认字体,而Colab默认环境可能没有预装支持天城文的字体。
解决方案
1. 修正路径处理逻辑(适配Linux)
删除多余的反斜杠转义,直接使用Linux风格的绝对路径:
# 替换原路径处理代码 font_path = os.path.abspath("input_files/font.ttf") # 仅转义路径中的单引号(如果存在),避免FFmpeg解析出错 escaped_sub_path = subtitles_path.replace("'", "\\'")
2. 调整FFmpeg滤镜参数格式
修正force_style的引号使用方式,确保字体路径被正确识别:
cmd = [ "ffmpeg", "-i", video_path, "-vf", f"subtitles={escaped_sub_path}:force_style=FontFile='{font_path}'", "-c:v", "libx264", "-c:a", "copy", "-preset", "fast", "-crf", "22", "-y", # 自动覆盖输出文件,避免Colab交互阻塞 output_path ]
3. 验证字体文件可访问性
在执行命令前添加检查,确保字体文件存在且可读:
if not os.path.exists(font_path): print(f"❌ Font file not found: {font_path}") return if not os.access(font_path, os.R_OK): print(f"❌ No read permission for font file: {font_path}") return
4. 备选:安装系统级印地语字体
如果自定义字体仍无法生效,可直接安装Colab缺失的系统字体包:
!apt-get update && apt-get install -y fonts-noto-devanagari
之后无需指定字体路径,直接使用字体名称即可:
"-vf", f"subtitles={escaped_sub_path}:force_style='FontName=Noto Sans Devanagari'"
验证步骤
执行命令前打印完整FFmpeg命令,检查路径是否正确:
print("Final FFmpeg command:", " ".join(cmd))
可通过!ls input_files命令确认字体文件是否在指定目录下。
内容的提问来源于stack exchange,提问作者Lavish
相关产品推荐
相关产品推荐

