-1

ENVIRONMENT:

Python 3.10

Windows 11

ffmpeg-python==0.2.0

CONTEXT:

I am trying to add hardcoded subtitles on a video with ffmpeg and Pyton.

PROBLEM:

ffmpeg is not able to find the path of my ass subtitle file. So I tried different ways with different methods. I asked different AI to try to find a solution. Impossible! It is such a crazy issue that I tested the code from a "test" folder located on the root "C:" from the command line wid nows. No AI was able to fixed this issue. I tried chatGPT, deepseek, claude.ai. They proposed different solutions which were not working.

THE CODE :

import os
import ffmpeg
import subprocess

def add_subtitles_with_ass(video_path, ass_path, output_path):

    video_path = os.path.abspath(video_path)
    ass_path = os.path.abspath(ass_path)
    output_path = os.path.abspath(output_path)

    print(f"🚀 Add susbtitiles with ASS : {ass_path}")
    ass_path_escaped = rf'"{ass_path}"'

    try:
        ffmpeg.input(video_path).output(output_path, vf=f"ass='{ass_path_escaped}'").run(overwrite_output=True)
        print(f"✅ Subtitles added with success : {output_path}")
    except Exception as e:
        print(f"❌ ERROR when adding subtitles : {e}")


def add_subtitles_with_ass_with_subprocess(video_path, ass_path, output_path):
    video_path = os.path.abspath(video_path)
    ass_path = os.path.abspath(ass_path)
    output_path = os.path.abspath(output_path)

    print(f"🚀 Add subtitles with ASS : {ass_path}")

    try:
        command = [
            'ffmpeg',
            '-i', video_path,
            '-vf', f"ass='{ass_path}'",
            '-c:a', 'copy',
            output_path,
            '-y'  # Overwrite output file without asking
        ]

        subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print(f"✅ Subtitles added with success : {output_path}")
    except subprocess.CalledProcessError as e:
        print(f"❌ ERROR when adding subtitles : {e.stderr.decode('utf-8')}")


print(f"Test 1 -----------------------------------------------------------------------")
ass_path="G:\Mi unidad\Python\Scripts\shorts_videos\10000views_and_higher\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.ass"
video_path="G:\Mi unidad\Python\Scripts\shorts_videos\10000views_and_higher\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo.mp4"
output_path="G:\Mi unidad\Python\Scripts\shorts_videos\10000views_and_higher\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.mp4"
add_subtitles_with_ass(video_path, ass_path, output_path)
print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 2 -----------------------------------------------------------------------")
ass_path2="G:\\Mi unidad\\Python\\Scripts\\shorts_videos\\10000views_and_higher\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.ass"
video_path2="G:\\Mi unidad\\Python\\Scripts\\shorts_videos\\10000views_and_higher\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo.mp4"
output_path2="G:\\Mi unidad\\Python\\Scripts\\shorts_videos\\10000views_and_higher\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.mp4"
add_subtitles_with_ass(video_path2, ass_path2, output_path2)

print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 3 -----------------------------------------------------------------------")
ass_path3="G:/\Mi unidad/\Python/\Scripts/\shorts_videos/\10000views_and_higher/\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.ass"
video_path3="G:/\Mi unidad/\Python/\Scripts/\shorts_videos/\10000views_and_higher/\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo.mp4"
output_path3="G:/\Mi unidad/\Python/\Scripts/\shorts_videos/\10000views_and_higher/\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.mp4"
add_subtitles_with_ass(video_path3, ass_path3, output_path3)

print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 4 -----------------------------------------------------------------------")
ass_path4="G:/\\Mi unidad/\\Python/\\Scripts/\\shorts_videos/\\10000views_and_higher/\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.ass"
video_path4="G:/\\Mi unidad/\\Python/\\Scripts/\\shorts_videos/\\10000views_and_higher/\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo.mp4"
output_path4="G:/\\Mi unidad/\\Python/\\Scripts/\\shorts_videos/\\10000views_and_higher/\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.mp4"
add_subtitles_with_ass(video_path4, ass_path4, output_path4)




