FFmpeg で Dolby Digital Plus with Dolby Atmos を -c:a copy すると Dolby Atmos として認識されなくなる問題の解決策

Last modified date

問題に遭遇した経緯

Dolby Digital Plus with Dolby Atmos 音声を Dolby Atmos 対応の AQUOS や arrows で再生すると、再生中に以下のような通知が出る。

Dolby ATOMS と誤字っているが、Dolby Atmos として認識されている事はわかる。

同じものを Dolby Atmos 対応の iPhone で再生すると、ログは以下のようになる。

ACDDPAtmosDecoder.cpp:476:Initialize: (0x10f954040) Input format: 12 ch,  48000 Hz, 'ec+3' (0x00000000) 0 bits/channel, 0 bytes/packet, 1536 frames/packet, 0 bytes/frame
ACDDPAtmosDecoder.cpp:479:Initialize: (0x10f954040) Output format: 12 ch,  48000 Hz, Float32, non-inter

12ch は 7.1.4ch のことで、iPhone は Dolby Atmos を 7.1.4ch にデコードしている。ec+3 は Dolby Digital Plus with Dolby Atmos のことを指す (詳細)。

不思議なことに、この動画ファイルを FFmpeg で -c:a copy して MP4 コンテナに格納 (映像コーデックは不問) すると、AQUOS では以下のような通知になる。

Dolby Audio は「Dolby Atmos 関連でない Dolby の音響技術」という意味であることから、どうやら非 Dolby Atmos の Dolby Digital Plus としてデコードされてしまっているらしい。

参考

Dolby Audio の詳細や Dolby Digital Plus with Dolby Atmos の構造 (JOC や Spatial Coding) に関しては、以下の記事で解説している。

FFmpeg で -c:a copy したものを iPhone で再生するとログはこうなる。

ACDDPAtmosDecoder.cpp:476:Initialize: (0x10f95c040) Input format:  6 ch,  48000 Hz, 'ec-3' (0x00000000) 0 bits/channel, 0 bytes/packet, 1536 frames/packet, 0 bytes/frame
ACDDPAtmosDecoder.cpp:479:Initialize: (0x10f95c040) Output format:  6 ch,  48000 Hz, Float32, non-inter

この Dolby Digital Plus with Dolby Atmos 音声は 5.1ch の Dolby Digital Plus + JOC のため、6ch は 5.1ch のことを指していると思われる。ec-3 は Dolby Atmos でない Dolby Digital Plus のことを指している。つまり、iPhone でも Dolby Atmos としては認識されていないようだ。

-c:a copy だけでは Dolby Atmos 用のメタデータか何かが引き継がれないのかとも思ったが、MediaInfo では問題なく Dolby Digital Plus with Dolby Atmos として認識さている。

さらに、PC から AV アンプに音声をパススルーしても、きちんと Dolby Digital Plus with Dolby Atmos として認識されていることから、音声のデータ自体には問題がないようだ。

そこで、ffprobe でファイルの情報を比較してみると、以下の部分が違っていた。

Dolby Atmos として扱われる Dolby Digital Plus (1)

major_brand     : mp42
minor_version   : 1
compatible_brands: mp42dby1isom

Dolby Atmos として扱われる Dolby Digital Plus (2)

major_brand     : dby1
minor_version   : 0
compatible_brands: dby1isommp42

Dolby Atmos として扱われる Dolby Digital Plus (3)

major_brand     : mp42
minor_version   : 1
compatible_brands: mp42dby1

5.1ch として扱われてしまう Dolby Digital Plus

major_brand     : isom
minor_version   : 512
compatible_brands: isomiso2avc1mp41

音声ストリームの情報に違いはなく (実際 AV アンプでは Dolby Atmos として扱われたし)、どうやら MP4 コンテナ自体のメタデータ (Major Brand と Compatible Brands) に問題があるようだ。FFmpeg はデフォルトでは Major Brand が isom、Compatible Brands が isom、iso2、avc1、mp41 となるようだ。

どうやら dby1 が Dolby 関連の Brand で、これが必要らしい。

dby1

