FC2ブログ

PCで: FFmpeg:MPEG-2 TS→MPEG-4でAACのオーディオをコピー

 どういう状況なのかについては説明を省略することにしますが(笑)、FFmpegのffmpegコマンドを使ってMPEG-2 TSのデータをMPEG-4にするとき、オーディオをコピーするやり方についてです。
注) 下記2016-11-23付けの追記を参照のこと。

 以前は変換が面倒なのでMPEG-2 TSのデータをBDにそのまま焼いていたのですが、でき上がる枚数や焼く時間のことを考えると圧縮をかけた方が実はいいかなと思い、最近はMPEG-4に圧縮しています。
 そんな理由なので、1bitでも小さく!みたいな圧縮効率は追求していません。

 で、メインテーマのオーディオについてです。
 以前手抜きをして適当に圧縮したら、後で見た時に酷い目に遭いました。人の声が……最初は気にならなかったのですが見ていてしばらくしたら耳をガリガリとやすりで削られているような気分になってきて。それからビットレートを上げるようにしました。
 しかしちょっと考えてみたら、元々ビデオに比べるとそう大きいデータでもないのでそもそも変換する必要もないじゃん無駄だし、ということに気付きました。時間やCPUの無駄というのもありますが、変換することでロスが発生するし。

 元データのオーディオはAACだしMPEG-4でも規格上AACは可能なはずなので、"-acodec copy" とかやってみたのですがエラーになります。MPEG-4にはそんなの入れられないよ、と。はてな?

 てなわけで調べてみたら、AACにも色々あって、元データのAACとMPEG-4で許容しているのが微妙に違うのだとか。正確なところまでは調べていませんが。
 うーん、じゃあどうしよう、と思って今度はffmpegの仕様の方を調べてみたら、なーんだ、ちゃんと用意されていました。

 ビットストリームフィルターという機構があって、その中にaac_adtstoascというのがありました。

2.1 aac_adtstoasc

Convert MPEG-2/4 AAC ADTS to MPEG-4 Audio Specific Configuration bitstream filter.

This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4 ADTS header and removes the ADTS header.

This is required for example when copying an AAC stream from a raw ADTS AAC container to a FLV or a MOV/MP4 file.


 というわけで、"-bsf aac_adtstoasc" というコマンドラインオプションを使えばいいのですね。これで、コンテナの仕様の問題はクリアできました。

 ところが、"-acodec copy -bsf aac_adtstoasc" だと、たまに別のエラーが出ます。"PES packet size mismatch" というものです。
 どうやら、生のまま何の変換もしないことで、元データにエラーがあったり、もしかするとPES(Packetized Elementary Stream)がデータの途中で終わってしまってそのまま送り込まれてってなこともあるかな、などと思われます。
 というわけでもう一度調べてみたら、今度はこんなオプションを見つけました。

2. Format Options

The libavformat library provides some generic global options, which can be set on all the muxers and demuxers. In addition each muxer or demuxer may support so-called private options, which are specific for that component.
(snip)
‘fflags flags (input/output)’
(snip)
‘discardcorrupt’

Discard corrupted frames.

 うーん、何か他にも影響ありそうな気がしないでもないですが、とりあえずやってみたら見事に出なくなりました。
 ちなみに、解説にあるように global options なので、最初に指定します。結局、こんな感じ。
ffmpeg -fflags +discardcorrupt -i INFILE.ts ... -codec:a copy -bsf:a aac_adtstoasc OUTFILE.mp4

 ところで、上記のコマンドラインで省略したビデオの部分ですが、ネットをふらついていて見つけた実測によると、変換元と先のピクセル数を同じにすると変換時間が短縮されるようですね。なんとなく直観的に正しそうな気がします。ただ、複雑なアルゴリズムが間に挟まるので理論上もそう言えるかというとよくわかりませんが。
 というわけで、例えば元データが 1440x1080 だとしたら無理に 1920x1080 にしたりしない方がいいのでしょう。

 ただ、1440x1080 は 16:9 ではないので、下手をすると縦長の動画ができ上がってしまいます。
 それを避けるためには、"-aspect 16:9 -s 1440x1080" みたいにすればいいようですね。

 そんなこんなで、毎回コマンドを打つのは面倒なのでシェルスクリプトにしたのですが、それでも毎回指定する、けど汎用的でない部分ってのがあるので、"-A" オプションというのを作り、そこに私の環境に固有の設定を詰め込みました。でき上がったデータの置き場所を設定したり、私が使っているシステムで作られるファイルの名前を自動判別してそこから各種オプションを設定したり。
 ちなみに、今回公開するにあたりその "-A" オプションで自動設定されるディレクトリも私の環境と違うものにしました。匿名化のために(笑)。

 元データの情報を引っ張り出すのに物凄く無駄なことをしているのですが、ちゃんと調べればもっといい方法が多分あるんでしょうね。その内調べてみようと思っています。

 というわけでそのスクリプトがこれです。拡張子が .txt なのはブログの制限より。
 過去に使ったオプションがコメントで残っていて微笑ましい(?)ですね。

