Mr.Slow
Mr.Slow

Reputation: 560

how to add subtitles in video with ffmpeg filter?

I am having hard time adding .srt subtitles to the newly creating video. I am using Python.

subtitles:

f"{PROJECT_PATH}/data/subtitles/final_subtitle_srt/all_slides.srt"

I have checked they are correct.

pieces of my code that does not work:

audio = f'{PROJECT_PATH}/data/ppt-elements/audio_{file_id}.txt'
        images = f'{PROJECT_PATH}/data/ppt-elements/images_{file_id}.txt'

        image_input = ffmpeg.input(images, f='concat', safe=0, t=seconds).video
        audio_input = ffmpeg.input(audio, f='concat', safe=0, t=seconds).audio

inputs = [image_input, audio_input]
 
command = (
            ffmpeg.filter('subtitles', f"{PROJECT_PATH}/data/subtitles/final_subtitle_srt/all_slides.srt")
            .output(*inputs,f"{PROJECT_PATH}/data/subtitles/final_subtitle_srt_all_slides.srt", 
                f"{PROJECT_PATH}/data/final-{file_id}.mp4", 
                vf="fps=10,format=yuv420p",
                preset="veryfast", 
                shortest=None, 
                r=10, 
                max_muxing_queue_size=4000,
                **additional_parameters,
            )
)

Am I using subtitles filter well?

Upvotes: 0

Views: 1129

Answers (1)

Rotem
Rotem

Reputation: 32124

subtitles filter applies the video, we may use it as follows:

image_input = ffmpeg.input(images, r=fps, f='concat', safe=0, t=seconds).video.filter('subtitles', f"{PROJECT_PATH}/all_slides.srt") 

In case there are other video filters to be chain we may chain the filters:

image_input = ffmpeg.input(images, r=fps, f='concat', safe=0, t=seconds).video.filter('fps', fps=fps).filter('format', pix_fmts='yuv420p').filter('subtitles', f"{PROJECT_PATH}/all_slides.srt")

We don't need to pass the subtitles stream as an input stream (use the subtitles only in the subtitles filter).


Code sample:

import ffmpeg

PROJECT_PATH = '/Tmp/ffmpeg'
file_id = '1'
audio = f'{PROJECT_PATH}/audio_{file_id}.txt'
images = f'{PROJECT_PATH}/images_{file_id}.txt'
seconds = 10
fps = 10

#image_input = ffmpeg.input(images, r=fps, f='concat', safe=0, t=seconds).video.filter('fps', fps=fps).filter('format', pix_fmts='yuv420p').filter('subtitles', f"{PROJECT_PATH}/all_slides.srt")
image_input = ffmpeg.input(images, r=fps, f='concat', safe=0, t=seconds).video.filter('subtitles', f"{PROJECT_PATH}/all_slides.srt")
audio_input = ffmpeg.input(audio, f='concat', safe=0, t=seconds).audio

command = (
    ffmpeg.
    output(image_input, audio_input, f"{PROJECT_PATH}/final-{file_id}.mp4",
    vcodec='libx264',    
    preset="veryfast", 
    acodec='aac',
    shortest=None,
    #r=fps,
    max_muxing_queue_size=4000)
    .global_args('-report')  # Create a report file
)

command.overwrite_output().run()

Note that concatenating images using concat demuxer is not a good practice because images don't have timetags.
I recommend you to rename the images to numbered sequence 0001.png, 0002.png, 0003.png... and use ffmpeg.input('%04d', r=fps, ...) without fps filter and without r=fps for the output.

Upvotes: 1

Related Questions