Bash script to adjust srt/subtitles files

Terminal logo

It's quite common to have synchronization problems with subtitles files. Indeed, very often the subtitle file is not adapted to our source video file. So we usually have a delay that goes from a few milliseconds to a few seconds which can be quite annoying when playing.

It's possible, with most players (vlc, mpv or mplayer); see here; to adjust the delay, but the configuration will be lost at the next playback. So it is more interesting to be able to adjust by directly modifying the subtitle file.

And I have developed a script to do just that.

Usage

  • Usage :
user@host:~$ ./shebangthe_srt.sh -f [srt file] -t '[+/- time]'
  • Substract 400 miliseconds to subtitles :
user@host:~$ ./shebangthe_srt.sh -f /home/std/Running.on.Empty.1988.1080p.BluRay.x264.AAC.5.1-POOP.srt -t '- 0.400'
  • Add 1.400 seconds to subtitles :
user@host:~$ ./shebangthe_srt.sh -f /home/std/Running.on.Empty.1988.1080p.BluRay.x264.AAC.5.1-POOP.srt -t '+ 1.400'

srt file format

  • This script has been built to work with this kind or srt files only :
[…]
1126
01:55:12,527 --> 01:55:14,461
I love you.

1127
01:55:20,735 --> 01:55:22,669
I really love you.

Code

#! /bin/bash

IFS=$'\n'
option_F_found=0
option_T_found=0

usage()
{
        echo "usage: ./subtitles.sh -f [srt file] -t '[+/- time]'"
        echo "ex : ./subtitles.sh -f /home/std/lecuisinierlevoleursafemmeetsonamant.srt -t '- 18.100'"
        echo "ex : ./subtitles.sh -f /home/std/lecuisinierlevoleursafemmeetsonamant.srt -t '+ 18.100'"
        echo ""
        exit 3
}

while getopts f:t: OPTNAME; do
        case "$OPTNAME" in
        f)
                FILE="$OPTARG"
                option_F_found=1
                ;;

        t)
                TIME="$OPTARG"
                option_T_found=1
                ;;


        *)
                usage
                ;;
        esac
done

if [ "$option_F_found" -eq "0" ] || [ "$option_T_found" -eq "0" ]; then
        usage
fi

FunctionDuration()
{
        duration_temp=$(date -d "1983-12-12 $1" "+%s.%3N")
        duration_diff=$(echo "scale=3; $duration_temp $TIME" | bc -l)
        duration_dest=$(date -d"@$duration_diff" "+%H:%M:%S,%3N")
        echo "$duration_dest"
}


for i in $(grep -E "[0-9]{2}:[0-9]{2}\,[0-9]{3}" "$FILE");
do
        A=$(echo "$i" | sed 's/\([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\,[0-9]\{3\}\) --> \([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\,[0-9]\{3\}\)/\1/')
        B=$(echo "$i" | sed 's/\([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\,[0-9]\{3\}\) --> \([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\,[0-9]\{3\}\)/\2/')
        VAL1=$(FunctionDuration "$A")
        VAL2=$(FunctionDuration "$B")
        echo "working on $A --> $B"
        sed -i "s/$i/$VAL1 --> $VAL2/" "$FILE"
done
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Contact :