MP4 files with Dolby content (e.g. Dolby AC-4, Dolby Digital Plus, Dolby TrueHD (Dolby MLP))

Brands – Registered Types – The ‘MP4’ Registration Authority

そこで、FFmpeg で -c:a copy する際に -brand dby1 してみると、 Major Brand が dby1 に、Compatible Brands が dby1、iso2、avc1、mp41 になった。これを AQUOS / arrows や iPhone で再生してみたところ、Dolby Atmos としては扱われなかった。どうやら mp42 も必要らしい。

-brand mp42 では Major Brand が mp42 に、Compatible brands は mp42、iso2、avc1、mp41 となり、dby1 が入らない。これも Dolby Atmos として扱われなかったことから、mp42 と dby1 の両方が必要ということになる。-brand mp42,dby1-brand mp42dby1isom を試してみても、 -brand mp42 と同じ結果になり、dby1 は無視された。

FFmpeg では、Major Brand は任意の値に設定することはできても、Compatible Brands は FFmpeg が用意した Major Brand ごとのプリセットにしか設定できないようだ。

解決策

The Dolby MP4 streaming muxer (dlb_mp4base) を使ってみることにした。dlb_mp4base では、 --mpeg4-brand で Major Brand を、--mpeg4-comp-brand で Compatible Brands を変更することができる。せっかくなので、一括変換するバッチファイルを作成した。

@echo off

md dlb_mp4base
for %%f in (*.mp4) do (
ffmpeg.exe -i "%%f" -c:v copy -an "dlb_mp4base\%%f.264"
ffmpeg.exe -i "%%f" -c:a copy -vn "dlb_mp4base\%%f.eac3"
ren "dlb_mp4base\%%f.eac3" "*.ec3"
mp4muxer.exe -i "dlb_mp4base\%%f.264" -i "dlb_mp4base\%%f.ec3" -o "dlb_mp4base\%%f" --mpeg4-comp-brand mp42,dby1,isom
del "dlb_mp4base\%%f.264"
del "dlb_mp4base\%%f.ec3"
)

解説

md dlb_mp4base

まず作業用フォルダ兼出力先フォルダとして、dlb_mp4base フォルダを生成。

for %%f in (*.mp4) do (

)

カレントディレクトリの全ての .mp4 ファイルに対して () 内の処理を行う。ファイル名は %%f に代入される。

ffmpeg.exe -i "%%f" -c:v copy -an "dlb_mp4base\%%f.264"

dlb_mp4base は入力として .mp4 などは受け付けていないようなので、FFmpeg で映像と音声を分離 (demux)。まずは映像から。今回作業した映像のコーデックは全て MPEG-4 AVC (H.264) のため、拡張子は .264 で出力。

ffmpeg.exe -i "%%f" -c:a copy -vn "dlb_mp4base\%%f.eac3"

こちらは音声の出力。dlb_mp4base は Dolby Digital Plus (Enhanced AC-3) 音声の拡張子が .ec3 でないと認識しないようだが、FFmpeg は .ec3 では出せないようなので、一旦 .eac3 で出力。

ren "dlb_mp4base\%%f.eac3" "*.ec3"

Dolby Digital Plus 音声の拡張子を .eac3 から .ec3 へ変更。

mp4muxer.exe -i "dlb_mp4base\%%f.264" -i "dlb_mp4base\%%f.ec3" -o "dlb_mp4base\%%f" --mpeg4-comp-brand mp42,dby1,isom

分離した映像と音声を dlb_mp4base に入力し、Compatible Brands を mp42、dby1、isom とした上で、MP4 コンテナに格納 (mux)。--mpeg4-brand を指定しない場合は (Compatible Brands に mp42 を入れなくとも) Major Brand は mp42 になる。

del "dlb_mp4base\%%f.264"
del "dlb_mp4base\%%f.ec3"

一時ファイルを削除。

これを行うことで、AQUOS / arrows や iPhone にて MP4 コンテナ内の Dolby Digital Plus を Dolby Atmos として扱うことができるようになった。

井戸水

ガジェットやオーディオビジュアルが好きな人。

コメントを残す…