[追記: 2016-05-22]
 先日(2016-05-08)のエントリを書いてちょっと思い出したので、その後若干改良されたバージョンを置いておきます。'-S' (Sound only)オプションなんて作ってあったりします。
 また、(バッド?)ノウハウですが、たまに、でき上がったMP4で音がしないことがあります。これは、"-G '-ss 1'" のようなオプションを付けてやる(つまりスタートをちょっとずらす)と大概改善されます。
 あと、NHKでは映像と音が数秒ずれたりすることがたまにあるのですが、これはまだ解決方法がわかりません。
[追記: 2017-08-11]
 音がずれるケースについては、どうしてかはわかりませんが回避できたっぽい?
[追記終わり]
[追記終わり]
[追記: 2017-01-22]
 いつ直したか忘れましたが、aac_adtstoascの指定の仕方(コマンドシンタックスレベルの)を訂正していたので新しいのをts2mp4_sh3.txtとして置いときます。
 まあでもこれ直しても、実際にはヘッダのパースでエラーが出るデータが多いみたいですけど。
[追記終わり]

[追記: 2016-11-23]
 この方法で作ったMP4、実はちょっと問題あるかも知れません。
 PCの環境を色々新しくしてみたら、Audaciousがエラーを出します。"Prediction is not allowed in AAC-LC" というメッセージで、これはFFmpeg由来のもののようです。
 変更前はFFmpegの2.3.6をリンクしていたのですが、新しく作ったAudaciousでは3.1.5にしていて、もしかするとフラグのチェックとかが厳密になったのかも知れません。
 とりあえず、極めて後ろ向きな解決策ですが、VLCのために古い(2.3.6の)FFmpegも残しているので、今はAudaciousをリンクし直してそれで再生しています。

コメント

非公開コメント

FFmpeg

詳しいご説明ありがとうございます。
ts動画をffmpegでmp4に変換しようとしたところ、

"start time for stream 2 is not set in estimate_timings_from_pts"
"Could not find codec parameters for stream 2 (Audio: aac ([15][0][0][0] / 0x000F), 0 channels, fltp): unspecified sample rate
Consider increasing the value for the 'analyzeduration' and 'probesize' options"

というwarningが表示されて、調べていたところ水響風さんのブログに行き着きました。

一度ts動画を-acodec copy -vcodec copyでまたtsに素通し変換してからh264でmp4に変換すると特に何もwarningは出ないのですが、これで良いものなんでしょうか?
素通しエンコしないで変換したmp4も違和感なく視聴できたのですが、warningが出ると少しスッキリしないもので...

あとは定番の
"PES packet size mismatch"
"AAC bitstream not in ADTS format and extradata missing"
ですね。特にNHKの番組を変換しようとするとこのwarningがよく表示されます。

最後に一つ、これは私自身の問題なのですが、水響風さんのように今後シェルスクリプトを作成していきたいのですが、どのように学んだのでしょうか? おすすめのサイトあるいは教材等ありましたら教えてくれると幸いです。

Re: FFmpeg

> 詳しいご説明ありがとうございます。
いえいえ。本文にも表れていますが、MP4を勉強しないで場当たりでやっているので、色々とお恥ずかしい限りです。

> "start time for stream 2 is not set in estimate_timings_from_pts"
> "Could not find codec parameters for stream 2 (Audio: aac ([15][0][0][0] / 0x000F), 0 channels, fltp): unspecified sample rate
思うのですが、これはそういうものなのではないでしょうか。
放送のMPEG2 TSには音声や映像の他にも色んな情報が混ざって飛んできているので、そこにはffmpegが知らないような形式になっているstreamもあるだろうと思います。
で、"-acodec copy -vcodec copy"のようにすると音声と映像だけになるのでメッセージも出なくなる、ということなのでは。

他の警告等についてはまあ、再生できればいいや的な感じでやっています。でも、もうちょっと勉強してやりたいこともあるんですけど。

> 今後シェルスクリプトを作成していきたいのですが、どのように学んだのでしょうか?
私の場合はあまり参考にならないかも知れません。元職業プログラマだったので。
LinuxなどUNIX系のシステムを使っているのなら、色んなところに色んなシェルスクリプトがある筈なので、それらを読んでみるといいのではないでしょうか。意外と/etcの下にあるものなどお勧めかも。
あとは、man pageですね。ちなみに、英語版を読むと日本語版にない機能が載ってたりすることもあるかも?

シェルスクリプトを勉強する場合固有のポイントは、それが元々シェルであることを意識することだと思います。つまり、プロセスを起動しているということ。
では具体的にどんな注意点があるかというと、代表的なのは、空白の扱いには神経質になるべきということでしょうか。
"$@"と"$*"の違いとか、変数Aが空だった場合の"$A"と$Aの違いとか。起動されるプロセスの引数の数が変ってしまいますから。また、if文の条件の式でもおかしなことになる場合があります。
他にも、while文の中で変数を変更しているのに抜けると変っていないなと思ったら、whileの出力をパイプで別のプロセスにつないでいた、つまりwhileも別プロセスだったというようなケースとか。

役に立つかどうかわかりませんが、ご参考までに。
プロフィール

水響俊二

Author:水響俊二
水響 俊二 [MIZUKI Shunji]

暫定的に、18禁作品の感想などは裏サイトで書いています。
   

最新記事
最新コメント
カテゴリ
検索フォーム
リンク
RSSリンクの表示
月別アーカイブ
アクセス解析中