logo rss

Script Bash : Ajuster le Décalage des Sous-titres .srt

Terminal logo

Il est courant de rencontrer des problèmes de synchronisation avec les fichiers de sous-titres. En effet, il arrive fréquemment que le fichier de sous-titres ne corresponde pas parfaitement à la piste vidéo utilisée, ce qui se traduit par un décalage pouvant aller de quelques millisecondes à plusieurs secondes — rendant le visionnage rapidement désagréable.

La plupart des lecteurs multimédias (VLC, MPV, MPlayer, etc.) permettent d’ajuster temporairement ce décalage (voir ici), mais ces réglages sont perdus à chaque nouvelle lecture. Il peut donc être plus pratique d’effectuer cette correction directement dans le fichier de sous-titres.

J’ai justement développé un script en Bash pour cela.

Utilisation

Utilisez la syntaxe suivante pour ajuster le minutage d’un fichier de sous-titres SRT :

user@host:~$ ./shebangthe_srt.sh -f [srt file] -t '[+/- time]'
  • Soustraire 0,400 seconde aux sous-titres :
user@host:~$ ./shebangthe_srt.sh -f /home/std/Running.on.Empty.1988.1080p.BluRay.x264.AAC.5.1-POOP.srt -t '- 0.400'
  • Ajouter 1,400 seconde aux sous-titres :
user@host:~$ ./shebangthe_srt.sh -f /home/std/Running.on.Empty.1988.1080p.BluRay.x264.AAC.5.1-POOP.srt -t '+ 1.400'

Format de fichier SRT

Ce script est conçu pour fonctionner exclusivement avec des fichiers de sous-titres SRT standard suivant le format illustré ci-dessous :

[…]
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.

Script Bash

Le script Bash suivant modifie les horodatages dans un fichier de sous-titres .srt, vous permettant de décaler le minutage vers l'avant ou vers l'arrière avec une précision à la milliseconde près.

#! /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