2019年7月5日金曜日

動画圧縮し直しスクリプトをまた直した

Ubuntuのインストールし直しで色々な作業をしているが、今年直したばかりの動画圧縮し直しスクリプトもまた直した。

ffmpegのaacのエンコーダが変わったようで、エンコーダの指定を変更する必要があった。
また、サイズの取得に失敗するときがあったので、サイズの取得方法を強化した。
ついでに、出力ファイルがすでに存在している場合、ファイル名の末尾に"-<数字>"を付けるようにした。
$ source-highlight --out-format=html -i ~/bin/toH264.sh
#!/bin/bash
SRCFILE=$1
DSTFILE=$2

if [ -z "$DSTFILE" ]; then
    BASENAME=$(basename $SRCFILE)
    DSTFILE=${BASENAME%.*}.mp4
fi

DIRNAME=$(dirname $DSTFILE)
BASENAME=$(basename $DSTFILE)
i=0
while [ -e "$DSTFILE" ]; do
    i=$(( i +1 ))
    DSTFILE=$DIRNAME/${BASENAME%.*}-${i}.mp4
done

#---------------------------------------------------------------#
#  Extract informations from source video.                      #
#---------------------------------------------------------------#
CREATION_TIME=""
ENCODER=""
videoFormat=""

while read s; do
    s=$(echo $s | sed -e "s/^ *//g");

    if [[ "$s" == creation_time\ :* ]]; then
        if [ -n "$CREATION_TIME" ]; then
            echo "creation_time duplicated. Discard candidate $CREATION_TIME"
        fi
        CREATION_TIME=$( echo $s | sed -e "s/^[ \t]*creation_time[ \t]\+:[ \t]\+//g" )
    fi

    if [[ "$s" == encoder\ :* ]]; then
        ENCODER=$( echo $s | sed -e "s/^[ \t]*encoder[ \t]\+:[ \t]\+//g" )
    fi

    if [[ "$s" == Stream\ *:\ Video:* ]]; then
        videoFormat=$( echo $s | sed -e "s/^[ \t]*Stream \+#.*: \+Video: \+//g" )
    fi
done < <( ffprobe ${SRCFILE} 2>&1 )


echo creation_time=$CREATION_TIME, ENCODER=$ENCODER, videoFormat=$videoFormat

#exit 0
#CREATION_TIME=$(ffprobe $SRCFILE 2>&1 | grep "creation_time" | head -n 1 | sed -e "s/[ \t]*creation_time[ \t]*:[ \t]*//g")

echo SRC: $SRCFILE
echo DST: $DSTFILE
if [ -z "$CREATION_TIME" ]; then
    echo "No \"creation_time\" metadata. use ctime."
    CREATION_TIME=$(stat "$SRCFILE" | grep "^Change:" | head -n 1 | sed -e "s/^Change:[ \t]*//g" | sed -e "s/\.[0-9]* +.*$//g")
fi
echo CERATION_TIME: \""$CREATION_TIME"\"

#---------------------------------------------------------------#
# Auto bitrate                                                  #
#   H.264には、エンコード品質を表すBPP(Bit Per Pixel)という     #
#   指標がある。                                                #
#   BPPを用いて、ビットレートは以下のように計算される。         #
#                                                               #
#                       BPP x fps x width x height              #
#     bitrate[kbps] = ------------------------------            #
#                                  1000                         #
#                                                               #
#   H.264のBPPは、動画の動きの速さと、品質で以下のように        #
#   決まっている。                                              #
#                |               品  質                         #
#                |---------+---------+---------+--------        #
#                |   最高  |   高    |   中    |   低           #
#     -----------+---------+---------+---------+--------        #
#       高  速   |  0.225  |  0.175  |  0.125  |  0.100         #
#       中  速   |  0.200  |  0.150  |  0.100  |  0.075         #
#       低  速   |  0.175  |  0.125  |  0.075  |  0.050         #
#                                                               #
#           高速: スポーツまたはミュージックビデオ              #
#           中速: 映画                                          #
#           低速: ナレータ(ニュースや演説など)                  #
#                                                               #
#---------------------------------------------------------------#
#videoFormat=$( ffprobe ${SRCFILE} 2>&1 | \
#               grep "Stream \+#[0-9]:[0-9]: \+Video: \+" | \
#              sed -e "s/^ \+Stream \+#[0-9]:[0-9]: \+Video: \+//g" );

#bpp="0.225"
bpp="0.125"
width_height=$(echo ${videoFormat} | sed -e 's/^.*, \([0-9]\+x[0-9]\+\), .*$/\1/g')
if [[ ! "$width_height" =~ ^[0-9]+x[0-9]+$ ]]; then
    width_height=$(echo ${videoFormat} | sed -e 's/^.*, \([0-9]\+x[0-9]\+\) \+\[.\+\], .*$/\1/g')
fi
if [[ ! "$width_height" =~ ^[0-9]+x[0-9]+$ ]]; then
    echo "Unknown video size." 1>&2
    exit 1
fi

width=$(echo ${width_height}  | sed -e 's/ *\([0-9]\+\)x[0-9]\+ *$/\1/g')
height=$(echo ${width_height} | sed -e 's/ *\+[0-9]\+x\([0-9]\+\) *$/\1/g')
fps=$(echo ${videoFormat}    | sed -e 's/^.*, \+\([0-9.]\+\) \+fps,.*$/\1/g')

if [ -z "$width" -o -z "$height" -o -z "$fps" ]; then
    echo "cann't get information for bitrate. Use 8192kbps"
    vBitrate=8192k
else 
    echo "bpp=$bpp, width=$width, height=$height, fps=$fps"
    vBitrate=$(echo "scale=0; $bpp * $width * $height * $fps / 1000" | bc)"k"
fi

echo "bitrate=${vBitrate}"
#exit 0

#---------------------------------------------------------------#
# Convert video format                                          #
#---------------------------------------------------------------#
ffmpeg -i $SRCFILE -nostdin -y -acodec aac -profile:a aac_low -b:a 128k -ar 44100 -ac 2 -vcodec libx264 -profile:v main -b:v ${vBitrate} -pix_fmt yuv420p -f mp4 -metadata "creation_time"="$CREATION_TIME" -metadata "encoder"="$ENCODER" $DSTFILE

# No audio
#ffmpeg -i $SRCFILE -nostdin -vcodec libx264 -profile:v main -b:v ${vBitrate} -pix_fmt yuv420p -f mp4 -metadata "creation_time"="$CREATION_TIME" -metadata "encoder"="$ENCODER" -map 0:0 $DSTFILE

touch -r ${SRCFILE} ${DSTFILE}
Ubuntu 18.04のffmpegのaacエンコーダ指定にしてしまったので、16.04で使うなら以前のスクリプトを参考に、最後の方をかきかえろ。

なんか最近、linux関連記事ばかり書いているな…

0 件のコメント:

コメントを投稿