radikoのflvから取り出したAACはなぜiTunesで読めないのか?

  • http://radiko.jp/ は既存のラジオ放送をWebで同時配信(サイマル放送)してくれている。
  • その番組をradikoroを使って録音すると、20100905220904.flvのようなフラッシュビデオ形式のファイルとして保存される。
  • 保存されたファイルは、大体1時間番組で20MBくらいのサイズ。
  • flvではiTunesiPodが再生してくれないので、radikoroの録音設定でmp3に変換するようにしている。
  • ところが、変換後のmp3は50MBくらいのサイズになってしまう。およそ2.5倍に膨れ上がっているのだ。
  • 今時のハードディスクは、テラバイトが標準になりつつあるので大した問題はない。でも、気分が良くない。
  • 調べてみるとradikoの音声は、HE-AAC 48kbpsのステレオ品質*1らしい。(着うたフルと同等レベル)
  • 上記のHE-AACは、flvというコンテナ*2に収められて、配信されているのだ。
  • そしてHE-AACは、flvの中からそっくりそのまま取り出すことができるらしい。
  • 早速ffmpegコマンドを利用して取り出してみた。
ffmpeg -i 20100905220904.flv -acodec copy 20100905220904.m4a
  • 呆気なく.flvが.m4aに変換されてしまった。
  • 実際には取り出しているだけなので、変換ではない。
  • 出てきた.m4aは.flvと遜色なく、劣化は全くないはず。
  • すんなりこれで解決かと思いきや、問題はそんなに簡単ではなかった。
  • 取り出された20100905220904.m4aを再生しようとしてみるが...
  • iTunesQuickTime Player・Quicklook等のQuickTime系ソフトウェアでは再生できなかったのだ。
  • 一方、VLCMPlayerではちゃんと再生できた。
  • 考えてみれば、flvの時からQuickTime系では再生できなかった。
  • Perianをインストールしているので、基本的にflvは再生できるはずなのに。


プロファイル

  • iTunesをはじめとするQuickTime系がサポートしているのは、LC(Low Complexity)プロファイル。
  • 一方のradikoAACは、MAINプロファイルなのであった。
  • プロファイルが違うと、同じAACでも再生できないのだ...。
  • LC(Low Complexity)とMAINプロファイルの違いは、AACエンコードをどこまで厳密に処理するかの違いのようだ。
    • MAINは、厳密に処理するので圧縮率は高くなるが、メモリーやCPUパワーが必要になる。
    • LC(Low Complexity)は、処理を簡略化し、メモリーやCPUパワーをあまり必要としない。

種類

つまり、AACには3つのプロファイルがある。

  • MAIN
    • エンコード処理を厳密に実行する。(圧縮率は良いが高負荷)
  • LC(Low Complexity)
  • SSR(Scalable Sampling Rate)


さらに、上記AACに以下の技術を適用してエンコードしている場合がある。

  • SBR(Spectral Band Replication:スペクトル帯域複製)*3
  • SBRを適用したAACのことを「HE-AAC*4」あるいは「aacPlus*5」と呼ばれる。


さらに、さらに、上記HE-AACに以下の技術を適用してエンコードしている場合がある。

  • iTunesが再生できるのは、LC(Low Complexity)プロファイルなHE-AACのみ。(HE-AAC v2はNG)
  • HE-AACなどの技術は、低ビットレートな環境で高品質を狙ったもの。
  • 最高品質を狙うのであれば、AAC最高の320Kbpsに設定するのがベスト。(但し、ファイルサイズはでかくなる)
  • ファイルサイズは、ビットレート・サンプルレートに比例する。(例:ビットレートが48Kから96Kになれば、ファイルサイズも2倍になる)


さらに、さらに、さらに...

AACもまた奥が深い...。

