FFmpeg中ASS字幕显示偏小且位置偏移,求ASS配置问题排查
问题场景
用两种方式给同一视频加字幕,drawtext命令显示正常,但ASS字幕出现字体偏小、Y轴位置偏移的问题,且仅在使用非通用字体(如Audiowide)时偏差明显。
1. 正常的drawtext命令
ffmpeg -i ./input.mp4 -vf "drawtext=text='reise':fontfile=../fonts/Audiowide-Regular.ttf:fontsize=55:fontcolor=white:x=0:y=683" -codec:a copy ./output.mp4
2. 异常的ASS字幕配置
ASS文件内容:
[Script Info] Title: Advanced Highlighted Subtitle Example ScriptType: v4.00+ WrapStyle: 0 PlayResX: 1048 PlayResY: 750 [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding Style: Default,Audiowide Regular,55,&HFFFFFF,&H00FFFFFF,&H00000000,&H00000000,1,0,0,0,100,100,0,0,0,0,0,2,10,10,10,1 [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,00:00:0.00,00:00:2.38,Default,,0,0,0,,{\pos(0,683)\an4}reise
对应的FFmpeg命令:
ffmpeg -i ./input.mp4 -vf "ass=../subtitles.ass:fontsdir=../fonts/Audiowide-Regular.ttf" ../output.mp4
核心问题与修复方案
1. PlayResX/Y与视频分辨率不匹配
ASS的PlayResX/PlayResY是字幕的画布基准分辨率,FFmpeg会自动将字幕按这个值与视频实际分辨率的比例缩放。如果你的视频分辨率不是1048x750,字幕就会被缩放,导致字体变小、位置偏移。
修复:把PlayResX和PlayResY改成视频的实际分辨率(比如视频是1920x1080就改成对应数值)。
2. 字体名称不匹配
ASS里的Fontname需要写字体的内部名称,不是文件名。Audiowide-Regular.ttf的内部名称可能不是Audiowide Regular(带空格),而是Audiowide-Regular或Audiowide。
验证方法:用ffprobe查看字体内部名称:
ffprobe -v error -show_entries stream_tags=title -of default=noprint_wrappers=1:nokey=1 ../fonts/Audiowide-Regular.ttf
修复:将ASS中Style行的Fontname替换为正确的内部名称。
3. fontsdir参数用法错误
FFmpeg的fontsdir参数需要指定字体所在的文件夹路径,而不是单个字体文件路径。原命令里写的是具体字体文件,导致FFmpeg可能无法正确加载字体, fallback到系统默认字体,引发显示偏差。
修复:修改命令为:
ffmpeg -i ./input.mp4 -vf "ass=../subtitles.ass:fontsdir=../fonts" ../output.mp4
4. 对齐标记与画布坐标的冲突
\pos(0,683)是基于ASS画布分辨率(PlayResX/Y)的坐标,如果画布分辨率和视频不一致,这个位置会被缩放偏移。配合\an4(左下对齐),只有当画布分辨率和视频一致时,坐标才会对应视频的实际位置。
修复:在正确设置PlayRes后,保留\pos(0,683)\an4即可匹配drawtext的位置。
修正后的ASS文件示例
假设视频分辨率为1920x1080,字体内部名称为Audiowide-Regular:
[Script Info] Title: Fixed Subtitle ScriptType: v4.00+ WrapStyle: 0 PlayResX: 1920 PlayResY: 1080 [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding Style: Default,Audiowide-Regular,55,&HFFFFFF,&H00FFFFFF,&H00000000,&H00000000,1,0,0,0,100,100,0,0,0,0,0,2,10,10,10,1 [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,00:00:00.00,00:00:02.38,Default,,0,0,0,,{\pos(0,683)\an4}reise
内容的提问来源于stack exchange,提问作者Armen Sanoyan

