FLVビデオから音声を切り出して無音部分を検出
ちょいと研究室のほうで要望があったのでやってみました。
ffmpegとdumpwave.cとphpを使います。
まずは下準備としてwaveファイルをphpが扱いやすいテキスト形式に変換します。
便利なプログラムがあります。
「WAVE ファイルの内容を調べる拙作プログラム dumpwave.c 」
http://oku.edu.mie-u.ac.jp/~okumura/wavefmt.html
これをメモ帳でもいいので、保存してコンパイルします。
コンパイル方法はプログラムにも書かれているようにgccだけでOKです。
cygwinでgccを入れれば簡単にコンパイルできます。
gcc dumpwave.c -o dumpwave.exe
コンパイル後、windows環境でも動くようにdumpwave.exeとcygwin1.dllファイルを一緒のフォルダに置いておきます。
#こうしておくとダブルクリックなどでとりあえず実行できるようになります。
次に、flvビデオからwaveファイルの抜き出しです。
ffmpeg.exe -y -i video.flv -ar 16000 video.wav
そして、抜き出したwaveファイルを先ほど準備した、dumpwave.cにてバイナリ⇒テキスト化します。
dumpwave.exe video.wav > video.txt
これでひとまず音声ファイルがテキスト化されphp側で処理しやすくなります。
次に取り出した音声のファイルからボリュームをゲットします。
ここは自分もちょっと怪しいですが、php側で以下の感じになります。
<?php // $data1 = array(); $rate = 1; $j = 1; $rate_a = array(); $block = 160; /* $ns2s = array( "120" => 1000/8, "160" => 1000/10, "256" => 1000/16, "320" => 1000/20, ); */ $fp = fopen( "video.txt" , "r" ); while( $line = fgets( $fp ) ){ //160個ずつ配列に入れる $rate_a[$j][] = intval( trim( $line ) ); if( $rate == $block ){ //ブロックの最大値と最小値の差 = Volume $max[$j] = ( abs( max( $rate_a[$j] ) ) + abs( min( $rate_a[$j] ) ) )/ 2; $rate = 1; $j++; } $rate ++; } //ファイルへの書き出し $outputfile = "video.csv"; $fp = fopen( $outputfile , "w"); foreach ($max as $key => $val ){ fputs( $fp , intval( trim( $val ) ) . "\n" ); } fclose( $fp ); ?>
上のプログラムで得られる$maxをグラフ化するとこんな感じになります。
横軸が時間(100で1秒)で縦がボリュームです。