From 5706de388de66b3f2f30f89ef71492cb6a75caa2 Mon Sep 17 00:00:00 2001 From: Pierre Neidhardt Date: Sat, 22 Feb 2014 17:12:59 +0100 Subject: [PATCH] tc-video-generic: big refactoring using ffprobe --- .scripts/tc-video-generic | 63 +++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/.scripts/tc-video-generic b/.scripts/tc-video-generic index 824adbcc..8ddd5086 100755 --- a/.scripts/tc-video-generic +++ b/.scripts/tc-video-generic @@ -141,12 +141,6 @@ if ! command -v ffmpeg >/dev/null; then exit fi -_duration() -{ - ## In seconds. - ffmpeg -nostdin -i "$1" 2>&1 | awk '/Duration/ {split($2, time, /:|\./); print time[1]*60*60 + time[2]*60 + time[3]}' -} - _highfreq() { awk 'BEGIN{max=0} /crop=/ {t[$NF]++; if (t[$NF]>max) {max=t[$NF]; val=$NF}} END{print val}' @@ -157,7 +151,7 @@ _cropvalue() ## For 5 different timeslices of 1 second at every 1/6th of the video, we ## sample the crop values. We keep the values with highest frequency. This ## is much faster than encoding in one pass with low framerate. - STEP=$(($(_duration "$1")/6)) + STEP=$((${format_duration:-$streams_stream_0_duration}/6)) for i in $(seq $STEP $STEP $((5*$STEP))); do ffmpeg -nostdin -ss $i -i "$1" -t 10 -vf "cropdetect=24:2:0" -f null - 2>&1 done | _highfreq @@ -165,7 +159,7 @@ _cropvalue() _croppreview() { - STEP=$(($(_duration "$1")/6)) + STEP=$((${format_duration:-$streams_stream_0_duration}/6)) for i in $(seq $STEP $STEP $((5*$STEP))); do ffmpeg -nostdin -v warning -y -ss $i -i "$1" \ -f image2 -vframes 1 $VIDEO_FILTER "${1%.*}-preview-$i-cropped.png" \ @@ -173,23 +167,29 @@ _croppreview() done } +## Return the audio encoding parameters. For instance +## -c:2 libvorbis -b:2 384k -c:5 copy +## If some stream bitrates are missing, we have two possibilities: +## either we copy the stream (default), or we encode it to a default value. _audiobitrate() { - ## As of 2013-10-23, ffmpeg sucks at retrieving audio bitrate. Therefore we - ## use mediainfo if available, ffmpeg otherwise. + local bitrate - ## In the end, if some stream bitrates are missing, we have two - ## possibilities: either we copy the stream (default), or we encode it to a - ## default value. + for i in $(seq 0 $(($format_nb_streams-1)) ); do + ## Skip non audio tracks. + [ "$(eval echo \$streams_stream_${i}_codec_type)" != "audio" ] && continue - ## AWK note: in "(bitrate+0 > 500)", the +0 is required to make sure bitrate is numeric. - if command -v mediainfo >/dev/null; then - ## WARNING: mediainfo puts a space every 3 digits, hence the 'for' loop. - mediainfo "$1" | awk 'BEGIN {id=0} /^Audio/ { while(getline && ! index($0,"Bit rate ") && NF != 0); for(i=4; i&1 | awk 'BEGIN {id=0} /^ *Stream.*Audio/ {match($0, / [^ ]+ kb\/s/); res=substr($0, RSTART+1, RLENGTH-6); print id, res; id++}' - fi | awk -v codec="$AUDIO_CODEC" -v bitrate="$AUDIO_DEFAULT_RATE" \ - '{if($2 || bitrate) {if($2) bitrate=$2; if(bitrate+0 > 500) bitrate=500; printf "-c:a:" $1 " " codec " -b:a:" $1 " " bitrate "k "} else printf "-c:a:" $1 " copy "} END {print ""}' + bitrate=$(( $(eval echo \$streams_stream_${i}_bit_rate) / 1000)) + if [ -z "$bitrate" ] || [ "$bitrate" -le 0 ]; then + bitrate="$AUDIO_DEFAULT_RATE" + fi + if [ -n "$bitrate" ] && [ "$bitrate" -gt 0 ]; then + [ $bitrate -gt 500 ] && bitrate=500 + printf -- "-c:%s %s -b:%s %sk " $i "$AUDIO_CODEC" $i "$bitrate" + else + printf -- "-c:%s copy " $i + fi + done } _transcode() @@ -198,10 +198,18 @@ _transcode() OUTPUT="${1%.*}.$EXT" [ -e "$OUTPUT" ] && OUTPUT="${1%.*}-$(date '+%F-%H%M%S').$EXT" + ## Metadata (i.e. tags + technical data). + _buffer="$(ffprobe -v quiet -print_format flat=s=_ -show_streams -show_format "$1")" + if [ $? -ne 0 ]; then + _error "File [$1] is unsupported by FFmpeg." + return + fi + eval "$_buffer" + unset _buffer + STREAM_TITLE="" if $OPT_REMOVE_TITLE; then - STREAM_NUM=$(ffmpeg -nostdin -i "$1" 2>&1 | grep -c 'Stream') - for i in $(seq 0 $STREAM_NUM); do + for i in $(seq 0 $(($format_nb_streams-1)) ); do STREAM_TITLE="${STREAM_TITLE}-metadata:s:$i title= " done fi @@ -237,11 +245,6 @@ EOF $OPT_PREVIEW && return - ## Zsh compatibility. We need it otherwise word splitting of parameter like - ## SAMPLE will not work. - STATUS="$(set -o | awk '/shwordsplit / {print $2}')" - [ "$STATUS" = "off" ] && set -o shwordsplit - ffmpeg -nostdin $OVERWRITE -i "$1" \ $VIDEO_PARAM $VIDEO_FILTER \ $AUDIO_PARAM \ @@ -249,10 +252,6 @@ EOF -map 0 $STREAM_TITLE \ $SAMPLE $TC_VIDEO_OPT "$OUTPUT" - ## Restore Zsh previous options. This will not turn off shwordsplit if it - ## was on before calling the function. - [ "$STATUS" = "off" ] && set +o shwordsplit - if $OPT_OVERWRITE; then rm "$1" mv -f "$OUTPUT" "${1%.*}.$EXT"