To concatenate multiple video segments and permanently burn embedded subtitles into the final output, you must use FFmpeg’s concat demuxer for efficient merging and the
subtitles filter to hardcode text. This process inherently requires re-encoding because modifying subtitle streams forces a video recompression. The most reliable method involves creating a file list of your cut segments, applying the subtitle overlay during the muxing phase, and ensuring keyframes align to prevent playback glitches in standard MP4 containers.
Preparing Your Video Segments
Before merging files, you need individual video clips that contain the embedded subtitle tracks you wish to preserve. If your source files are large or complex, it is often faster to cut them first using stream copying rather than full decoding. You can extract specific time ranges without quality loss by using the
-c copy flag alongside precise timestamp markers.
For example, to grab a segment from 10 seconds to 30 seconds:
ffmpeg -i input.mp4 -ss 00:00:10 -to 00:00:30 -c copy part1.mp4
Note that using
-c copy preserves the original codec parameters. As discussed in our guide on
FFmpeg: Honoring Outpoint Timestamps with Concat Demuxer and Preserving Input Codec Parameters, maintaining consistent codecs across all segments is crucial for the concat demuxer to work seamlessly. If your segments have different resolutions, frame rates, or codecs, the concat demuxer will fail, and you will need to transcode them to a uniform format first.
Creating the Concat File List
FFmpeg’s concat demuxer reads a plain text file that lists each video segment. This approach is significantly more efficient than listing every file directly in the command line, especially when dealing with dozens of cuts. Create a text file named
mylist.txt and add each segment on a new line using the
file directive.
The content of
mylist.txt should look like this:
file 'part1.mp4'
file 'part2.mp4'
file 'part3.mp4'
Ensure there are no extra spaces after the filename and that the paths are relative to where you run the FFmpeg command, or use absolute paths if necessary. This list tells FFmpeg exactly which chunks to stitch together in order. For more advanced concatenation scenarios involving variable frame rates, refer to
How to Concatenate Videos with FFmpeg.
Hardcoding Subtitles During Merging
This is the critical step where re-encoding becomes mandatory. You cannot simply copy the subtitle stream while also modifying the video stream (which happens when you apply filters). To embed subtitles visually into the video frames, you must use the
subtitles video filter. This filter decodes the subtitle track, renders it as an image overlay, and composites it onto every video frame.
Your complete command structure looks like this:
ffmpeg -f concat -safe 0 -i mylist.txt -vf "subtitles=sub.mkv" -c:v libx264 -crf 23 -preset fast -c:a aac output.mp4
Let’s break down the components. The
-f concat flag specifies the format. The
-vf "subtitles=sub.mkv" applies the filter, pointing to your subtitle file (which can be MKV, SRT, ASS, etc.). Because we are adding a video filter, FFmpeg ignores
-c copy and defaults to encoding. We explicitly set
-c:v libx264 for the video codec and
-c:a aac for audio, which is standard for MP4 compatibility. The
-crf 23 sets a good balance between quality and file size.
If your subtitles are already embedded inside the video files themselves (rather than being separate
.srt or
.mkv files), you can still use the filter by referencing the internal track. However, it is often cleaner to extract the subtitle track first using
ffmpeg -i input.mp4 -map 0:s:0 sub.srt and then point the filter to that extracted file.
Handling Keyframes and Sync Issues
When concatenating videos, misaligned keyframes can cause stuttering or sync issues, particularly when hardcoding subtitles changes the frame-by-frame composition. Ensuring that your input segments start on keyframe boundaries helps mitigate this. While cutting with
-c copy might not always land perfectly on keyframes depending on the container, the concat demuxer handles basic stitching well.
If you experience audio-video desync after hardcoding, check your subtitle timing. The
subtitles filter relies on the timestamps within the subtitle file matching the video duration. If your cuts altered the presentation timestamps (PTS) without adjusting the subtitle file, the text may appear at wrong times. In such cases, you may need to remux the segments to reset PTS values before applying the subtitle filter.
Frequently Asked Questions
Can I hardcode subtitles without re-encoding the video?
No, hardcoding subtitles requires rendering text onto video frames, which necessitates a full video re-encode. You can only avoid re-encoding if you are extracting subtitles to a separate file or attaching them as a selectable track.
Why does my concatenated video stutter after adding subtitles?
Stuttering often results from non-keyframe aligned cuts or mismatched frame rates between segments. Ensure all input files share the same resolution and frame rate, and consider using the
-fflags +genpts flag to regenerate packet timestamps during the merge.
How do I handle multiple subtitle languages in one file?
You can specify multiple subtitle files in the filter using a comma-separated list, but FFmpeg will only render the first valid one unless you map specific tracks. It is generally easier to choose one language track per output file to avoid conflicts.
What is the best CRF value for high-quality output?
A Constant Rate Factor (CRF) of 18-23 provides visually lossless to high-quality results. Lower numbers mean higher quality and larger files; 23 is the default and offers a solid compromise for general distribution.