α7とBessaflex、OPTIMAとの大きさ比較
LinuxでTS→MP4変換、現状の最適解(自己満足)
いろいろハマってたどりついた、現状の最適解。
とりあえず1ヶ月分を変換してみたけど、問題っぽい問題は出なかったです。
(1) recfsusb2n改
・http://d.hatena.ne.jp/kinumi/20110611/1307770437
・http://d.hatena.ne.jp/kinumi/20110702/1309597287
↓
(2) TsSplitter
・Windowsソフトウェアなので、Wineで。
・オプション:-SD -1SEG -SEP -PTS -LOGFILE
↓ 分割されたファイルのうち、最大のファイルを選択して処理
(3) HandBrakeCLI
・オプション:-Z "Universal" -r 29.97 -X 640
↓
(4) ffmpeg
・これ対策 → http://mycometg3.blog.so-net.ne.jp/2008-05-11
・オプション:-acodec copy -vcodec copy
aacが厄介(2)
昨日の日記ではヘッダを
FF F8 XX 80
と仮定して処理を行っていましたが、どうやら
FF F8 XX 40
となっている放送もあるようです。
ですので、昨日のスクリプトを修正しました。
「FF F8」が登場したら、それ以降を抜き出します。
使用は自己責任で。無保証。
#!ruby # # fixaac.rb # # usage: # ruby fixaac.rb INFILE OUTFILE # ifn = ARGV[0] ofn = ARGV[1] open(ifn) do |fi| found = false until fi.eof? byte1 = fi.read(1) if byte1[0] == 0xff byte2 = fi.read(1) if byte2[0] == 0xf8 found = true break end end end if found puts "Header is found. Processing..." fi.seek fi.pos - 2 open(ofn, "w") do |fo| until fi.eof? fo.write fi.read(1024 * 1024) end end else puts "Invalid AAC file." end end
aacが厄介
(2011/07/13 追記)
下記だと音声がぶっ飛ぶケースがあり、調査したところ
FF F8 4C A0
というヘッダも存在しているみたいです。なので
FF F8
だけみるようにする必要があるきがします。
うまくいったらまた書きます。
(2011/07/13 追記2)
スクリプトを修正しました。
aacが厄介(2) - looselife diary
直接fsusb2の話題ではないんですが一応。
録画した番組を自動的にmp4にするスクリプトを作って運用しているんですが、うまくいかない場合があります。
しかもかなり頻繁にある、というか成功するほうが少ない印象です。
いろいろな方法を試してみているんですが、どの方法もダメ。
ダメな場合に出てくるのは決まってAAC関連のエラーメッセージっぽいです。
んで、今現在たどり着いたのが以下のページ。
これは、放送波上の AAC データには、 raw data の前に ADTS ヘッダが付加されていることが多いのですが、この「ヘッダ・データ」の構造が正常に維持されず、ファイルがデータ部の途中から開始していると、ファイルの先頭に ADTS ヘッダが来ず、いきなりデータ部から始まるということになってしまい、 ADTS ヘッダのパースが正常にできないためにエラーが出力される、ということです。
http://d.hatena.ne.jp/RobinEgg/20090420/p1
うーん。ぽいなあ。これっぽい。うん、これに違いない。
id:RobinEggさんはaacの構造を修復するツールをpythonで作ってくださっています。
んですが、せっかくなので自分でも作ってみました。rubyで。
まだ全部がうまくいっているわけではないので、ちゃんと動いているのかはよくわかりません。
とりあえず、このプログラムを通すと先頭4バイトが「FF F8 XX 80」となることは確認してます。
再生も可能っぽいです。
使用は自己責任で。無保証。
#!ruby # # fixaac.rb # # usage: # ruby fixaac.rb INFILE OUTFILE # ifn = ARGV[0] ofn = ARGV[1] open(ifn) do |fi| found = false until fi.eof? byte1 = fi.read(1) if byte1[0] == 0xff byte2 = fi.read(3) if byte2[0] == 0xf8 && byte2[2] == 0x80 found = true break end end end if found puts "Header is found. Processing..." fi.seek fi.pos - 4 open(ofn, "w") do |fo| until fi.eof? fo.write fi.read(1024 * 1024) end end else puts "Invalid AAC file." end end
Atom + recfsusb2n
Vaio Type P (Atom Z540) にて録画サーバを作って運用しています。
Atomは非力なCPUですので、録画時のCPU使用率が80%〜100%となってしまいます。
それが原因かは定かではありませんが、電波状況は良いのに、割と頻繁にTSの取りこぼしが発生します。
なんとかCPU負荷を下げられないか、色々と試行錯誤してみたところ、
recfsusb2nのコンパイルオプションをAtom向けに設定することで、
CPU使用率を15〜20%程度まで下げることができました。
これでTSの取りこぼしが無くなるかは不明ですが、しばらくこれで運用してみようかと思います。
パッチ
recfsusb2n 0.9.2 に対するパッチです。無保証。
--- ./FSUSB2N.org/Makefile 2011-03-21 01:34:39.000000000 +0900 +++ ./recfsusb2_custom/Makefile 2011-07-02 17:31:14.872231254 +0900 @@ -8,7 +8,9 @@ endif CXX = g++ -CXXFLAGS = -g -Wall -pthread -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(B25) +CXXFLAGS = -O3 -mfpmath=sse -msse -msse2 -msse3 -mtune=atom -march=atom -g -Wall -pthread -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(B25) +CC = gcc +CFLAGS = -O3 -mfpmath=sse -msse -msse2 -msse3 -mtune=atom -march=atom -g -Wall -pthread -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(B25) OBJS = fsusb2n.o usbops.o em2874-core.o ktv.o IoThread.o $(B25_OBJS) #LIBS = -lpthread -lboost_system -lboost_thread-mt -lboost_filesystem LIBS = -lpthread -lboost_thread-mt -lboost_filesystem
リンク
recfsusb2n for linux
http://tri.dw.land.to/fsusb2n/recfsusb2n.html
recfsusb2nで初期のストリームを捨ててみる
先日、USB地デジチューナーのKTV-FSUSB2を購入しました。
Ubuntu 11.04で、recfsusb2nを使って録画サーバを構築できています。
先人に感謝です。
録画サーバとしては正常に動いてはいるものの、気になる点がありました。
録画したTSが、ffmpegやmencoderなどのツールで受け付けられないんです。
ffmpegだとこんな感じ。
$ ffmpeg -i /tmp/err.ts ...略... [NULL @ 0x9a4e420]Format detected only with low score of 25, misdetection possible! [mp1 @ 0x9a4f720]Header missing Last message repeated 1 times [mpeg @ 0x9a4e420]pes_ext F0 is invalid [mp1 @ 0x9a4f720]Header missing Last message repeated 200 times [ac3 @ 0x9a53cc0]frame sync error [mpeg @ 0x9a4e420]Could not find codec parameters (Audio: mp1, 0 channels, s16) [mpeg @ 0x9a4e420]Could not find codec parameters (Video: 0x0000) [mpeg @ 0x9a4e420]Could not find codec parameters (Audio: ac3, 0 channels, s16) [mpeg @ 0x9a4e420]Could not find codec parameters (Video: 0x0000) Last message repeated 1 times [NULL @ 0x9ab9670]start time is not set in av_estimate_timings_from_pts /tmp/err.ts: could not find codec parameters
mencoderだとこんな感じ。
$ mencoder /tmp/err.ts -o dummy.ts MEncoder UNKNOWN-4.5.2 (C) 2000-2011 MPlayer Team success: format: 0 data: 0x0 - 0x1347f6c TS file format detected. VIDEO MPEG2(pid=337) AUDIO MPA(pid=338) NO SUBS (yet)! PROGRAM N. 0 TS_PARSE: COULDN'T SYNC MPEG: FATAL: EOF while searching for sequence header. Video: Cannot read properties. Exiting...
気になったので調べてみました。
TSパケットの解析
TSはTSパケットと呼ばれる188バイトのパケットの集合体でできています。
その中身を見てみました。
00000000 1 1 1 036C 00000001 1 0 1 1500 00000002 1 0 0 1D3A 00000003 1 0 0 0148 00000004 1 0 0 1164 00000005 1 0 0 0154 00000006 1 1 1 1167 00000007 1 0 0 11C4 00000008 1 0 1 1B99 00000009 1 1 1 1078 00000010 1 1 1 1354 00000011 1 0 0 1400 00000012 1 0 0 0109 00000013 1 1 1 13B6 00000014 1 0 0 08BB 00000015 1 1 0 1E41
先頭の数字が受信したパケットの番号、その次の3つの数字がそれぞれトランスポートエラーインジケータ、ペイロードスタートインジケータ、トランスポート優先度、最後の記号がPIDを表しています。
ことごとく、トランスポートエラーインジケータが立っています。PIDもめちゃめちゃです。
どうやらこのチューナー、録画を開始してから受信が落ち着くまで、しばらく時間がかかるっぽいです。
うちの環境では先頭から6000パケットあたりで安定し始め、だいたい7000-10000パケットあたりで完全に安定します。
10000パケット目からみてみると、こんなかんじ
00010000 0 0 0 0100 00010001 0 0 0 0100 00010002 0 0 0 0100 00010003 0 0 0 0583 00010004 0 0 0 0100 00010005 0 0 0 0100 00010006 0 0 0 0100 00010007 0 0 0 0100 00010008 0 0 0 0100 00010009 0 0 0 0164 00010010 0 0 0 0100 00010011 0 0 0 0100 00010012 0 0 0 0100 00010013 0 0 0 0100 00010014 0 0 0 0100 00010015 0 0 0 0140
きれいですね。
録画するときに、先頭のパケットを捨てる
どうやら、先頭のパケットを削れば良さそうです。
録画してから削っても良いんですが、巨大なTSは録画した後の編集が非常にめんどくさいです。
できれば、録画時に削ってしまいたい、、、
最初に考えたのは、recfsusb2nでTSを標準出力に吐き出して、それをごにょごにょする方法。
実際にやってみたんだけども、CPU負荷がすごいです。Atomが悲鳴をあげてる;;
ごにょごにょするツールがRubyだ、てのもあるかもしれません。Cだと話は変わるかも。
次に考えたのが、recfsusb2nに手を入れちゃう方法。
recfsusb2nはTSパケットを意識してないっぽかったので、最初の2回分の受信を捨てることにした。
時間にしておそらく1秒くらいじゃないかな。ということで、うまくいったっぽい。
正常なTSになったっぽい
$ ffmpeg -i test.ts ...略... Input #0, mpegts, from 'test.ts': Duration: 00:00:09.15, start: 82202.683756, bitrate: 16324 kb/s Program xxxxx Metadata: name : xxxxx provider_name : Stream #0.0[0x111]: Video: mpeg2video, yuv420p, 1440x1080 [PAR 4:3 DAR 16:9], 24000 kb/s, 30.34 fps, 29.97 tbr, 90k tbn, 59.94 tbc Stream #0.1[0x112]: Audio: aac, 48000 Hz, stereo, s16, 226 kb/s Stream #0.2[0x114]: Data: 0x0006 Stream #0.3[0x810]: Data: 0x000d Stream #0.4[0x811]: Data: 0x000d Stream #0.5[0x81a]: Data: 0x000d Stream #0.6[0x81f]: Data: 0x000d Stream #0.7[0x816]: Data: 0x000d Stream #0.8[0x81b]: Data: 0x000d Program xxxxx Metadata: name : xxxxx provider_name : Stream #0.0[0x111]: Video: mpeg2video, yuv420p, 1440x1080 [PAR 4:3 DAR 16:9], 24000 kb/s, 30.34 fps, 29.97 tbr, 90k tbn, 59.94 tbc Stream #0.1[0x112]: Audio: aac, 48000 Hz, stereo, s16, 226 kb/s Stream #0.2[0x114]: Data: 0x0006 Stream #0.3[0x810]: Data: 0x000d Stream #0.4[0x811]: Data: 0x000d Stream #0.5[0x81a]: Data: 0x000d Stream #0.6[0x81f]: Data: 0x000d Stream #0.7[0x816]: Data: 0x000d Stream #0.8[0x81b]: Data: 0x000d Program xxxxx Metadata: name : xxxxx provider_name : Stream #0.10[0x151]: Video: h264, yuv420p, 320x180, 8.83 fps, 14.99 tbr, 90k tbn, 14.99 tbc Stream #0.9[0x152]: Audio: aac, 48000 Hz, stereo, s16, 46 kb/s Stream #0.11[0x154]: Data: 0x0006 At least one output file must be specified
パッチ
recfsusb2n 0.9.2 に対するパッチです。無保証。
fsusb2n.cpp
@@ -183,10 +183,17 @@ usbDev->startStream(); // Main loop + int stream_counter = 0; while (!caughtSignal && (args.forever || time(NULL) <= time_start + args.recsec)) { usleep(750000); const void *buf = NULL; int rlen = usbDev->getStream(&buf); + + stream_counter++; + if (stream_counter < 2) { + continue; + } + if (0 == rlen) continue; #ifdef B25 // B25を経由して受け取る
リンク
recfsusb2n for linux
http://tri.dw.land.to/fsusb2n/recfsusb2n.html