変換(MAINプロファイルHE-AAC → LCプロファイルHE-AAC

  • メインプロファイルからLC(Low Complexity)プロファイルのAACにするには、再エンコードするしかなさそう。
  • 素人目には同じAACなのだから、劣化なしのプロファイル変換を期待してしまうのだが、それは無理なようだ。
ffmpeg -i 20100905220904.flv -ab 48k 20100905220904_ffmpeg_48k.m4a 
  • 変換された20100905220904_ffmpeg_48k.m4aを聴いてみると、何だか少しこもった感じの音。(高音域がなくなってしまったような印象)
  • しかも、ファイルサイズは増えて381KB→512KB。ファイルサイズからビットレートを予測すると64Kbpsでエンコードされている模様。
  • ffmpegが出力する情報を見ても64Kbps前後でエンコードされているようだ。
  • 調べてみると、MacPortでインストールしたffmpegHE-AACエンコードの機能はない様子。
  • 通常のAACビットレートは64〜320kbpsが有効範囲。
  • おそらく、48Kbpsを指定しても、ffmpegが有効範囲最低の64Kbpsに補正してしまうのだ。
  • そこで、一旦劣化なしのaiffに変換してみた。
ffmpeg -i 20100905220904.flv 20100905220904.aiff
  • 20100905220904.aiffファイルサイズは約30倍になり、馬鹿でかくなった...。
  • 20100905220904.aiffiTunesに読み込む。
  • iTunes >> 環境設定... >> 一般 >> 読み込み設定... で、
    • 読み込み方法:AAC エンコーダを指定して、
    • 設定:カスタム...を以下のように設定した。

  • この設定で、ライブラリ >> ミュージックの20100905220904を右クリック、AACバージョンを作成 を実行すると、
  • HE-AACバージョンの20100905220904が追加された!
  • 音質を確認すると、radikoのflvと区別できないレベル。問題なし。
  • ファイルサイズを確認すると、365KB。元ファイルとほぼ同じサイズ。
  • 不要なaiffバージョンを削除して、変換作業完了。

AppleScriptで変換

  • 毎回ターミナルでffmpegを実行して、iTunesに読み込ませて、右クリックしてAACバージョンを作成では、いかにも面倒。
  • お決まりのAppleScriptで、一連の作業を処理するようにしてみた。


property ffmpeg_path : "/opt/local/bin/ffmpeg"
property tmp_path : "/tmp/_flv_to_itunes/"

try
do shell script "mkdir " & tmp_path
end try

tell application "Finder"
set select_list to selection
end tell

repeat with f in select_list
set file_path to (f as text)'s POSIX path
set file_name to do shell script "n=" & file_path's quoted form & ";echo \"${n##*/}\""
set fn_no_ext to do shell script "n=" & file_name's quoted form & ";echo \"${n%.*}\""
set aiff_path to tmp_path & fn_no_ext & ".aiff"
set convert_path to POSIX file aiff_path
do shell script ffmpeg_path & " -y -i " & file_path's quoted form & " " & aiff_path's quoted form
tell application "iTunes" to convert convert_path
do shell script "rm " & aiff_path's quoted form
end repeat

  • ~/Library/Scripts/以下に保存して、スクリプトメニューから実行すると良さそう。
  • Finderでflvファイルを選択(複数選択OK)して実行すると、iTunesに登録される。
  • flvかどうかのチェックはしていないので、ffmpegaiffに変換できるファイルなら、何でもiTunesに登録してしまう。

afconvertでHE-AAC変換

  • 上記までのAACバージョンの作成は、iTunes >> 環境設定... >> 一般 >> 読み込み設定... に依存する。
  • もし設定がMP3 エンコーダになっていると、MP3バージョンが作成されてしまうのだ。
afconvert -f m4af -d aac -b 128000 20100905220904.aiff
  • 入力ファイル名だけ指定して、出力ファイル名を省略すると、入力ファイル名の拡張子だけ変更したファイルになる。
  • オプション指定できるデータフォーマットはafconvert -hfで確認できる。
$ afconvert -hf
Audio file and data formats:
    '3gpp' = 3GP Audio (.3gp)
               data_formats: 'aac ' 'samr' 
    '3gp2' = 3GPP-2 Audio (.3g2)
               data_formats: 'aac ' 'samr' 
    'adts' = AAC ADTS (.aac, .adts)
               data_formats: 'aac ' 'aach' 
    'ac-3' = AC3 (.ac3)
               data_formats: 'ac-3' 
    'AIFC' = AIFC (.aifc, .aiff, .aif)
               data_formats: I8 BEI16 BEI24 BEI32 BEF32 BEF64 UI8 'ulaw' 
                             'alaw' 'MAC3' 'MAC6' 'ima4' 'QDMC' 'QDM2' 
                             'Qclp' 'agsm' 
    'AIFF' = AIFF (.aiff, .aif)
               data_formats: I8 BEI16 BEI24 BEI32 
    'amrf' = AMR (.amr)
               data_formats: 'samr' 
    'caff' = Apple CAF (.caf)
               data_formats: '.mp1' '.mp2' '.mp3' 'QDM2' 'QDMC' 'Qclp' 
                             'Qclq' 'aac ' 'aach' 'aacl' 'alac' 'alaw' 
                             'dvi8' 'ilbc' 'ima4' I8 BEI16 BEI24 BEI32 
                             BEF32 BEF64 LEI16 LEI24 LEI32 LEF32 LEF64 
                             'ms\x00\x02' 'ms\x00\x11' 'ms\x001' 'samr' 
                             'ulaw' 
    'm4af' = Apple MPEG-4 Audio (.m4a)
               data_formats: 'aac ' 'aach' 'aacl' 'alac' 
    'MPG1' = MPEG Layer 1 (.mp1, .mpeg, .mpa)
               data_formats: '.mp1' 
    'MPG2' = MPEG Layer 2 (.mp2, .mpeg, .mpa)
               data_formats: '.mp2' 
    'MPG3' = MPEG Layer 3 (.mp3, .mpeg, .mpa)
               data_formats: '.mp3' 
    'mp4f' = MPEG-4 Audio (.mp4)
               data_formats: 'aac ' 'aach' 'aacl' 
    'NeXT' = NeXT/Sun (.snd, .au)
               data_formats: I8 BEI16 BEI24 BEI32 BEF32 BEF64 'ulaw' 
    'Sd2f' = Sound Designer II (.sd2)
               data_formats: I8 BEI16 BEI24 BEI32 
    'WAVE' = WAVE (.wav)
               data_formats: UI8 LEI16 LEI24 LEI32 LEF32 LEF64 'ulaw' 
                             'alaw' 
  • 目指すフォーマットは「 'm4af' = Apple MPEG-4 Audio (.m4a)」と思われる。(拡張子が.m4aなので)
  • そのデータフォーマットには'aac ' 'aach' 'aacl' 'alac' の4つが指定できるようになっている。
  • aaciTunes標準のAACだと思うが、その他のフォーマットが略語で自分にはチンプンカンプン。
  • 調べるのは面倒なので、それぞれ実際にエンコードしてみることに。
  • それぞれのデータフォーマットにビットレートの制限があるらしく、範囲外だとエラーが発生した。
  • 適当に変更しながら、実行してみた。
$ afconvert -f m4af -d aac -b 128000 20100905220904.aiff
$ afconvert -f m4af -d aach -b 128000 20100905220904.aiff
Error: Couldn't set audio converter property ('!dat')
$ afconvert -f m4af -d aach -b 48000 20100905220904.aiff
$ afconvert -f m4af -d aacl -b 48000 20100905220904.aiff
Error: Couldn't set audio converter property ('!dat')
$ afconvert -f m4af -d aacl -b 128000 20100905220904.aiff
$ afconvert -f m4af -d alac -b 128000 20100905220904.aiff
Error: Couldn't set audio converter property ('who?')
$ afconvert -f m4af -d alac -b 48000 20100905220904.aiff
Error: Couldn't set audio converter property ('who?')
$ afconvert -f m4af -d alac 20100905220904.aiff
  • 出来上がったファイルをFinderの情報を見るで確認してみると...
aac


aach


aacl


alac

なるほど!

  • 目指すデータフォーマットはaachだ!(HE-AAC
  • MPEG4 Low Delay AAC = エンコード時間を大幅に短縮して、双方向通信で違和感なく会話できる。(上記で「種類」見出しの さらに、さらに、さらにで調べたもの)
  • Apple Lossless = 劣化なしの可逆圧縮だけど、aiffの半分くらいになる。これもAAC派生の技術だったとは...。iTunesではApple Losslessエンコーダとして独立している。
  • つまり、以下のコマンドでradiko品質のHE-AACが生成されるのだ!iTunesの設定に依存することなく!
afconvert -f m4af -d aach -b 48000 20100905220904.aiff


property ffmpeg_path : "/opt/local/bin/ffmpeg"
property afconvert_path : "/usr/bin/afconvert"
property tmp_path : "/tmp/_flv_to_itunes/"

try
do shell script "mkdir " & tmp_path
end try

tell application "Finder"
set select_list to selection
end tell

repeat with f in select_list
set file_path to (f as text)'s POSIX path
set file_name to do shell script "n=" & file_path's quoted form & ";echo \"${n##*/}\""
set fn_no_ext to do shell script "n=" & file_name's quoted form & ";echo \"${n%.*}\""
set aiff_path to tmp_path & fn_no_ext & ".aiff"
set m4a_path to tmp_path & fn_no_ext & ".m4a"
set convert_path to POSIX file m4a_path
do shell script ffmpeg_path & " -y -i " & file_path's quoted form & " " & aiff_path's quoted form
do shell script afconvert_path & " -f m4af -d aach -b 48000 " & aiff_path's quoted form & " " & m4a_path's quoted form
tell application "iTunes" to add convert_path
do shell script "rm " & aiff_path's quoted form
do shell script "rm " & m4a_path's quoted form
end repeat

  • 実行してみると、自分のMacBook環境で1時間のラジオ番組をiTunesに追加するのに2分くらい、ffmpegとafconvertが頑張っている。
  • 既に同じファイル名がミュージックライブラリに存在する場合は、追加されない。(エンコード作業だけは実行されるが)


以上で、radikoのflvとほぼ同じ品質のHE-AACiTunesに保存できるようになった!

*1:HE-AAC = High-Efficiency Advanced Audio Coding

*2:入れ物、エンコードデータを収める規格

*3:スウェーデンのCoding Technologiesが開発

*4:HE(High Efficiency)-AAC

*5:Coding Technologiesの商標なので、HE-AACが一般的