録画サーバ構築 comskip で CMスキップ

録画サーバ構築に関連する要素技術も大分押さえられてきた。あとはCM処理をどうするか検討する。市販のレコーダーになるべく機能を寄せるには、やはりCM前後にチャプターを入れたい。録画ファイルのCM位置を検出するコマンドとしてcomskipというものがあるようだ。このコマンドはLinuxにも移植されていて、CentOS7ならnux-dextopリポジトリからyum installできる。ただし、ffmpegが2系でないとインストール出来ないので注意。あとで使うことになるMP4Boxもインストールしておく。以下の通り。

yum install --enablerepo=epel,nux-dextop comskip gpac

インストールが出来たら、設定ファイルを編集する。設定に使うcomskip.iniはネット上でも色々なバリエーションが存在するので、よさそうなものを頂いて流用させてもらうのがよいかも。自分もぐぐって見つけたものを使わせてもらってます。設定はほぼ流用したままだが、delete_logo_file=1は変更しておいた方がよい。comskip処理時にlogoファイルが生成されるのだが、それをそのままにしてリトライするとSegfaultで処理が失敗してしまうからだ。準備が出来たら以下のようにコマンドを実行する。

comskip test.ts

当たり前のように見えるが、ポイントなのは録画ファイルの存在するディレクトリに移動してから、コマンドを実行すること。対象ファイルを絶対パスで渡すと、なぜかCMをほとんど検知してくれないからだ。細かい原因は調べていないが、とりあえずカレントで動かせば特に問題ないので、そのように処理させている。しばらく待てばvdrファイルが出来て、その中に以下のようなフォーマットでCMの時間が記録されている。

cat test.vdr
0:00:00.00 start
0:05:03.75 end
0:22:50.58 start
0:25:04.38 end
0:49:03.08 start
0:51:29.36 end
0:54:42.59 start
1:00:30.84 end

このデータを元にTSファイルのCMを分断してる方も多いようだが、自分の場合はmp4ファイルに対してチャプターとして設定している。このチャプター設定を行う際にMP4Boxコマンドが必要となる。vdrファイルをMP4Box用のフォーマットに変換する。以下のような処理となる。

#!/usr/bin/perl
use File::Basename;
my ($filename)=fileparse($ARGV[0], ".vdr");
open(VDR,"<$filename.vdr");
open(CHP,">$filename.chp");
my $count=0;
while(my $line=<VDR>){
  $count++;
  my $chapnum=sprintf("%02d", $count);
  my ($chaptime)=split(/\s+/, $line);
  print CHP "CHAPTER$chapnum=$chaptime\n";
  print CHP "CHAPTER${chapnum}NAME=chap$chapnum\n";
}
close(VDR);
close(CHP);

このscriptで生成したtest.chpは以下のようなフォーマットになる。

cat test.chp
CHAPTER01=0:00:00.00
CHAPTER01NAME=chap01
CHAPTER02=0:05:03.75
CHAPTER02NAME=chap02
CHAPTER03=0:22:50.58
CHAPTER03NAME=chap03
CHAPTER04=0:25:04.38
CHAPTER04NAME=chap04
CHAPTER05=0:49:03.08
CHAPTER05NAME=chap05
CHAPTER06=0:51:29.36
CHAPTER06NAME=chap06
CHAPTER07=0:54:42.59
CHAPTER07NAME=chap07
CHAPTER08=1:00:30.84
CHAPTER08NAME=chap08

このchpファイルを使って、以下のようなコマンドでmp4ファイルに対してチャプターを付与する。

MP4Box -chap test.chp -out test_chap.mp4 test.mp4

これでチャプター付きのmp4ファイルを生成できる。幾つかの視聴ソフトで試してみたが、期待通りにチャプターとして動作してくれる。あえて言うとカーナビだけはこのチャプターを誤解釈してしまった。詳細はいずれ。当初はTSファイルに対してcomskipをかけてCM検出していたのだが、何かをきっかけに幾つかのTSファイルのCM検知精度が著しく落ちてしまった。ネット上のcomskip.iniを見比べて、いろいろなパラメータを試してみたが、検知精度は回復していない。ffmpegのバージョンとかなのかなあ。

とりあえずmp4ファイルに対してなら高い精度で検出してくれるので、mp4ファイルに対してcomskipを実行している。mp4ファイルの方がデータサイズも小さいし、実は処理効率よかったりするのかな。ちなみにmp4ファイルに対する検出もNVENCで作ったものはCM検知精度が低いので、QSVエンコードで作ったmp4ファイルに対してcomskipしている。この辺の差異もまだよくわかっていない。時間のあるときにもう少し調べないと。次回は要素技術として検証してきたQSVエンコードとcomskipをepgrecの処理の中に組み込んでいく。