forthrin
forthrin

Reputation: 2777

Rendering pixel perfect subtitles for small videos

I want to burn subtitles with a font as small as possible (yet readable) on top of a small size video, as shown on the first image. FFmpeg makes the font blurry for any font size tried (second image).

ffmpeg -i in.jpg -vf "scale=160x128,subtitles=in.srt:force_style='OutlineColour=&H80000000,BorderStyle=3,Fontsize=15,Fontname=Silkscreen'" out.png

Is there any way I can achieve pixel perfect subtitles with small fonts using FFmpeg or other readily available command line tools? (The smallest font I've found is Silkscreen, though it's ASCII only!)

enter image description here enter image description here

Upvotes: 3

Views: 2497

Answers (1)

Chortos-2
Chortos-2

Reputation: 1123

You can get a much better result by enabling font hinting in libass, but it appears that FFmpeg doesn’t support setting this option currently. Try this with mpv:

mpv in.jpg --vf=scale=160:128 --sub-file=in.srt --sub-ass-hinting=light --sub-font=Silkscreen --sub-font-size=54 --sub-back-color=0/0/0/0.5 --sub-color=1/1/1 --o=out.png

(There’s also --sub-ass-force-style=FontName=Silkscreen,etc. if you need it or simply prefer to use the ASS syntax directly.)

You may have better luck with --sub-ass-hinting=normal or --sub-ass-hinting=native, but the value light gave me the best result for the image in your question.

Here’s what I got:

Output from mpv using the image from the question. Output from mpv using the image from the question and keeping the original source image’s aspect ratio.

(The source image I found on the Web has a 3:2 aspect ratio, but your example was 4:3. On the left, I had to use --vf=scale=160:120,dsize=160:120 to match your size and aspect ratio. On the right, I used --vf=scale=180:120 to match your image height but keep the original aspect ratio.)

For an even better result, you probably need to tweak the font size, as the font in question is optimized for specific sizes as far as I understand. ASS “font size” is not the conventional font size in points (but rather the sum of the ascender and descender heights in pixels), so this isn’t completely trivial, but a bit of experimentation will probably get you there.

Compared to your old approach, this also gives you a cleaner box around/behind the subtitles. When using BorderStyle=3 with a semitransparent OutlineColour like you currently do, there is a separate box for each line of text and those boxes overlap slightly; as a result, you can see a thin area of darker/more intense colour between each two lines of text. This may not be very noticeable at your sizes, but you’ll see it if you look hard enough. As an extension to the ASS format, libass supports a custom BorderStyle=4, which produces a single box around the whole text. When setting --sub-back-color in mpv, it automatically selects this. (If multiple pieces of text appear simultaneously, each will still have its own box and the boxes may overlap. But based on my very brief search, it seems this situation is rare in SRT files.) Should you want to revert to BorderStyle=3, I think you’ll need to add --sub-ass-force-style=BorderStyle=3 and replace --sub-back-color with --sub-border-color.

Upvotes: 2

Related Questions