Comskipを使って録画データのCMを全自動でカットするスクリプト

先日PT3+Chinachuな録画サーバーを構築したお話をしたわけですが、現在はもっぱらアニメを録画させています。ほとんど見てないけど。

30分の番組を録画してファイルサイズは大体3GB弱。非常にかさばります。もちろんエンコすることでコンパクトに出来るんですが、その前に邪魔なCMを消すことでよりスマートにしようというのが今回の目的であります。

CMをカットするスクリプトといえば、ComskipBatch.rbというrubyで書かれたスクリプト。これを使ってコマンドを打てば手動でCMカットの処理をさせることができるのですが、今回はシェルスクリプトとcronの力を使って全自動でカットさせてしまいたいと思います。

また、CMカットが正常に出来たかも簡易的に判定するようにしました。

Comskipとffmpegのインストールは上記の解説ページ通りにやれば大丈夫でした。

ffmpegのインストールに関してもリンクが張られています。ubuntu14.04 にffmpegをインストールする – UbuntuによるEco Linuxサーバ構築記がそのリンク先なのですが、ここに書かれているコードを全部コピーしてシェルスクリプトとして実行すればワンタッチでいけました。すごい。

最後のエンコードテストだけファイルがないといってエラーになったので、ここは手動でやり直しましたけどね。

というわけで、Comskipとffmpegのインストールが終わったら早速シェルスクリプトを書きましょう。

※この記事に掲載しているスクリプトですが、どうやら動画の長さを正しく判定できなかったりしてなんやかんやうまく動かない場合があるようです。
もし利用する場合はご自分で色々調整されることをオススメ致します。

なお、今回のフォルダ構成ですが、録画先が/server/red/recというディレクトリ。

./rec
┣作業中
┣失敗
┣処理済み
┗CMカット済み

そして中身がこんな感じになっています。掲載するシェルスクリプトではこの構成で作業するようになっているので注意。

シェルスクリプトは/chinachu/recorded.shで、ログを/chinachu/recorded.logに吐いています。

#!/bin/sh

MAILTO="your@mail.address" #通知先メールアドレス
dir="/server/red/rec" #作業ディレクトリ
work=`ls -t $dir |grep m2ts |tail -1` #tsファイルの人はtsに書き換えてね
com=`ps aux |grep ruby |grep Comskip`
rec=`ps aux |grep recpt1 |grep device`

#録画中は中止
if [ "${rec}" != "" ] ; then
 echo "録画中のため中止" >> /chinachu/recorded.log
 exit
fi

#別の処理が進行していれば中止
if [ "${com}" != "" ] ; then
 echo "別ファイル処理中のため中止" >> /chinachu/recorded.log
 exit
fi

#ファイルがあれば作業フォルダへ移動
if [ "${work}" = "" ] ; then
 echo "作業待ちファイルはありません。" >> /chinachu/recorded.log
 exit
else
 echo "$workを作業フォルダへ移動します。" >> /chinachu/recorded.log
 mv $dir/$work $dir/作業中

 time1=`ffmpeg -i $dir/作業中/$work 2>&1 |grep Duration |cut -c16-17`
 echo "$workの元の長さ:$time1" >> /chinachu/recorded.log

#CMカット
ruby /opt/comskip_batch/ComskipBatch.rb --margin 3 --file $dir/作業中/$work --move_to $dir/CMカット済み/

#処理判定
if [ $? -eq 0 ] ; then
 echo "$workのCMカットに成功しました。" >> /chinachu/recorded.log

 time2=`ffmpeg -i $dir/CMカット済み/$work 2>&1 |grep Duration |cut -c16-17`
 echo "$workの処理後の長さ:$time2" >> /chinachu/recorded.log

 timem=`echo "$time1 * 0.7" |bc` #元ファイルの7割以下になっているかどうか

 if [ $timem -gt $time2 ] ; then
  echo "$workのCMカットに失敗した可能性あり。確認してください。" >> /chinachu/recorded.log
  mail -s "$work CM cut failure?" $MAILTO < /chinachu/recorded.log
 else
  echo "$workのCMカットは恐らく正常に終了しました。" >> /chinachu/recorded.log
 fi

 mv $dir/作業中/$work.bak $dir/処理済み
 #万が一移動に失敗したら、クリアを中止
 if [ $? -eq 0 ] ; then
  echo "$workを処理済みフォルダに移動しました。" >> /chinachu/recorded.log
  rm -rf $dir/作業中/*.*
 else
  echo "$workの処理済みフォルダへの移動に失敗しました。クリア中止。" >> /chinachu/recorded.log
  mail -s "$work MV failure." $MAILTO < /chinachu/recorded.log
 fi
 exit

else
 echo "$workのCMカットに失敗しました。" >> /chinachu/recorded.log
 mv $dir/作業中/$work $dir/失敗
 mv $dir/作業中/$work.bak $dir/失敗 #失敗するタイミングがわからないので.bakも
 mail -s "$work CM cut failure." $MAILTO < /chinachu/recorded.log
 exit
fi
fi

ド素人が書いたゴリ押しスクリプトなのでルールとか色々間違えてるかもしれませんが、私の環境ではこれで動いています。

一応上から解説をしていくと、まず一番古い録画ファイル(m2ts)を取得し、パスを$workに格納。

そこから録画中、CMカット中かをプロセスから判定し、作業をしていなければ指定ファイルを作業中フォルダへ移動します。

んでCMカットを行い、ステータスコードを見て成功か失敗か判定、失敗なら失敗フォルダへファイルを移動すると共にメールで通知します。

あ、Comskipの引数に関しては先程の解説ページをご覧ください。この場合はカットしたファイルをCMカット済みフォルダへ移動するということになります。

成功した場合は作業済みフォルダをクリアし、.bakファイルを処理済みフォルダへ移動します。万が一この移動に失敗するとクリアは中止します。

ここまでがCMカット関係。

で、カット前に$time1に動画の長さを格納しています。これはffmpegになんの引数も無くファイルだけ入れると動画情報が表示されることを利用しています。

ちなみに分しか取得していないので、一時間超えの番組だとちゃんと判定出来ないはず。

元の長さに0.7をかけてCMカット後のファイルの長さと比較し、もしこれより小さくなっていたらCMカットに失敗しているかも?ということでメールで通知してくれます。

今のところ30分アニメでのCMカット成功率は100%に近いので、大丈夫だとは思うんですけどね。(試しにアンパンマンをやったら後半全部消えた)

 

で、このスクリプトを保存し、実行権限を与えた上でComskipを実行できるユーザーのcronに登録しましょう。

私は毎時10分に実行するようにしました。

後はこれで放置しておけば、録画データをどんどんCMカットしていってくれます。

まぁ、簡単なシェルスクリプトなのでどんどんカスタマイズしていっていただければいいかなと思います。

 

私のサーバーはCeleronG550というしょっぼいCPUで運用していますが、CMカットまでは一応任せることができています。

CPU更新したい…。



コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)