print(f"Test 1 with subprocess -----------------------------------------------------------------------")
add_subtitles_with_ass_with_subprocess(video_path, ass_path, output_path)
print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 2 with subprocess -----------------------------------------------------------------------")
add_subtitles_with_ass_with_subprocess(video_path2, ass_path2, output_path2)
print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 3 with subprocess -----------------------------------------------------------------------")
add_subtitles_with_ass_with_subprocess(video_path3, ass_path3, output_path3)
print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 4 with subprocess -----------------------------------------------------------------------")
add_subtitles_with_ass_with_subprocess(video_path4, ass_path4, output_path4)
print(50*"*")
print(50*"*")
print(50*"*")

#======================= IT DIDN'T WORK, SO LET'S DO WITH RELATIVE PATH ===================================


print(f"Test 1 with relative path -----------------------------------------------------------------------")
ass_path_relative="10000views_and_higher\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.ass"
video_path_relative="10000views_and_higher\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo.mp4"
output_path_relative="10000views_and_higher\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.mp4"
add_subtitles_with_ass(video_path_relative, ass_path_relative, output_path_relative)
print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 2  with relative path -----------------------------------------------------------------------")
ass_path2_relative="10000views_and_higher\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.ass"
video_path2_relative="10000views_and_higher\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo.mp4"
output_path2_relative="10000views_and_higher\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.mp4"
add_subtitles_with_ass(video_path2_relative, ass_path2_relative, output_path2_relative)

print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 3  with relative path -----------------------------------------------------------------------")
ass_path3_relative="10000views_and_higher/\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.ass"
video_path3_relative="10000views_and_higher/\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo.mp4"
output_path3_relative="10000views_and_higher/\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.mp4"
add_subtitles_with_ass(video_path3_relative, ass_path3_relative, output_path3_relative)

print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 4  with relative path -----------------------------------------------------------------------")
ass_path4_relative="10000views_and_higher/\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.ass"
video_path4_relative="10000views_and_higher/\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo.mp4"
output_path4_relative="10000views_and_higher/\\Li2zY7XcOf0_Matthew_Hussey_flip_h_BW_with_logo_EN.mp4"
add_subtitles_with_ass(video_path4_relative, ass_path4_relative, output_path4_relative)




print(f"Test 1 with subprocess  with relative path -----------------------------------------------------------------------")
add_subtitles_with_ass_with_subprocess(video_path, ass_path, output_path)
print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 2 with subprocess  with relative path -----------------------------------------------------------------------")
add_subtitles_with_ass_with_subprocess(video_path2_relative, ass_path2_relative, output_path2_relative)
print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 3 with subprocess  with relative path -----------------------------------------------------------------------")
add_subtitles_with_ass_with_subprocess(video_path3_relative, ass_path3_relative, output_path3_relative)
print(50*"*")
print(50*"*")
print(50*"*")

print(f"Test 4 with subprocess  with relative path -----------------------------------------------------------------------")
add_subtitles_with_ass_with_subprocess(video_path4_relative, ass_path4_relative, output_path4_relative)
print(50*"*")
print(50*"*")
print(50*"*")

THE OUTPUT:

The output was too large to post it here. I uploaded it on my github :

https://github.com/gauthierbuttez/public/blob/master/output_ffmpeg.log

I also zipped and uploaded all the files to make reproducing the issue on your computer easy:

https://github.com/gauthierbuttez/public/blob/master/test.zip

Is there any kind super Python Master in the place?

1 Answer 1

0

It's just a quirk of how FFmpeg expects a absolute path in the ass filter. It requires you to escape every special character because of the way it parses strings internally. The most surprising fact is that the colon (:) also needs to be escaped.

So, when passing absolute path in terminal it would look like this:

ffmpeg -i video.mp4 -vf "ass='G\:\\Shorts_videos\\Li2zY7XcOf0.ass'" -c:a copy out.mp4 -y

Because of that in Python you would need to double escape backslashes and escape colon. So absolute path in string literal would look like this in Python:

# As a normal string literal
ass_path = "G\\:\\\\Shorts_videos\\\\Li2zY7XcOf0.ass"

# It is easier to read as a raw string literal, in my opinion,
# because it looks exactly like the one passed in terminal.
# So following would also be valid:
ass_path = r"G\:\\Shorts_videos\\Li2zY7XcOf0.ass"

P.S. In other paths (for video and output), I also recommend using raw string literals. Otherwise, sequences like \t in a string might be mistakenly interpreted as a tab or another escape sequence. By prefixing the string with r, you won’t need to manually escape characters in such cases.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.