4

I have a couple of srt subtitle tracks for an mp4 video. How do I make them into mkv using ffmpeg/avconv?

I would like to use space efficiently. Performing conversion on Darwin v13. I will be grateful if anyone could help me with that. Thanks in advance.

I can use any shell that makes a sufficiently convenient environment for the operation. However, I mostly use zsh.

Example

/some/path
    Lecture_About_Evolution_of_Evolution.mp4
    english.srt
    native.srt
    perl.srt
    elven.srt

I want to generate Lecture.mkv out of the mp4 file and all *.srt subtitle tracks. But I have no idea how.

2 Answers 2

11

Using ffmpeg:

ffmpeg -i video.mp4 -i subtitle1.srt -i subtitle2.srt -map 0 -map 1 -map 2 \
-c copy -metadata:s:s:0 language=eng -metadata:s:s:1 language=ipk output.mkv
  • This will stream copy (-c copy) all streams, so re-encoding is avoided.

  • The default stream selection will only choose one stream per stream type, so -map is used to manually override that.

  • I don't use avconv, so I don't know if any of this info will apply. Make sure you're using a recent, real version of ffmpeg. Development is very active and the counterfeit "ffmpeg" from the Libav fork is old and dead. See the FFmpeg Download page for various options.

7
  • Is it possible to make it independant from the number of subtitle tracks?
    – theoden8
    Aug 17, 2015 at 22:46
  • @theoden Can you explain in more detail? I'm not quite following what you're asking.
    – llogan
    Aug 17, 2015 at 23:15
  • I mean so that all srts of a mask and an mp4 file are combined into one mkv file. Although the solution you provided seems to be working, it aims only 2 subtitle tracks. Is there a scheme for doing that? I added an example to make myself clear. Sorry for being slightly misunderstood.
    – theoden8
    Aug 18, 2015 at 1:45
  • @theoden You are looking for a complete script? I'm not a zsh user, but I recommend looking at globbing and arrays. shellcheck is always helpful for bash.
    – llogan
    Aug 18, 2015 at 2:25
  • @theoden You will have to explicitly list each SRT input as shown in the example.
    – llogan
    Aug 18, 2015 at 16:10
1

Here's the full answer that I made according to my needs.

Code

#!/bin/zsh

mkv_sub_getshort() {
    sub=$1
    sub="${sub%.${sub:e}}"
    sub="$(sed 's/^.*[[:punct:]]//g' <<< "$sub")"
    echo $sub
}

mkv_maker() {
    local c=0
    for i in *srt; do
        LOCAL_SUB[((++c))]="$i"
        LOCAL_SUB_SHORT[$c]="$(mkv_sub_getshort "$i")"
    done

    local W="   "
    printf "ffmpeg -i *mp4"
    printf "$(for i in ${LOCAL_SUB[*]}; do printf "${W}-i \"$i\""; done)"
    printf "$(for i in $(seq $((${#LOCAL_SUB} + 1))); do printf "${W}-map $((i - 1))"; done)"
    printf "${W}-c copy"
    printf "$(for i in $(seq ${#LOCAL_SUB}); do ((--i)); printf "${W}-metadata:s:s:$i language=${LOCAL_SUB_SHORT[$((i + 1))]%.srt}"; done)"
    printf "${W}output.mkv"

    unset LOCAL_SUB LOCAL_SUB_SHORT
}

mkv_maker

This generates the command for the number of subtitle tracks in folder.

Sample output

$ ls -a
.           ..          mkvmaker vid.mp4     vid_eng.srt vid_fr.srt  vid_rus.srt vid_swe.srt

$ ./mkvmaker
ffmpeg -i *mp4 -i "vid_eng.srt" -i "vid_fr.srt" -i "vid_rus.srt" -i "vid_swe.srt" -map 0 -map 1 -map 2 -map 3 -map 4 -c copy -metadata:s:s:0 language=eng -metadata:s:s:1 language=fr -metadata:s:s:2 language=rus -metadata:s:s:3 language=swe output.mkv

Credits

Credit goes to LordNeckbeard for the previous answer which helped me to understand how to make this working.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .