{{tag>vidéo}}
====== Script d'extraction des sous-titres d'une vidéo TS en SRT======
Script bash permettant de convertir un groupe de fichiers vidéos de même extension contenu dans un même répertoire et d'extraire ses sous-titre en fichier srt.
Contrairement aux idées reçues il ne suffit pas renommer l'extension d'un fichier TS (.ts) en MKV (.mkv) pour pouvoir l'extraire avec MKVToolnix-gui.
FFMPEG le fait par contre très bien.
===== Algorithme =====
Inspiré de l'algorithme : [[tutoriel:vobsub_srt|Conversion de sous-titres VobSub en SRT]]
* étudier fichier TS contenant sous-titres vobsub avec ffmpeg
* étudier les numéros des pistes "subtitles"
* extraire sous-titres vobsub dans une vidéos mastroika
* extraire les sous-titres des vidéos mastroïka avec mkvextract
* convertir fichier .sub et .idx en tiff;
* reconnaissance de caractère de chaque tiff avec cunéiform
* création d'un fichier srt
==== Exemple de séquence bash correspondant à l'algorithme ====
ffmpeg -i data0003.ts 2>&1 | grep subtitle
mkdir data0003
ffmpeg -i data0003.ts -map 0:4 -map 0:5 -vn -an -scodec dvdsub data0003.mkv
mkvextract tracks "data0003.mkv" -c ISO8859-1 0:data0003/0_
mkvextract tracks "data0003.mkv" -c ISO8859-1 1:data0003/1_
subp2tiff --sid=0 -n data0003/0_
subp2tiff --sid=1 -n data0003/1_
for eachTiff in data0003/*.tif; do cuneiform -l fra -f text -o $eachTiff.txt $eachTiff; done
subptools -s -w -t srt -i data0003/0_.xml -o 0_.srt
subptools -s -w -t srt -i data0003/1_.xml -o 1_.srt
==== Exemple de conversion de fichier TS en MKV avec FFMPEG ====
La commande suivante permet d'obtenir l'info : ffmpeg -i
9 pistes :
0:0 vidéo
0:1 ne contenant pas de données
0:2 Audio
0:3 ne contenant pas de données
0:5 Subtite
0:6 subtitle
0:7 piste non reconnue par ffmpeg
0:8 piste non reconnue par ffmpeg
ffmpeg -threads 4 -i data0003.ts -map 0:0 -map 0:2 -map 0:5 -map 0:6 -acodec copy -vcodec copy -scodec dvdsub output.mkv
//-threads// pour pouvoir utiliser un traitement multiprocesseurs
-// map// pour spécifier toutes les pistes à utilisables
//-acodec// suivi de //copy// pour le traitements des pistes audio
//-vcodec// suivi de //copy// pour le traitement de la piste vidéo
//
-scodec// suivi de //dvdsub// pour le traitement des sous-titres
===== dépendances à installer =====
**[[apt>ffmpeg]]** - une collection de logiciels libres destinés au traitement de flux audio ou vidéo
**[[apt>mkvtoolnix]]** éventuellement aussi **[[apt>mkvtoolnix-gui]]** - un ensemble d'outils permettant de créer, de modifier et d'inspecter des fichiers Matroska
**[[apt>cuneiform]]** - Système de reconnaissance optique de caractères multi-langue
**[[apt>ogmrip]]** - Application pour extraire et encoder des DVDs
===== Script ts2srt =====
[[https://raw.githubusercontent.com/albanmartel/ts2srt/master/ts2srt.bash| ts2srt.bash]]
# ----------------------------------------------------
# Script''ts2srt''
# ----------------------------------------------------
# Par ''Alban MARTEL''
# Courriel : albanmartel(POINT)developpeur(AT)gmail(POINT)com
# Utilisant comme base de travail le script de beguam
# http://doc.ubuntu-fr.org/tutoriel/vobsub_srt
# License : GNU GPL
# Ce script permet d'extraire les sous-titres d'une video TS et de les transformer en SRT éditable.
#
# Depends :
# ffmpeg est une collection de logiciels libres destinés au traitement de flux audio ou vidéo
# mkvToolnix (interface graphique pour mkvmerge) est un ensemble d'outils permettant de créer, de modifier et d'inspecter des fichiers Matroska
# cuneiform - Système de reconnaissance optique de caractères multi-langue
# ogmrip - Application pour extraire et encoder des DVDs
#
# Date : 26/08/2015
# version : 0.1
# Mise-à-jour :
# ----------------------------------------------------
# !/bin/bash
# OUTPUT-COLORING
red=$( tput setaf 1 )
green=$( tput setaf 2 )
NC=$( tput sgr0 ) # or perhaps: tput sgr0
#NC=$( tput setaf 0 ) # or perhaps: tput sgr0
function readDirectoryPath(){
echo -n "chemin absolu du répertoire des vidéos où extraire les sous-titres : "
read directory;
courant_directory=$(pwd);
if [[ ! -e "$directory" ]]; then
echo "incorrect";
readDirectoryPath;
fi
cd $directory;
directory=$(pwd);
cd $courant_directory;
echo $directory;
#testIfAnyFileIsPresent=$(find . -maxdepth 1 -iname "*.$extension" | wc -l);
}
function presentationOfFileDirectory(){
message=$("<<"$directory">> contient les fichiers suivants : ");
files=$(ls $directory/*.*);
print "%$\n" "${green}$message${NC}";
print "%$\n" "${green}$files${NC}";
}
function readVideoExtension(){
echo -n "Extension des fichiers vidéos à traiter ("$((4-$count))" tentatives restantes) : "
read extension;
testIfAnyFileIsPresent=$(find $directory -maxdepth 1 -iname "*.$extension" | wc -l);
}
function choiseTypeOfVideo(){
local tmp_videos=""
count=0;
readDirectoryPath;
presentationOfFileDirectory;
testIfAnyFileIsPresent=0;
while [ $testIfAnyFileIsPresent = 0 ] && [ $count != 3 ] ; do
count=$(($count+1));
readVideoExtension;
done
if [ $count = 3 ] ; then
print "%$\n" "${red}""3 mauvaises tentatives entrainent l\'arrêt du programme""${NC}";
print "%$\n" "${red}""Abandon""${NC}";
exit 100;
fi
#/home/alban/Vidéos/fr3/annez.ts" | sed "s/\(.*\)\/\([Aa-Zz]*.$extension\)/\2/g"
#Example : data0001.ts data0002.ts data0003.ts
cd $directory;
videoFiles=($( ls *.$extension ));
cd $courant_directory;
}
function cleanVideoInformations() {
cat $1 | grep Imput > $2;
cat $1 | grep Duration >> $2;
cat $1 | grep Stream >> $2;
rm $1;
}
function prepareCommandToObtainSubtitlesTrackNumer(){
local a;
#local j=0;
for (( i=0 ; i < ${#videoFiles[@]} ; i++ )) ; do
#/home/alban/Vidéos/fr3/ENEMY/data0003.ts
data_videos_files[i]=$(echo $directory"/"${videoFiles[i]});
#/tmp/data0001_subtitle_infos.txt
tmp_video_info[i]=$(echo "/tmp/"${videoFiles[i]} | sed "s/.$extension/_subtitle_infos.txt/g");
#/tmp/data0003.ts.info
video_info_file[i]=$(echo /tmp/${videoFiles[i]}.info);
#ffprobe /home/alban/Vidéos/fr3/ENEMY/data0003.ts 2>&1 | ffmpeg -i EnnemyMine.ts -vn -an 2>&1 | grep '[A-Z][a-z]\{4\}' | sed "s/\(^[ ]*\)\([[:alnum:]]\)/\2/g" >/tmp/data0001_subtitle_infos.txt
ffprobe ${data_videos_files[i]} 2>&1 | grep '[A-Z][a-z]\{4\}' | sed "s/\(^[ ]*\)\([[:alnum:]]\)/\2/g" >${tmp_video_info[i]};
#create a cleanning file of video information
cleanVideoInformations "${tmp_video_info[i]}" "${video_info_file[i]}";
#cat /tmp/video-info.txt | grep Subtitle | sed "s/\(^.* \#\)\([0-9]:[0-9]\)(\([[:alnum:]]\{3\}\))\(.*\)/\2#\3/g"
# tracks_Info[1] =Stream #0:5(fra): Subtitle: dvd_subtitle (default) Stream #0:6(ger): Subtitle: dvd_subtitle Stream #0:7(fra): Subtitle: dvd_subtitle
tracks_Info[i]=$(cat ${video_info_file[i]} | grep Subtitle | sed "s/\(^.* \#\)\([0-9]:[0-9]\)(\([[:alnum:]]\{3\}\))\(.*\)/\2#\3/g" );
rm ${video_info_file[i]};
done
}
function createDirectoryIfNotExist(){
if [[ ! -e $1 ]] ; then
mkdir $1;
fi
}
function ExtractSubtitleFromVideoInMKV(){
local j=0;
local k=0;
$1
echo 'tracks_Info: '${tracks_Info[@]};
for ((i=0 ; i< ${#tracks_Info[@]}; i++)); do
#From : data0001.ts to: data0001
extract_work_files[i]=$(echo ${videoFiles[i]} | sed "s/.$extension//g");
#echo ${directory}/${extract_work_files[i]};
createDirectoryIfNotExist "${directory}/${extract_work_files[i]}";
tmp=($(echo ${tracks_Info[i]}));
for each in ${tmp[@]};do
# De : 0:4#fra à : 0.4 fra
#0:4
track_number=$(echo $each | cut -d'#' -f1);
#fra
track_lang=$(echo $each | cut -d'#' -f2);
#ffmpeg -threads 4 -i /home/alban/Vidéos/fr3/ENEMY/data0001.ts -map 0:5 -vn -an -scodec dvdsub /home/alban/Vidéos/fr3/ENEMY/data0001/data0001_0_fra.mkv
ffmpeg -threads 4 -i ${directory}/${videoFiles[i]} -map $track_number -vn -an -scodec dvdsub ${directory}/${extract_work_files[i]}/${extract_work_files[i]}\_$j\_$track_lang.mkv;
mkv_files[k]=$(echo ${directory}/${extract_work_files[i]}/${extract_work_files[i]}\_$j\_$track_lang.mkv);
mkv_directories[k]=$(echo ${directory}/${extract_work_files[i]});
subtitle_sub_id[k]=$(echo ${extract_work_files[i]}\_$j\_$track_lang);
subtitle_lang[k]=$(echo $track_lang);
j=$(($j + 1));
k=$(($k + 1))
done
done
}
function OpticalRecognitionCharacterOfTiff(){
for eachTiff in $1*.tif; do
cuneiform -l $2 -f text -o $eachTiff.txt $eachTiff;
done
}
function convertMKVSubtitleInSRT(){
local j=0
for (( i=0 ; i < ${#mkv_files[@]}; i++ )); do
#mkvextract tracks /home/alban/Vidéos/fr3/EnnemyMine/EnnemyMine_0_fra.mkv -c ISO8859-1 0:/home/alban/Vidéos/fr3/EnnemyMine/EnnemyMine_0_fra
mkvextract tracks ${mkv_files[i]} -c ISO8859-1 0:${mkv_directories[i]}/${subtitle_sub_id[i]};
# if sub file existe and has a size equal to 0 than erase sub and idx files
if [ ! -s ${mkv_directories[i]}/${subtitle_sub_id[i]}.sub ]; then
rm ${mkv_directories[i]}/${subtitle_sub_id[i]}.sub;
rm ${mkv_directories[i]}/${subtitle_sub_id[i]}.idx;
fi
done
for (( i=0 ; i < ${#videoFiles[@]} ; i++ )) ; do
work_directories=$(echo ${videoFiles[i]} | sed "s/.$extension//g") ;
#mkv_directories=$(echo $directory/work_directories kv_directories${videoFiles[i]} | sed "s/.$extension//g");
for each in $directory/$work_directories"/*.idx"; do
subtitle_sub=($(echo $each));
for filesub in ${subtitle_sub[@]}; do
#id_file=/home/alban/Vidéos/clanDesSabresVollants/de/Le_Secret_des_poignards_Volants_base/Le_Secret_des_poignards_Volants_base__fra
id_file=$(echo $filesub | sed "s/.idx//g");
subp2tiff --sid=0 -n $id_file;
#fra
sub_lang=$(echo $filesub | sed "s/\(.*\)\([a-z]\{3\}\)\(.idx\)/\2/g");
#subtitle_file_name : /home/alban/Vidéos/clanDesSabresVollants/de/Le_Secret_des_poignards_Volants_base/Le_Secret_des_poignards_Volants_base__fra.srt
subtitle_file_name=$(echo $filesub | sed "s/.idx//g");
echo "subtitle_file_name : "$subtitle_file_name;
#sub_id=$directory/$work_directories$(echo $filesub | sed "s/\(.*\)\(\_[0-9]\_\)\([a-z]\{3\}\)\(.idx\)/\2\3/g");
#OpticalRecognitionCharacterOfTiff "$sub_id" "$sub_lang";
OpticalRecognitionCharacterOfTiff "$subtitle_file_name" "$sub_lang";
#echo $directory/$(echo ${videoFiles[i]} | sed "s/.$extension//g")/;
# tmp= Le_Secret_des_poignards_Volants_base__fra
tmp=$(echo $filesub | sed "s/\(.*\)\/\(.*\)\(.idx\)/\2/g" );
echo "commande subptools : subptools -s -w -t srt -i $id_file.xml -o $directory/$tmp.srt";
subptools -s -w -t srt -i $id_file.xml -o $directory/$tmp.srt
done
rm -rf $directory/$work_directories;
done
done
}
choiseTypeOfVideo;
prepareCommandToObtainSubtitlesTrackNumer;
ExtractSubtitleFromVideoInMKV
convertMKVSubtitleInSRT;
exit 0;
===== Contributeurs =====
[[:utilisateurs:albanmartel]]