Programster's Blog

Tutorials focusing on Linux, programming, and open source

Subtitles Cheatsheet

Listing Tracks

The easiest way to list the subtitle tracks is by running:

mkvmerge -i myFile.mkv

Extraction

Mkv files often come with subtitles "buried" within them which are not "hard subbed" (built into the image). These can be extracted with:

mkvextract tracks input.mkv \
[track number]:subtitles.txt

This will not remove the subtitles from the mkv file.

This may extract an ass or srt file

Remove Specific Tracks

If you want to remove a subtitle track, you need to recreate the mkv file and copy across the tracks that you want to keep. The command below will keep tracks 1 and 3, so we are "removing" track 2 (it won't be in the output file).

mkvmerge -o output.mkv \
--subtitle-tracks 1,3 \
input.mkv

Remove All Subtitles

The command below will create an output.mkv file from input.mkv, but with no subtitles within it.

mkvmerge -o output.mkv \
--no-subtitles \
input.mkv

Merging

If you have two separate files, one MKV video file, and one srt subtitles file, you can merge them easily with:

mkvmerge -o output.mkv \
input.mkv \
subtitles.srt

If you have an mp4 file instead of an mkv, you can losslessly convert it to an MKV file before performing the step above.

Conversion

You can convert from ass to srt with this tool. However, I found that it would insert ? characters wherever it found characters it didn't understand. For example there is a special character for three dots ... which is really common.

Synchronization

VLC media player can use g and h to adjust times to see how much of a delay you need

You can shift srt subtitles (even by fractions of a second) with this script:

#!/bin/bash

set -o errexit -o noclobber -o nounset -o pipefail

date_offset="$1"

shift_date() {
    date --date="$1 $date_offset" +%T,%N | cut -c 1-12
}

while read -r line
do
    if [[ $line =~ ^[0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9]\ --\>\ [0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9]$ ]]
    then
        read -r start_date separator end_date <<<"$line"
        new_start_date="$(shift_date "$start_date")"
        new_end_date="$(shift_date "$end_date")"
        printf "%s %s %s\n" "$new_start_date" "$separator" "$new_end_date"
        echo "New date"
    else
        printf "%s\n" "$line"
    fi
done

Example usage:

./shifter.sh "+3.5 seconds" < input.srt > output.srt

References