#!/bin/bash
################################################################################
#
# Version: 1.5.4
# Name: dPluzz-cli.sh
# Last modification: 2018/08/10
#
# -------------------------------------- HISTORY -------------------------------
#
# 2018/08/10 (1.5.4): Correctifs pour FTV
#
# 2018/03/30 (1.5.3): Correctifs pour FTV, arte, M6&Cie
#
# 2017/12/23 (1.5.2): Correctifs pour M6&Cie, C+&Cie, Gulli, NRJ12&Cie
# Divers beugues corrigés
# Possibilité de mettre en pause les opérations dans certains cas
#
# 2017/07/27 (1.5.0): Caractères non-ASCII dans les titres peuvent être autorisés (--keep-non-ascii)
# Si échec, possibilité d'empêcher l'effacement des fichiers créés (--no-cleaning)
# Prise en charge de RTBF
#
# 2017/07/26 (1.4.6): Beugues corrigés (fin de téléchargement, arte)
#
# 2017/09/08 (1.5.1): Correctifs pour arte
#
# 2017/07/24 (1.4.5): Correction numéro de saison/épisodes
#
# 2017/07/01 (1.4.4): Ignore WGETRC
#
# 2017/05/19 (1.4.3): Correctifs pour FTV et arte (enfin !)
#
# 2017/03/05 (1.4.2): Correctifs pour M6
#
# 2016/12/20 (1.4.1): Correctifs pour arte
#
# 2016/10/30 (1.4.0): Correctifs pour dailymotion (donc les chaînes qui l'utilisent comme numéro 23 ou l'équipe), pluzz
#
# 2016/10/09 (1.3.1): Correction faux positif
#
# 2016/09/29 (1.3.0): Prise en charge de France Info (TV), Arte (+7, Concert), LCP-AN, Public Sénat, M6, W9, 6ter, Numéro23, L'Équipe, Dailymotion
# Beugues corrigés (ftv, kill_jobs, build_filenames, fusion des urls partielles)
# Nouvelles fonctions (clean_files, lowercase, uppercase, softly_normalisedcase, strictly_normalisedcase, fix_case, normalise_url)
#
# 2016/09/12 (1.2.0): Prise en charge de TV5 Monde+ et TV5 Monde+ Afrique
#
# 2016/09/10 (1.1.0): Réparation des chaînes C8 (ex-D8), CStar (ex-D17), NRJ12, Cherie25, Gulli
# Beugues corrigés (sanitise)
# Nouvelles dépendances (perl)
#
# 2016/08/29 (1.0.0): Libération officielle
# Désactivation des tests sur la disponibilité des codecs dans avconv/ffmpeg car non fiables
#
# 2016/02/25 (0.9.0): Fusion de dPluzz et dCplus développés principalement par Matthieugoua, melixgaro, gaara
# Merci aussi à Lulux3
# Voir ces scripts pour leur propre historique [melixgaro]
#
#-------------------------------------- DEPENDANCIES ---------------------------
#
# avconv (sudo apt-get install --no-install-recommends libav-tools)
# ou bien
# ffmpeg (sudo apt-get install --no-install-recommends ffmpeg)
#
################################################################################
# Probably deprecated. Delete at next release if nobody complains
# Workaround for grep 2.21 or later
# export LC_ALL=C
# Ignore WGETRC
unset WGETRC
# Traps
kill_jobs()
{
pkill -TERM -P "$BASHPID"
logger warning "Programme interrompu par l'utilisateur"
clean_files
exit 1
}
trap kill_jobs INT TERM #EXIT
# Script variables
version="1.5.4"
script_path="$(cd "$(dirname "$0")"; pwd -P)"
script_md5="$(md5sum "${script_path}/$(basename "$0")" | cut -d\ -f1)"
term_width=$(tput cols)
################################################################################
# Color definition
export black_fgc="\e[7;0;31m"
export red_fgc="\e[7;0;31m"
export green_fgc="\e[0;32m"
export yellow_fgc="\e[0;33m"
export blue_fgc="\e[1;34m"
export magenta_fgc="\e[0;35m"
export cyan_fgc="\e[0;36m"
export white_fgc="\e[0;37m"
export default_fgc="\e[0;39m"
################################################################################
# Exiting
clean_files ()
{
local filename
if ! ${clean_if_failure}
then
exit
fi
logger info "Effacement des fichiers temporaires…"
for filename in "${files_to_clean[@]}"
do
[[ -f "${filename}" ]] && rm -v -- "${filename}"
done
}
exit_if_empty ()
{
if [[ ${#1} -eq 0 ]]
then
logger critical "${2}"
fi
}
# Flagging functions
debug_flagger ()
{
echo "$(date +"%d/%m/%Y %H:%M:%S") [DEBUG] "
}
info_flagger ()
{
echo "$(date +"%d/%m/%Y %H:%M:%S") [INFO] "
}
warning_flagger ()
{
echo "$(date +"%d/%m/%Y %H:%M:%S") [WARNING] "
}
critical_flagger ()
{
echo "$(date +"%d/%m/%Y %H:%M:%S") [CRITICAL] "
}
# Logging
logger ()
{
cr='
'
while read line
do
case "${1}" in
"debug")
echo -e "${blue_fgc}$(debug_flagger)${line}${default_fgc}" >&2
;;
"info")
echo -e "${green_fgc}$(info_flagger)${line}${default_fgc}" >&2
;;
"warning")
echo -e "${yellow_fgc}$(warning_flagger)${line}${default_fgc}" >&2
;;
"critical")
echo -e "${red_fgc}$(critical_flagger)${line}${default_fgc}" >&2
;;
esac
done <<< "${2//\\n/${cr}}"
if [[ "${1}" == "critical" ]]
then
clean_files
exit 1
fi
}
# String handling
sanitise ()
{
# echo "${1}" | recode h4..latin1 | sed 's+^[[:blank:]]*++g' | sed 's+[[:blank:]]*$++g' | sed 's+[[:blank:]]\{1,\}+_+g' | iconv -f utf-8 -t ascii//translit | sed 's/[\&"!?;]/_/g' | sed 's/[^[:alnum:]-]/_/g' | sed 's/_\{2,\}/_/g' | sed 's/-\{2,\}/-/g' | sed 's/_-/-/g' | sed 's/^_*\([^_].*[^_]\)_*/\1/g' | sed 's/.*/\u\0/g' | sed 's/^-*//g'
echo "${1}" | perl -MHTML::Entities -alne 'print(decode_entities($_))' | sed 's+^[[:blank:]]*++g' | sed 's+[[:blank:]]*$++g' | sed 's+[[:blank:]]\{1,\}+_+g' | perl -Mutf8 -MText::Unidecode -alne 'use open ":std", ":encoding(utf-8)"; print(unidecode($_));' | sed 's/[\&"!?;]/_/g' | sed 's/[^[:alnum:]-]/_/g' | sed 's/_\{2,\}/_/g' | sed 's/-\{2,\}/-/g' | sed 's/_-/-/g' | sed 's/^_*\([^_].*[^_]\)_*/\1/g' | sed 's/.*/\u\0/g' | sed 's/^-*//g'
}
sanitise_but_keep_non_ascii ()
{
echo "${1}" | perl -MHTML::Entities -alne 'print(decode_entities($_))' | sed 's+^[[:blank:]]*++g' | sed 's+[[:blank:]]*$++g' | sed 's+[[:blank:]]\{1,\}+_+g' | sed 's/[\&"!?;]/_/g' | sed 's/[^[:alnum:]-]/_/g' | sed 's/_\{2,\}/_/g' | sed 's/-\{2,\}/-/g' | sed 's/_-/-/g' | sed 's/^_*\([^_].*[^_]\)_*/\1/g' | sed 's/.*/\u\0/g' | sed 's/^-*//g'
}
lowercase ()
{
sed 's/.*/\L\0/g' <<< "${1}"
}
uppercase ()
{
sed 's/.*/\U\0/g' <<< "${1}"
}
softly_normalisedcase ()
{
sed 's/.*/\u\0/g' <<< "${1}"
}
strictly_normalisedcase ()
{
sed 's/.*/\L\u\0/g' <<< "${1}"
}
fix_case ()
{
case "${2}" in
"L")
lowercase "${1}"
;;
"U")
uppercase "${1}"
;;
"S")
softly_normalisedcase "${1}"
;;
"N")
strictly_normalisedcase "${1}"
;;
*)
echo "${1}"
;;
esac
}
progressfilt ()
{
local line=""
local prev_progression=0
while read line
do
progression=$(grep -oE "[0-9.]{1,}%" <<< "${line}" | sed 's/%//g' | awk '{if ($1 ~ /[0-9]/) {printf "%6.2f", $1} else {printf "%6.2f", 0}}')
if [[ "${progression}" != "${prev_progression}" && ${#progression} -ne 0 ]]
then
prev_progression=${progression}
echo -ne "\e[F" >&2
logger info "Progression: ${progression}%"
fi
done
}
month_number ()
{
local month=$(tr '[A-Z]' '[a-z]' <<< "${1}")
local nmonth=""
case "${1}" in
"janvier")
nmonth="01"
;;
"février"|"fevrier")
nmonth="02"
;;
"mars")
nmonth="03"
;;
"avril")
nmonth="04"
;;
"mai")
nmonth="05"
;;
"juin")
nmonth="06"
;;
"juillet")
nmonth="07"
;;
"aout"|"août")
nmonth="08"
;;
"septembre")
nmonth="09"
;;
"octobre")
nmonth="10"
;;
"novembre")
nmonth="11"
;;
"décembre"|"decembre")
nmonth="12"
;;
*)
nmonth="00"
;;
esac
echo "${nmonth}"
}
normalise_url ()
{
local line=""
local reference_url="${1}"
local netloc
netloc="$(sed 's+\(https\?://\)\?\([^/]*\).*+\1\2+g' <<< "${reference_url}")"
while read line
do
if [[ "${line:0:4}" == "http" ]]
then
echo "${line}"
elif [[ "${line:0:2}" == ".." ]]
then
echo "$(dirname "${reference_url}")/${line}"
elif [[ "${line:0:1}" == "/" ]] # DM
then
echo "${netloc}${line}"
elif [[ ! "${line}" =~ ^.*"/".*$ ]] # Gulli, LCP
then
echo "$(dirname "${reference_url}")/${line}"
# else
# echo "${line}"
fi
done < /dev/stdin
}
################################################################################
# Common variables
user_agent="Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:44.0) Gecko/20100101 Firefox/44.0"
advice_msg="Réessayer plus tard, ou si l'erreur persiste, attendez une mise-à-jour. Si vous êtes dans une zone géographique bloquée, il n'y a rien à faire"
lock_msg="Cette vidéo semble être verrouillée, il n'y a pas grand chose à faire (à part déplorer l'usage de mécanismes contraignants et restrictifs par les diffuseurs)"
timestamp=$(date +%s)
# User settings: display
is_coloured=true
is_verbose=false
keep_non_ascii=false
clean_if_failure=true
columns=$(tput cols)
if [[ ! ${columns} =~ [0-9] ]]
then
columns=79
fi
# User settings: video
avconv_exec="avconv"
want_ffmpeg=false
video_container="mkv"
video_codec="copy"
video_codec_is_changed_by_user=false
audio_codec="aac"
audio_codec_is_changed_by_user=false
subtitle_codec="ass"
subtitle_codec_is_changed_by_user=false
want_mp3=false
want_vo=false
want_subtitles=false
subtitle_lang="vf"
colored_subtitles=false
keep_srt=false
keep_ass=false
mux_subtitles=false
conversion_log=false
video_quality="best"
forced_filename_root=""
accepted_keywords=("%(TITRE)" "%(SOUSTITRE)" "%(JOUR)" "%(MOIS)" "%(ANNEE)" "%(HEURE)" "%(MINUTE)" "%(RUBRIQUE)" "%(SAISON)" "%(EPISODE)" "%(QUALITE)" "%(URL)" "%(ID)")
number_format="%02d"
naming_convention="%(RUBRIQUE)-%(TITRE)-%(SOUSTITRE)_S%(SAISON)E%(EPISODE)_%(ANNEE)%(MOIS)%(JOUR)-%(HEURE)%(MINUTE)"
naming_convention="%(TITRE)-%(ANNEE)%(MOIS)%(JOUR)-%(HEURE)%(MINUTE)"
################################################################################
# Command line parsing
usage()
{
fmt -w ${columns} -p" " << EOF
usage: $(basename $0) [OPTIONS] [-u|--url] URL
OPTIONS:
-u|--url STR adresse de la vidéo
-d|--directory STR dossier de destination
-o|--output STR nom du fichier (sans extension). À la priorité sur le nommage automatique
--name-format formatage du nom des fichiers [défaut: ${naming_convention}]
Mots-clefs acceptés: %(TITRE), %(SOUSTITRE), %(JOUR), %(MOIS), %(ANNEE), %(HEURE), %(MINUTE), %(RUBRIQUE), %(SAISON), %(EPISODE)
Vous pouvez appliquer un modificateur sur un mot-clef afin de contrôler la casse. Les modificateurs sont 'L' (basse casse intégrale), 'U' (haute casse intégrale), 'N' (haute casse pour la première lettre, basse casse pour le reste). Exemple d'utilisation pour avoir le titre en haute casse : %(TITRE:U)
--keep-non-ascii garde les caractères non-ASCII dans le nom du fichier [défaut: false]
--no-cleaning garde le fichier en cas d'échec [défaut: false]
-q|--quality qualité de la vidéo, si pertinent (best, standard, worst) [défaut: best]
--video-codec STR spécifie le codec video (copy, libx264) [défaut: copy]
il est conseillé de garder la valeur par défaut. Tout autre choix est encore expérimental. Si vous choisissez un codec autre que 'copy', la création de la vidéo sera plus longue (les réglages actuels peuvent aider à réduire la taille pour une qualité comparable)
--audio-codec STR spécifie le codec audio (aac, mp3, copy) [défaut: aac]
--subtitle-codec STR spécifie le codec de sous-titre (ass, srt, subrip) [défaut: ass]
--video-container STR spécifie le conteneur vidéo (mkv, mp4) [défaut: mkv]
--subtitle-lang STR spécifie la langue des sous-titres, si disponible (vf, vf-ad) [défaut: vf]
vf-ad fournit la version française avec audiodescription
--colored-subtitles garde la couleur dans les sous-titre, si disponible [défaut]
activé pour les sous-titres avec audiodescription
--subtitle-mode STR mode de sauvegarde des sous-titres (srt, ass, mux)
[défaut: srt]
'srt' ou 'ass' active la sauvegarde des sous-titres dans un fichier séparé au format srt ou ass
'mux' est un mode expérimental qui permet de multiplexer la piste de sous-titres avec les autres pistes et de n'avoir qu'un seul fichier à la fin (mkv uniquement)
--vo requiert la langue originale, si disponible
-f|--ffmpeg utilise ffmpeg [défaut: avconv]
--log conserve le journal de la conversion
--no-color désactive la coloration du terminal
-v|--verbose mode bavard
-V|--version affiche la version du script
-h|--help affiche cette aide
OPTIONS OBSOLÈTES:
-m OBSOLÈTE (conservée pour compatibilité,
utilisez --audio-codec)
convertit l'audio en MP3
SCHÉMAS D'URL ACCEPTÉS:
Les étoiles indiquent l'endroit à partir duquel vos urls peuvent différer
-> http://www.france.tv/*
-> http://www.francetvinfo.fr/*
-> http://www.arte.tv/fr/*
-> http://www.arte.tv/de/*
[La vidéo sera en allemand]
-> http://concert.arte.tv/fr/*
-> http://concert.arte.tv/de/*
[La vidéo sera en allemand]
-> http://www.lcp.fr/*
-> http://replay.publicsenat.fr/vod/*
-> http://www.publicsenat.fr/lcp/*
-> https://www.mycanal.fr/*
-> https://www.6play.fr/*
-> http://www.nrj-play.fr/nrj12/replay/*
-> http://www.nrj-play.fr/cherie25/replay/*
-> http://replay.gulli.fr/*
-> http://www.lequipe.fr/lachainelequipe/video/*
-> http://www.numero23.fr/*video_id*
[Il est important que l'adresse se termine par une chaîne similaire à '?video_id=123abcd'. Sur http://www.numero23.fr/replay, depuis votre navigateur, il faut faire un clique droit sur les miniatures des vidéos (les photos avec l'icône de lecture) et copier l'adresse.]
-> http://www.tv5mondeplus.com/*
-> http://www.tv5mondeplusafrique.com/*
-> http://www.dailymotion.com/*
-> http://www.rtbf.be/auvio/*
REMARQUES:
(1) En cas d'échec, veuillez réessayer plus tard avant d'invoquer un possible bogue
(2) Notez que le nom du fichier sera automatiquement nettoyé de certains caractères non recommendés (en particulier, les espaces, certains signes de ponctuations…)
(3) L'objectif de ce programme n'étant pas la conversion audio/vidéo, les options concernant les codecs/conteneurs resteront extrêmement basiques. Vous pouvez toujours utiliser avconv/ffmpeg par la suite
(4) Selon votre version de ffmpeg/avconv, certains codecs peuvent ne pas être disponibles
(5) Des cookies de session sont sauvegardés dans un fichier dont le nom ressemble à 'wget-1234567.cookies'. Ce fichier est effacé lorsque le programme se termine normalement. Sinon, vous pouvez les effacer manuellement
(6) Il est possible, pour certaines chaînes, de mettre en pause les opérations avec la touche p. Un nouvel appui sur la touche p relance les opérations. Attention, cette fonction est expérimentale ; il se peut que la reprise échoue
EOF
}
if [[ $# == 0 ]]
then
usage
exit 1
fi
while test -n "${1}"
do
case "${1}" in
"--no-color")
shift
exit
is_coloured=false
black_fgc=""
red_fgc=""
green_fgc=""
yellow_fgc=""
blue_fgc=""
magenta_fgc=""
cyan_fgc=""
white_fgc=""
default_fgc=""
;;
"-v"|"--verbose")
shift
is_verbose=true
;;
"-V"|"--version")
shift
echo -e "${default_fgc}$(basename ${0} .sh): v. ${version}${default_fgc}" >&2
exit 1
;;
"-h"|"--help")
usage
exit 1
;;
"-u"|"--url")
shift
url="${1}"
shift
;;
"-d"|"--directory")
shift
directory="${1}"
shift
;;
"-o"|"--output")
shift
forced_filename_root="${1}"
shift
;;
"--name-format")
shift
naming_convention="$(sed 's/\%(\([^)]*\))/%(\U\1)/g' <<< "${1}")"
for tag in $(grep -oE "%\([^\)]*\)" <<< "${naming_convention}")
do
if [[ ! $(grep -G "${tag/:*/)}" <<< "${accepted_keywords[@]}") ]]
then
logger critical "Ce mot-clef ${tag} est inconnu"
fi
done
shift
;;
"--keep-non-ascii")
shift
keep_non_ascii=true
sanitise ()
{
sanitise_but_keep_non_ascii "${1}"
}
;;
"--no-cleaning")
shift
clean_if_failure=false
;;
"-q"|"--quality")
shift
video_quality="$(tr '[A-Z]' '[a-z]' <<< "${1}")"
case "${video_quality}" in
"best"|"standard"|"worst")
:
;;
*)
logger critical "Qualité non prise en charge"
;;
esac
shift
;;
"--video-codec")
shift
video_codec="$(tr '[A-Z]' '[a-z]' <<< "${1}")"
video_codec_is_changed_by_user=true
case "${video_codec}" in
"copy"|"libx264")
:
;;
*)
logger critical "Codec video non pris en charge"
;;
esac
shift
;;
"--audio-codec")
shift
audio_codec="$(tr '[A-Z]' '[a-z]' <<< "${1}")"
audio_codec_is_changed_by_user=true
case "${audio_codec}" in
"aac"|"mp3"|"copy")
:
;;
*)
logger critical "Codec audio non pris en charge"
;;
esac
shift
;;
"--subtitle-codec")
shift
subtitle_codec="$(tr '[A-Z]' '[a-z]' <<< "${1}")"
subtitle_codec_is_changed_by_user=true
case "${subtitle_codec}" in
"ass"|"srt"|"subrip")
:
;;
*)
logger critical "Codec de sous-titres non pris en charge"
;;
esac
shift
;;
"--video-container")
shift
video_container="$(tr '[A-Z]' '[a-z]' <<< "${1}")"
case "${video_container}" in
"mkv"|"mp4")
:
;;
*)
logger critical "Conteneur vidéo non pris en charge"
;;
esac
shift
;;
"--subtitle-lang")
shift
want_subtitles=true
subtitle_lang="$(tr '[A-Z]' '[a-z]' <<< "${1}")"
case "${subtitle_lang}" in
"vf"|"vf-ad")
:
;;
*)
logger critical "Langue de sous-titres non prise en charge"
;;
esac
shift
;;
"--colored-subtitles")
shift
colored_subtitles=true
;;
"--subtitle-mode")
shift
subtitle_mode="$(tr '[A-Z]' '[a-z]' <<< "${1}")"
case "${subtitle_mode}" in
"srt")
keep_srt=true
keep_ass=false
mux_subtitles=false
;;
"ass")
keep_ass=true
keep_srt=false
mux_subtitles=false
;;
"mux")
mux_subtitles=true
keep_srt=false
keep_ass=false
;;
*)
logger critical "Mode de sauvegarde des sous-titres non pris en charge"
;;
esac
shift
;;
"--vo")
shift
want_vo=true
;;
"-f"|"--ffmpeg")
shift
want_ffmpeg=true
avconv_exec="ffmpeg"
;;
"--log")
shift
conversion_log=true
;;
"-m")
shift
want_mp3=true
;;
"--keep-srt") # Private
shift
keep_srt=true
;;
"--keep-ass") # Private
shift
keep_srt=true
;;
"-"*)
logger critical "Option inconnue"
;;
*)
url="${1}"
shift
;;
esac
done
################################################################################
# Main: functions
# Sanity checks: url
case "${url}" in
http*://pluzz.francetv.fr*|http*://www.francetvinfo.fr*|http*://culturebox.francetvinfo.fr*)
tvg="ftv-legacy"
;;
http*://www.france.tv*)
tvg="ftv"
;;
http*://www.arte.tv*|http*://concert.arte.tv*)
tvg="arte"
;;
http*://www.lcp.fr*)
tvg="lcp"
;;
http*://www.publicsenat.fr*|http*://replay.publicsenat.fr*)
tvg="ps"
;;
http*://www.canalplus.fr*|http*://www.c8.fr*|http*://replay.c8.fr*|http*://www.cstar.fr*|http*://replay.cstar.fr*|http*://www.itele.fr*)
tvg="c+-legacy"
;;
http*://www.mycanal.fr*)
tvg="c+"
;;
http*://www.6play.fr*)
tvg="m6"
;;
http*://www.nrj-play.fr/nrj12*|http*://www.nrj-play.fr/cherie25*)
tvg="nrj"
;;
http*://replay.gulli.fr*)
tvg="gulli"
;;
http*://www.lequipe.fr/lachainelequipe/video*)
tvg="e21"
;;
http*://www.numero23.fr*video_id*)
tvg="n23"
;;
http*://www.tv5mondeplus.com*)
tvg="tv5"
;;
http*://www.tv5mondeplusafrique.com*)
tvg="tv5-afrique"
;;
http*://www.dailymotion.com*)
tvg="dm"
;;
http*://www.rtbf.be/auvio*)
tvg="rtbf"
;;
*)
logger critical "Chaîne non prise en charge ou url incorrecte"
;;
esac
# Sanity checks: avconv/ffmpeg
if [[ ! $(which ${avconv_exec}) ]]
then
logger critical "${avconv_exec} n'est pas présent sur votre machine"
fi
# Sanity checks: codec availability
case "${video_codec}" in
"libx264")
video_codec_test=$(${avconv_exec} -codecs 2> /dev/null | grep ".EV... h264 .*encoder.* libx264[^[:alnum:]]")
;;
"copy")
video_codec_test="copy"
;;
*)
logger critical "Erreur inconnue"
;;
esac
# exit_if_empty "${video_codec_test}" "Codec video (${video_codec}) non pris en charge par votre version de ${avconv_exec}"
case "${audio_codec}" in
"aac")
audio_codec_test=$(${avconv_exec} -codecs 2> /dev/null | grep ".EA... aac .*encoder.* aac[^[:alnum:]]")
;;
"mp3")
audio_codec_test=$(${avconv_exec} -codecs 2> /dev/null | grep ".EA... mp3 .*encoder.* libmp3lame[^[:alnum:]]")
;;
"copy")
audio_codec_test="copy"
;;
esac
# exit_if_empty "${audio_codec_test}" "Codec audio (${audio_codec}) non pris en charge par votre version de ${avconv_exec}"
case "${subtitle_codec}" in
"ass")
subtitle_codec_test=$(${avconv_exec} -codecs 2> /dev/null | grep ".ES... ssa\|ass" | head -n 1)
;;
"srt")
subtitle_codec_test=$(${avconv_exec} -codecs 2> /dev/null | grep ".ES... srt")
;;
"subrip")
subtitle_codec_test=$(${avconv_exec} -codecs 2> /dev/null | grep ".ES... subrip")
;;
"copy")
subtitle_codec_test="copy"
;;
esac
# exit_if_empty "${subtitle_codec_test}" "Codec de sous-titres (${subtitle_codec}) non pris en charge par votre version de ${avconv_exec}"
# Sanity checks: container
if [[ "${video_container}" == "mp4" ]]
then
logger warning "Avec ce conteneur (mp4), il faudra attendre le téléchargement complet avant de pouvoir commencer la lecture. Préférez le conteneur mkv pour une lecture immédiate"
fi
# Sanity checks: video codec
if ${video_codec_is_changed_by_user} && [[ "${video_codec}" != "copy" ]]
then
logger warning "Vous avez requis un recodage de la piste vidéo. Cette fonction est expérimentale et engendrera un traitement plus long"
fi
# Sanity checks: audio codec
if ${want_mp3} && ${audio_codec_is_changed_by_user} && [[ "${audio_codec}" != "mp3" ]]
then
logger critical "Options '-m' et '--audio-codec aac' incompatibles. '-m' est obsolète, préférez-y '--audio-codec mp3'"
fi
if ${want_mp3} && ! ${audio_codec_is_changed_by_user}
then
audio_codec="mp3"
logger warning "L'option '-m' est obsolète, préférez-y '--audio-codec mp3'"
fi
# Sanity checks: subtitles
if ${want_subtitles}
then
if [[ "${subtitle_lang}" == "vf-ad" ]]
then
colored_subtitles=true
fi
if ! ${keep_srt} && ! ${keep_ass} && ! ${mux_subtitles}
then
keep_srt=true
fi
if ${mux_subtitles} && [[ "${video_container}" == "mp4" ]]
then
keep_srt=true
keep_ass=false
mux_subtitles=false
logger warning "Avec ce conteneur (mp4), les sous-titres seront dans un fichier séparé (srt). Préférez le conteneur mkv pour avoir un seul fichier"
fi
if ${mux_subtitles}
then
logger warning "Le multiplexage des sous-titres est expérimental. Il peut échouer selon la version de avconv/ffmpeg disponible sur votre machine"
fi
fi
# Sanity checks: destination
if [[ ${#directory} -eq 0 ]]
then
directory="${HOME}"
else
directory="$(readlink -f "${directory}")"
if [[ ! -d "${directory}" ]]
then
logger critical "Le dossier de destination n'existe pas"
fi
fi
# Main: functions
vtt2srt ()
{
local srt_subtitle_filename="${1}"
# sed -i 's+^[^[:print:][:blank:]]*]*>\(.*\)[^[:print:][:blank:]]*$+\1+g' "${srt_subtitle_filename}"
sed -i 's+^[^[:print:]]*[[:blank:]]*$++g' "${srt_subtitle_filename}"
sed -i 's+[^[:print:]]$++g' "${srt_subtitle_filename}"
sed -i 's+^[^[:print:][:blank:]]*]*\)>\(.*\)[^[:print:][:blank:]]*$+\2+g' "${srt_subtitle_filename}"
sed -i '/^[[:blank:]]*[0-9:.]\{3,\}/ s/\([0-9][0-9]\):\([0-9][0-9]\):\([0-9][0-9]\)\(\.\([0-9]*\)\)/\1:\2:\3,\5/g' "${srt_subtitle_filename}"
sed -i '/^WEBVTT/d' "${srt_subtitle_filename}"
}
srt2ass ()
{
local srt_subtitle_filename="${1}"
local ass_subtitle_filename="${2}"
${avconv_exec} -y -i "${srt_subtitle_filename}" "${ass_subtitle_filename}" 2> /dev/null
}
check_desc ()
{
if [[ $(grep "${2}" <<< "${1}") == "" ]]
then
logger critical "Impossible d'obtenir les informations\n${advice_msg}"
fi
}
build_filenames ()
{
local rules="${1}"
if [[ ${#forced_filename_root} -eq 0 ]]
then
filename_root="${rules}"
for subchain in $(grep -oE "%\([^)]*\)" <<< "${filename_root}")
do
_match=""
_tag="$(sed -n 's/%(\([^:]*\)\(\:\(.\)\)\?)/\1/p' <<< "${subchain}")"
_case="$(sed -n 's/%(\([^:]*\)\(:\(.\)\)\?)/\3/p' <<< "${subchain}")"
case "${_tag}" in
"TITRE")
_match="${video_title1:-}"
;;
"SOUSTITRE")
_match="${video_title2:-}"
;;
"JOUR")
_match="${video_date_day:-}"
;;
"MOIS")
_match="${video_date_month:-}"
;;
"ANNEE")
_match="${video_date_year:-}"
;;
"HEURE")
_match="${video_date_hour:-}"
;;
"MINUTE")
_match="${video_date_minute:-}"
;;
"RUBRIQUE")
_match="${video_code:-}"
;;
"SAISON")
_match="${video_season:-}"
;;
"EPISODE")
_match="${video_episode:-}"
;;
"URL")
_match="${video_uname:-}"
;;
"QUALITE")
# _match="${video_quality:-}"
case "${video_quality}" in
"best")
_match="HQ"
;;
"standard")
_match="MQ"
;;
"worst")
_match="LQ"
;;
esac
;;
"ID")
_match="${video_id:-}"
;;
esac
_match="$(fix_case "${_match}" "${_case}")"
# filename_root="$(sed 's/'"${subchain}"'/'"${_match}"'/' <<< "${filename_root}")"
filename_root="${filename_root/"${subchain}"/"${_match}"}"
done
# Deprecated. Delete at next release
# filename_root="${filename_root/\%(TITRE)/${video_title1:-}}"
# filename_root="${filename_root/\%(SOUSTITRE)/${video_title2:-}}"
# filename_root="${filename_root/\%(JOUR)/${video_date_day:-}}"
# filename_root="${filename_root/\%(MOIS)/${video_date_month:-}}"
# filename_root="${filename_root/\%(ANNEE)/${video_date_year:-}}"
# filename_root="${filename_root/\%(HEURE)/${video_date_hour:-}}"
# filename_root="${filename_root/\%(MINUTE)/${video_date_minute:-}}"
# filename_root="${filename_root/\%(RUBRIQUE)/${video_code:-}}"
# filename_root="${filename_root/\%(SAISON)/${video_season:-}}"
# filename_root="${filename_root/\%(EPISODE)/${video_episode:-}}"
# filename_root="${filename_root/\%(URL)/${video_uname:-}}"
# filename_root="${filename_root/\%(QUALITE)/${video_quality:-}}"
else
filename_root="${forced_filename_root}"
fi
# Sanitise
filename_root="$(sanitise "${filename_root}")"
filename_root="$(sed 's/^\(.\{245\}\).*/\1/g' <<< "${filename_root}")"
case "${video_container}" in
"mkv")
video_filename="${directory}/${filename_root}.mkv"
;;
"mp4")
video_filename="${directory}/${filename_root}.mp4"
;;
esac
files_to_clean[$((${#files_to_clean[@]}+1))]="${video_filename}"
srt_subtitle_filename="${directory}/${filename_root}.srt"
files_to_clean[$((${#files_to_clean[@]}+1))]="${srt_subtitle_filename}"
ass_subtitle_filename="${directory}/${filename_root}.ass"
files_to_clean[$((${#files_to_clean[@]}+1))]="${ass_subtitle_filename}"
if ${conversion_log}
then
log_filename="${directory}/${filename_root}.log"
files_to_clean[$((${#files_to_clean[@]}+1))]="${log_filename}"
else
log_filename="/dev/null"
fi
}
parse_parent_m3u8 ()
{
local tvg="${1}"
local video_parent_m3u8="${2}"
video_parent_m3u8_content=($(wget -q -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies "${video_parent_m3u8}" -O - | sed 's/[^[:print:]]//g' | sed 's/^[[:blank:]]\+//g' | sed 's/[[:blank:]]\+//g'))
exit_if_empty "${video_parent_m3u8_content}" "Échec à cause d'une erreur inattendue (zone géographique bloquée, perte de connexion…)\n${advice_msg}"
counter=-1
slist=$(
_resolutions=""
for line in ${video_parent_m3u8_content[@]}
do
counter=$((counter+1))
case "${line}" in
*"RESOLUTION="*)
sbw=$(sed 's+.*\(BANDWIDTH\)[[:blank:]]*=[[:blank:]]*\([0-9]*\).*+\2+g' <<< "${line}")
surl="${video_parent_m3u8_content[$((counter+1))]}"
if [[ "${surl:0:1}" == "#" || "${surl}" == '' || "${surl:0:1}" == ' ' ]]
then
continue
fi
if [[ "${surl:0:4}" != "http" ]]
then
surl="$(dirname "${video_parent_m3u8}")/${surl}"
fi
if [[ "$(grep "r=${sbw:--1};" <<< "${_resolutions}")" == "" ]]
then
echo "AV.|VF|${sbw:--1}|${surl}"
if [[ ${sbw:--1} != -1 ]]
then
_resolutions="${_resolutions}r=${sbw};"
fi
fi
;;
*"TYPE=AUDIO"*)
case "${tvg}" in
"ftv")
svourl="$(grep -Ei "^.*#EXT-X-MEDIA:.*TYPE=AUDIO.*LANGUAGE=.qaa." <<< "${line}" | sed -n 's+.*URI=\"\([^\"]*.m3u8\)\".*+\1+p')"
if [[ ${#svourl} -ne 0 ]]
then
if [[ "${surl:0:4}" != "http" ]]
then
svourl="$(dirname "${video_parent_m3u8}")/${svourl}"
fi
echo "A..|VO|-1|${svourl}"
fi
ssvfurl="$(grep -Ei "^.*#EXT-X-MEDIA:.*TYPE=AUDIO.*NAME=.Audio *Fran.ais..*LANGUAGE=.fr." <<< "${line}" | sed -n 's+.*URI=\"\([^\"]*.m3u8\)\".*+\1+p')"
if [[ ${#ssvfurl} -ne 0 ]]
then
if [[ "${surl:0:4}" != "http" ]]
then
ssvfurl="$(dirname "${video_parent_m3u8}")/${ssvfurl}"
fi
echo "A..|SVF|-1|${ssvfurl}"
fi
;;
*)
:
;;
esac
;;
esac
done | sort -t\| -k1d,1d -k3n,3n
)
if [[ "$(grep "|SVF|" <<< "${slist[@]}")" != "" ]]
then
ssvfurl="$(grep "|SVF|" <<< "${slist[@]}" | awk -F '|' '{print $4}')"
akey="$(sed 's/.*\(-audio[^=]*=[0-9]\+\).m3u8.*/\1/g' <<< "${ssvfurl}")"
_slist=$(
for line in ${slist[@]}
do
if [[ "$(grep -E "^AV..VF.[0-9]" <<< "${line}")" != "" ]]
then
if [[ "$(grep -E -- "-audio" <<< "${line}")" == "" ]]
then
sed 's/-video/'"${akey}"'-video/g' <<< "${line}"
else
echo "${line}"
fi
elif [[ "$(grep -E "|SVF|" <<< "${line}")" == "" ]]
then
echo "${line}"
fi
done
)
slist="${_slist}"
fi
}
get_dm_video ()
{
local video_id1="${1}"
local video_id2="${2}"
if [[ "${video_id2}" == "" ]]
then
video_id2="${video_id1}"
fi
video_desc="$(wget -q -O - -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies "https://api.dailymotion.com/video/${video_id2}?fields=id,duration,owner.screenname,title,uri,description,created_time" | sed 's+\\/+/+g' | sed 's/\\u\(....\)/\\x{\1}/g' | ascii2uni -q -a C)"
exit_if_empty "${video_desc}" "Impossible d'obtenir les informations\n${advice_msg}"
check_desc "${video_desc}" "${video_id1}"
_video_date=$(sed -n 's+.*\"created_time\":\([0-9]*\).*+\1+p' <<< "${video_desc}")
_video_date=($(date -d"@${_video_date}" +"%d %m %Y %H %M"))
video_date="$(sed 's/\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\)/\3\/\2\/\1 \4:\5/g' <<< "${_video_date[@]}")"
video_date_day=${_video_date[0]}
video_date_month=${_video_date[1]}
video_date_year=${_video_date[2]}
video_date_hour=${_video_date[3]}
video_date_minute=${_video_date[4]}
video_code=""
video_title1="$(sed -n 's+.*\"title\":\"\([^\"]*\)\".*+\1+p' <<< "${video_desc}")"
video_title2=""
video_season=""
video_episode=""
video_method="http-m3u8"
video_parent_m3u8="$(get_dm_video_url "${video_id2}" "http-m3u8")"
exit_if_empty "${video_parent_m3u8}" "Impossible d'obtenir la vidéo\n${advice_msg}"
parse_parent_m3u8 "${tvg}" "${video_parent_m3u8}"
video_subtitles=""
}
get_dm_video_url ()
{
local video_id="${1}"
local video_method="${2}"
local json_content=""
local dm_urls=""
# get_dm_video_url "x4uvf9z"
# get_dm_video_url "x4usn5f"
# get_dm_video_url "x1a8ecs"
# get_dm_video_url "x31f1qq"
# json_content="$(wget -q -O - -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies "http://www.dailymotion.com/json/video/${video_id}?fields=video_id,title,stream_h264_ld_url,stream_h264_url,stream_h264_hq_url,stream_h264_hd_url,stream_h264_hd1080_url,stream_hls_url" | sed 's+\\/+/+g')"
# grep -a -oE "http[^\"]*H264-176x144-2[^\"]*" <<< "${json_content}"
# grep -a -oE "http[^\"]*H264-320x240[^\"]*" <<< "${json_content}"
# grep -a -oE "http[^\"]*H264-512x384[^\"]*" <<< "${json_content}"
# grep -a -oE "http[^\"]*H264-848x480[^\"]*" <<< "${json_content}"
# grep -a -oE "http[^\"]*H264-1280x720[^\"]*" <<< "${json_content}"
# grep -a -oE "http[^\"]*H264-1920x1080[^\"]*" <<< "${json_content}"
# grep -a -oE "http[^\"]*H264-2560x1440[^\"]*" <<< "${json_content}"
# grep -a -oE "http[^\"]*H264-3840x2160[^\"]*" <<< "${json_content}"
json_content="$(wget -q -O - -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies "http://www.dailymotion.com/embed/video/${video_id}" | sed 's+\\/+/+g')"
dm_urls="$((grep -a -oE "qualities.:.*" | grep -a -oE "http[^\"]*(m3u8|H264-)[^\"]*" | grep -v "&include=[0-9]*") <<< "${json_content}")"
if [[ "${video_method}" == "http-m3u8" ]]
then
(grep -a -oE "http[^\"]*m3u8[^\"]*") <<< "${dm_urls}"
elif [[ "${video_method}" == "http-mp4" ]]
then
(grep -a -oE "http[^\"]*H264-[^\"]*") <<< "${dm_urls}"
else
echo ""
fi
}
# Main: misc
cookies_filename="${directory}/wget-${timestamp}.cookies"
files_to_clean[$((${#files_to_clean[@]}+1))]="${cookies_filename}"
# Main: get infos
logger debug "Exécutable: ${script_path}"
logger debug "Version: ${version} (${script_md5})"
logger info "Obtention des information pour ${url}"
url_content="$(wget -q -O - -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies "${url}" | perl -MHTML::Entities -CS -alne 'print(decode_entities($_))')"
exit_if_empty "${url_content}" "Impossible d'obtenir la page\n${advice_msg}"
case "${tvg}" in
"ftv-legacy")
video_uname="$(basename "${url}" .html | sed 's/_\?,\([0-9]*\)[^0-9]*.*/_\1/g')"
video_id=$(grep -a -oE "data-diffusion=.[0-9]*." <<< "${url_content}" | head -n 1 | grep -a -oE "[0-9]+")
video_idc="Pluzz"
if [[ "${video_id}" == "" ]]
then
video_id=$((grep -a -oE "http://info.francetelevisions.fr/\?id-video=[^@]*@[^\"]*" | sed 's/.*id-video=//g') <<< "${url_content}")
video_idc=${video_id##*@}
video_id=${video_id%%@*}
fi
if [[ "${video_id}" == "" ]]
then
video_id=$((grep -a -oE "http://videos.francetv.fr/video/[^@]*@[^\"]*" | sed 's/.*video\///g') <<< "${url_content}")
video_idc=${video_id##*@}
video_id=${video_id%%@*}
fi
exit_if_empty "${video_id}" "Impossible d'obtenir l'ID\n${advice_msg}"
video_desc="$(wget -q -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies "http://webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/?idDiffusion=${video_id}&catalogue=${video_idc}&callback=webserviceCallback_${video_id}" -O - | sed 's+\\/+/+g' | sed 's/\\u\(....\)/\\x{\1}/g' | ascii2uni -q -a C)"
exit_if_empty "${video_desc}" "Impossible d'obtenir les informations\n${advice_msg}"
check_desc "${video_desc}" "${video_id}"
video_date="$(sed -n 's+.*\"date_debut..\"\(\([0-9]*\)/\([0-9]*\)/\([0-9]*\) *\([0-9]*\):\([0-9]*\)\)\".*+\4/\3/\2 \5:\6+p' <<< "${video_desc}")"
_video_date=($(date -d "${video_date}" +"%d %m %Y %H %M"))
video_date_day=${_video_date[0]}
video_date_month=${_video_date[1]}
video_date_year=${_video_date[2]}
video_date_hour=${_video_date[3]}
video_date_minute=${_video_date[4]}
video_code="$(sed -n 's+.*\"code_programme..\"\([^\"]*\)\".*+\1+p' <<< "${video_desc}")"
video_title1="$(sed -n 's+.*\"titre..\"\([^\"]*\)\".*+\1+p' <<< "${video_desc}")"
video_title2="$(sed -n 's+.*\"sous_titre..\"\([^\"]*\)\".*+\1+p' <<< "${video_desc}")"
video_season="$(sed -n 's+.*\"saison..\([[0-9]]*\).*+\1+p' <<< "${video_desc}")"
video_episode="$(sed -n 's+.*\"episode..\([[0-9]]*\).*+\1+p' <<< "${video_desc}")"
video_method="http-m3u8"
video_parent_m3u8="$(sed -n 's+.*url..\"\(http[^\"]*m3u8[^\"]*\)\".*+\1+p' <<< "${video_desc}")"
if [[ "${video_parent_m3u8}" =~ ^.*"replay.francetv.fr/startover/".*$ ]]
then
logger critical "Cette vidéo n'est pas encore disponible, veuillez réessayer dans un moment"
fi
exit_if_empty "${video_parent_m3u8}" "Impossible d'obtenir la vidéo\n${advice_msg}"
parse_parent_m3u8 "${tvg}" "${video_parent_m3u8}"
if [[ "${slist}" =~ ^.*"cartons/carton".*$ ]]
then
logger critical "${lock_msg}"
fi
if [[ "${video_parent_m3u8}" =~ ^.*"media-secure".*$ ]]
then
logger warning "Cette vidéo est peut-être verrouillée. Si c'est le cas, il n'y a rien à faire"
fi
video_subtitles="$(sed -n 's+.*\"url..\"\(http[^\"]*vtt\)\".*+\1+p' <<< "${video_desc}")"
;;
"ftv")
video_uname="$(basename "${url}" .html | sed 's/_\?,\([0-9]*\)[^0-9]*.*/_\1/g')"
# video_id=$(grep -a -oE "data-main-video=.[0-9]*." <<< "${url_content}" | head -n 1 | grep -a -oE "[0-9]+")
if [[ "$(grep -a -oEi "> *indisponible *<" <<< "${url_content}")" != "" ]]
then
logger critical "Cette vidéo n'est plus disponible"
fi
video_id=$(grep -a -oE "videoId[^:]?: *[\"'][0-9a-z\-]*[\"']" <<< "${url_content}" | head -n 1 | sed 's/videoId[^:]\?: *.\(.*\)./\1/g')
if [[ ${video_id} =~ ^[0-9]*$ ]]
then
video_idc="Pluzz"
video_idcc="webserviceCallback_${video_id}"
else
video_idc=""
video_idcc=""
fi
if [[ "${video_id}" == "" ]]
then
video_id=$((grep -a -oE "http://info.francetelevisions.fr/\?id-video=[^@]*@[^\"]*" | sed 's/.*id-video=//g') <<< "${url_content}")
video_idc=${video_id##*@}
video_id=${video_id%%@*}
fi
if [[ "${video_id}" == "" ]]
then
video_id=$((grep -a -oE "http://videos.francetv.fr/video/[^@]*@[^\"]*" | sed 's/.*video\///g') <<< "${url_content}")
video_idc=${video_id##*@}
video_id=${video_id%%@*}
fi
if [[ ${video_idc} == "" ]]
then
video_idc=""
video_idcc="webserviceCallback_${video_id}"
fi
exit_if_empty "${video_id}" "Impossible d'obtenir l'ID\n${advice_msg}"
video_desc="$(wget -q -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies "http://webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/?idDiffusion=${video_id}&catalogue=${video_idc}&callback=${video_idcb}" -O - | sed 's+\\/+/+g' | sed 's/\\u\(....\)/\\x{\1}/g' | ascii2uni -q -a C)"
exit_if_empty "${video_desc}" "Impossible d'obtenir les informations\n${advice_msg}"
# check_desc "${video_desc}" "${video_id}"
video_date="$(sed -n 's+.*\"date_debut..\"\(\([0-9]*\)/\([0-9]*\)/\([0-9]*\) *\([0-9]*\):\([0-9]*\)\)\".*+\4/\3/\2 \5:\6+p' <<< "${video_desc}")"
_video_date=($(date -d "${video_date}" +"%d %m %Y %H %M"))
video_date_day=${_video_date[0]}
video_date_month=${_video_date[1]}
video_date_year=${_video_date[2]}
video_date_hour=${_video_date[3]}
video_date_minute=${_video_date[4]}
video_code="$(sed -n 's+.*\"code_programme..\"\([^\"]*\)\".*+\1+p' <<< "${video_desc}")"
video_title1="$(sed -n 's+.*\"titre..\"\([^\"]*\)\".*+\1+p' <<< "${video_desc}")"
video_title2="$(sed -n 's+.*\"sous_titre..\"\([^\"]*\)\".*+\1+p' <<< "${video_desc}")"
video_season="$(sed -n 's+.*\"saison..\([[0-9]]*\).*+\1+p' <<< "${video_desc}")"
video_episode="$(sed -n 's+.*\"episode..\([[0-9]]*\).*+\1+p' <<< "${video_desc}")"
video_method="http-m3u8"
video_parent_m3u8="$(sed -n 's+.*url..\"\(http[^\"]*m3u8[^\"]*\)\".*+\1+p' <<< "${video_desc}")"
if [[ "${video_parent_m3u8}" != "" ]] # Check availability
then
video_parent_m3u8="$(wget -q -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies "$(wget -q -U "${user_agent}" --save-cookies "${cookies_filename}" --load-cookies "${cookies_filename}" --keep-session-cookies -O - "https://player.webservices.francetelevisions.fr/v1/videos/${video_id}?country_code=FR&w=840&h=472&version=5.18.0&domain=www.france.tv&device_type=mobile&browser=firefox&browser_version=70&os=linux&gmt=%2B1" | sed 's+\\++g; s/u0026/\&/g' | grep -oE "https...hdf[^\"]*.m3u8[^\"]*")" -O - | grep -oE "http[^\"]*")"
else
video_parent_m3u8="" # Not available no need to query
fi
if [[ "${video_parent_m3u8}" =~ ^.*"replay.francetv.fr/startover/".*$ ]]
then
logger critical "Cette vidéo n'est pas encore disponible, veuillez réessayer dans un moment"
fi
exit_if_empty "${video_parent_m3u8}" "Impossible d'obtenir la vidéo\n${advice_msg}"
parse_parent_m3u8 "${tvg}" "${video_parent_m3u8}"
if [[ "${slist}" =~ ^.*"cartons/carton".*$ ]]
then
logger critical "${lock_msg}"
fi
if [[ "${video_parent_m3u8}" =~ ^.*"media-secure".*$ ]]
then
logger warning "Cette vidéo est peut-être verrouillée. Si c'est le cas, il n'y a rien à faire"
fi
video_subtitles="$(sed -n 's+.*\"url..\"\(http[^\"]*vtt\)\".*+\1+p' <<< "${video_desc}")"
;;
"arte")
video_uname="$(basename "${url}" .html | sed 's/_\?,\([0-9]*\)[^0-9]*.*/_\1/g')"
video_id=$((grep -a -oE "http[^\"]*player[^\"]*api[^\"]*" | head -n 1 | grep -a -oE "[0-9]*-[0-9]*-[A-Z]" | head -n 1) <<< "${url_content}")
if [[ "${video_id}" == "" ]]
then
video_id=$((grep -a -oE "name=.[^\"]*programId[^\"]*. * value=.[0-9A-Z-]*." | sed -n 's/.*value=\"\([^\"]*\)\".*/\1/p') <<< "${url_content}")
fi
if [[ "${video_id}" == "" ]]
then
video_id=$((grep -a -oE "http[^\"]*player*[^\"]*" | head -n 1 | grep -a -oE "[0-9]*-[0-9]*-[A-Z]" | head -n 1) <<< "${url_content}")
fi
if [[ "${video_id}" == "" ]]
then
video_id=$((grep -a -oE "