Adding multiple English subtitle streams to an MP4 file with FFmpeg requires using the -c:s mov_text or -c:s srt encoder for each subtitle input, rather than relying on the default behavior which often overwrites previous streams. By explicitly mapping each subtitle file to a distinct stream index and ensuring the container format supports embedded text tracks, you can successfully bundle multiple language variants into a single MP4 output without data loss or unexpected overwriting.
Understanding MP4 Subtitle Container Support
The MP4 container format is fully capable of holding multiple subtitle streams simultaneously. A common misconception, often leading to troubleshooting errors, is that MP4 files are limited to a single subtitle track. This is incorrect; modern MP4 containers support various subtitle formats includingmov_text, srt, vtt, and even binary formats like webvtt. The issue usually arises not from container limitations, but from how FFmpeg handles stream mapping and encoding when multiple inputs are provided. If you do not explicitly map every subtitle file to a separate output stream, FFmpeg may discard earlier subtitles in favor of the last one processed, resulting in the "unexpected output" where only one set of subtitles appears.
To ensure all subtitles are preserved, you must treat each subtitle file as a distinct input stream and assign it a unique position in the output file. This involves careful use of the -map option, which overrides FFmpeg’s automatic stream selection logic. Without explicit mapping, FFmpeg might select only one video, one audio, and one subtitle stream based on its internal priority rules, ignoring the others entirely.
The Role of the mov_text Codec
For standard SRT-style subtitles, themov_text codec is the most reliable choice for MP4 containers. It converts standard text-based subtitles into a format native to QuickTime and MP4 specifications. When adding multiple subtitles, each subtitle input should be encoded using this specific codec. Using other codecs like ass (Advanced SubStation Alpha) can sometimes cause compatibility issues with certain players if not strictly handled, though mov_text remains the safest bet for broad compatibility across Windows, macOS, and mobile devices.
If your subtitles are already in a different format, such as WebVTT, you may need to convert them first or use the appropriate encoder. However, for most users dealing with standard .srt files, forcing the mov_text encoding ensures that the metadata is correctly interpreted by media players.
Constructing the Correct FFmpeg Command
The core of the solution lies in the command structure. You need to provide each subtitle file as an input using the-i flag, followed by explicit mapping commands. Consider a scenario where you have a video file video.mp4, an English subtitle file en.srt, and another English variant or translation en_alt.srt (perhaps for hearing impaired descriptions or alternative phrasing).
The basic structure looks like this:
ffmpeg -i video.mp4 -i en.srt -i en_alt.srt -map 0:v -map 0:a -map 1:s -map 2:s -c:v copy -c:a copy -c:s mov_text output.mp4
Let's break down why this works. The -map 0:v maps the video from the first input (video.mp4). The -map 0:a maps the audio from the same input. Crucially, -map 1:s maps the subtitle stream from the second input (en.srt) to the first subtitle slot in the output. Similarly, -map 2:s maps the subtitle from the third input (en_alt.srt) to the second subtitle slot. The -c:v copy and -c:a copy flags ensure that the video and audio are not re-encoded, preserving quality and speeding up the process. The -c:s mov_text applies the correct subtitle encoding to all mapped subtitle streams.
Without the explicit -map commands for subtitles, FFmpeg might ignore en_alt.srt entirely, or worse, merge them incorrectly. By specifying the source index (1 and 2) and the stream type (s), you guarantee that both files are included in the final container.
Verifying Stream Placement and Metadata
After running the command, it is essential to verify that both subtitle streams are present and correctly labeled. You can use the following command to inspect the output file:ffprobe output.mp4
Look for the subtitle sections in the output. You should see two distinct subtitle streams, each with a codec_name of mov_text or similar, and ideally with metadata tags indicating their language. If you want to tag them specifically as English, you can add language tags during the mapping process:
-metadata:s:s:0 lang=eng -metadata:s:s:1 lang=eng
This step is particularly important if you intend to switch between these subtitles in a player. While they are both English, having distinct stream indices allows players to list them separately. Some advanced players allow you to rename these streams via UI settings, but proper tagging at creation time ensures better initial recognition.
Common Pitfalls and Troubleshooting
One frequent error occurs when users try to concatenate subtitle files before processing. Do not attempt to mergeen.srt and en_alt.srt into a single file manually unless you are sure the timestamps do not overlap and the formatting is identical. It is much cleaner and more robust to keep them as separate inputs and let FFmpeg handle the multiplexing. Another pitfall is assuming that the order of -i arguments dictates the final stream order without using -map. Always rely on -map for deterministic results.
If you encounter errors regarding unsupported codecs, ensure your FFmpeg build supports mov_text. Most standard builds do, but minimal compilations might lack it. In such cases, converting subtitles to WebVTT and using the webvtt codec is a viable alternative, as WebVTT has growing support in HTML5 video players and some native MP4 players.
For further details on managing subtitle streams within complex multimedia projects, you might find it useful to review strategies for removing unwanted subtitles, as discussed in How to Remove All But 2 Subtitles in FFmpeg Without Knowing Their Index Number. Additionally, understanding how to selectively keep subtitles while converting audio can help refine your workflow, as outlined in How to Copy Video, Covert All Audio Streams to AC3, and Only Keep Subtitles in English Using FFmpeg.
Frequently Asked Questions
Can I mix different subtitle formats in one MP4?
Yes, you can mix formats like SRT and WebVTT in a single MP4 file, provided you use the appropriate encoder for each stream. For example, you can encode one stream with-c:s mov_text and another with -c:s webvtt. However, player compatibility varies, so sticking to a single format like mov_text is recommended for maximum reliability across all devices.
Why does my player only show one subtitle track?
Most likely, the player is configured to display only one subtitle track at a time, or it defaults to the first one found. Check your player’s settings to see if there is an option to enable multiple tracks or to manually select which subtitle stream to activate. Some older players may also struggle with multiplemov_text streams if the metadata tags are missing.
Do I need to re-encode the video to add subtitles?
No, adding subtitle streams is a muxing operation, not a transcoding one. By using-c:v copy, you avoid re-encoding the video, which saves significant time and preserves original quality. The subtitles are stored as separate data tracks within the container, independent of the video bitstream.
What if I get an error about duplicate stream IDs?
This error typically occurs when FFmpeg cannot automatically assign unique identifiers to the new streams. Using explicit-map commands resolves this by clearly defining the source and destination for each stream. Ensure that you are not accidentally mapping the same input stream multiple times to conflicting positions in the output.
Is mov_text compatible with all MP4 players?
mov_text is widely supported on Apple devices, Windows Media Player, and most modern web browsers via HTML5 video elements. However, some specialized or very old hardware players might prefer other formats like srt wrapped in a specific way or webvtt. If you face compatibility issues, testing with webvtt is a good fallback strategy.