I set up a script that generates a simple video with one mp3 audio and one text on screen. I would like to add the option to specify a font type and use that for formatting of the text on the video.
This is my code:
import subprocess
from pathlib import Path
from myproject import AUDIOS_FOLDER, FONTS_FOLDER
font_name = "Montserrat-LightItalic"
font_path = str(FONTS_FOLDER / font_name) + '.ttf'
assert Path(font_path).is_file()
ffmpeg_command = [
'ffmpeg',
'-y',
'-f', 'lavfi',
'-i', 'color=c=gray:s=640x480:d=4',
'-i', f'{str(AUDIOS_FOLDER / "i_have_a_cat.mp3")}',
'-vf', f'drawtext=text=\'I have a cat\':fontsize=24:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:fontfile=\'{font_path}\'',
str(ffmpeg_poc_path / 'output.mp4')
]
subprocess.run(ffmpeg_command)
The problem I am facing is that the :fontfile=\'{font_path}\'
setting doesn't get activated. The above code produces the exact same output as if I drop the :fontfile=\'{font_path}\'
section entirely.
I tried using alternative font names without using the font_path
, e.g.:
'-vf', f'drawtext=text=\'I have a cat\':fontsize=24:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:fontfile=\'arialbd.ttf\''
or
'-vf', f'drawtext=text=\'I have a cat\':fontsize=24:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:fontfile=\'sseriff.ttf\''
but these didn't work either, despite both files existing at C:\Windows\Fonts
on my local device. So at this stage, I concluded that neither the system default fonts, nor the custom installed, project-specific ones work.
Note 1: I also tried with and without single and double quotes, with no success:
:fontfile='sseriff.ttf'
:fontfile=\'sseriff.ttf\'
:fontfile="sseriff.ttf"
:fontfile=\"sseriff.ttf\"
Note 2: As for the project-specific fonts which I intend to collect under: project_root/fonts
directory, I came across this comment and I transformed the path as advised here; with no success:
font_path = font_path.replace("\\", "\\\\").replace("C:", "C\:")
# example result: C\:\\user\\OneDrive\\Desktop\\myproject\\fonts\\Montserrat-LightItalic.ttf
Note 3: Based on Rotem's advice below, I copied the custom font files from C:\Windows\Fonts
to my working directory. In the below case, I used the arialbd.ttf
custom font:
'-vf', f'drawtext=text=\'I have a cat\':fontsize=24:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:fontfile=arialbd.ttf'
Note that no quotes should be used around the filename; otherwise, the font won't be applied.
While this works perfectly, I am still unable to reference an arbitrary font type via an absolute path. The following approach doesn't work:
font_path = FONTS_FOLDER / "arialbd.ttf"
assert font_path.is_file()
font_path_str = str(font_path)
# path looks like this: c:\user\OneDrive\myproject\fonts\arialbd.ttf
ffmpeg_command = [
'ffmpeg',
'-y',
'-f', 'lavfi',
'-i', 'color=c=gray:s=640x480:d=4',
'-i', f'{str(audios_path / "i_have_a_cat.mp3")}',
'-vf', f'drawtext=text=\'I have a cat\':fontsize=24:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2:fontfile={font_path_str}',
str(ffmpeg_poc_path / 'output.mp4')
]
I also tried to duplicate all backslashes and convert C:\
to C\:\
but still no success.
sseriff.ttf
file from the Fonts folder to the folder of the Python script (to the "working directory"), and tryfontfile="sseriff.ttf"
. You may also try full path:fontfile="c:\\Windows\\Fonts\\sseriff.ttf"
. Note: I can't findsseriff.ttf
file in myc:\Windows\Fonts
folder - make sure that the file exists (there issseriff.fon
file, and I don't know if FFmpeg supports.fon
files).sseriff.ttf
is not found atC:\Windows\Fonts
. Butarialbd.ttf
is there. I copied this file across to my working directory and reran the script as you recommended and when provided without any quote symbols, it works! But if I want to provide any kind of path to thefontfile
argument, it still doesn't work :( I edited my post.