Script Bash : Ajuster le Décalage des Sous-titres .srt
- Mise à jour le 27 juil. 2025
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