I'm writing a Python script using subprocess to hardcode subtitles onto a video. My code builds a complex filter graph for ffmpeg's -vf argument, which includes burning in multiple layers of styled subtitles from an SRT file.
The script works perfectly for most files, but it fails whenever the subtitle filename contains a single quote (apostrophe), for example, That's It and That's All.srt.
When the script encounters such a file, the ffmpeg process fails immediately and doesn't create an output file. This causes a downstream KeyError: 'streams' in my code when it later tries to run ffprobe on the non-existent output file, but the root cause is the ffmpeg command failing silently.
The only solution I've found is to programmatically rename the file to remove the apostrophe, which I want to avoid.
The first time I encountered this, I read through the output log and saw that ffmpeg was removing the apostrophes itself from the string path passed to ffmpeg in the code.
[Parsed_subtitles_1 @ 000002c435dce5c0] Unable to open C:/FUBAR/Season 01/FUBAR - S01E08 - Thats It and Thats All.srt
The Code
Here is a simplified example of how the -vf filter string and the final ffmpeg command are constructed in my script:
import subprocess
from pathlib import Path
# --- Example of a problematic file path ---
source_video_path = Path(r"C:\videos\FUBAR - S01E08 - That's It and That's All.mkv")
subtitle_path = source_video_path.with_suffix('.srt')
# --- This is how I build the filter string ---
video_filter = 'crop=1920:800:0:140' # Example starting filter
# The subtitle path is formatted for the filter string
# NOTE: My real code finds this path dynamically.
formatted_subtitle_path = str(subtitle_path).replace('\\', '/')
# A simplified version of my style loop
style_string = "FontName=Segoe UI,FontSize=18,PrimaryColour=&H00FFFFFF"
# The filename is placed inside single quotes in the filter
video_filter += f",subtitles=filename='{formatted_subtitle_path}':force_style='{style_string}'"
# --- The final ffmpeg command list ---
command = [
'ffmpeg.exe',
'-y',
'-i', str(source_video_path),
'-vf', video_filter,
'-c:a', 'copy',
'output.mkv',
]
print("--- Generated FFmpeg Command ---")
# Using print to show how Python sees the arguments before execution
for i, arg in enumerate(command):
print(f"Arg[{i}]: {arg}")
# When run, ffmpeg fails on this command because of the ' in the filename.
# process = subprocess.run(command, text=True, capture_output=True)
# print("\n--- FFmpeg Output ---")
# print(process.stderr)
What I've Tried
I understand the problem is that the single quote in That's It prematurely terminates the filename='...' string within the -vf filter. I have tried several common methods to escape it, but none have worked:
- Backslash Escaping: I've tried replacing the apostrophe in the
formatted_subtitle_pathwith various escape sequences before building the filter string.
replace("'", r"\'")replace("'", r"\\'")replace("'", r"\\\'")
Shell Quoting Trick: I also tried the ''' method.
replace("'", r"'\''")Using Double Quotes: I tried changing the filter string to wrap the filename in double quotes, but
ffmpegstill seems to fail.
video_filter += f""",subtitles=filename="{formatted_subtitle_path}":force_style=...
None of these attempts have succeeded; the ffmpeg process always fails to start or errors out immediately.
What is the definitive, cross-platform way to format the filename string for ffmpeg's subtitles filter so that it can correctly handle paths containing single quotes?