Android/iOS同時対応動画をエンコードする心得

  • 101
    いいね
  • 2
    コメント

AndroidとiOS両方に対応するならmp4を使う

動画を撮るとき、Androidは.mp4、iOSは.mov (QuickTime)形式で保存されます。
mp4はmovは、様々な形式(コーデック)の動画情報や音声情報を含むことができる「コンテナフォーマット」で、中身の動画や音声の情報の保存方法は別途決められています。AndroidやiOSで動画を撮影した場合、動画コーデックは H.264(別名MPEG-4 AVC) 、音声コーデックはAACで保存されています。

.movはそのままの形式ではAndroidでは再生できませんが、コンテナなので、動画や音声の情報をデコード・エンコードせずにデータをコピーするだけで.mp4に変換できます。iPhoneは.mp4も再生できるので、 .mp4に変換するとAndroid/iOSの両方に対応 できます。
(.mp4は.movをベースに作られています)

H.264のProfileとLevel

H.264(MPEG-4 AVC)では、エンコードおよび再生時に機器に求められる性能(すなわちCPUやメモリ量)、圧縮率、画質といったパラメータが ProfileLevel によって決められていて、用途に応じて変更することができます。機器やデコーダによってサポートされているProfile, Levelが異なるため、再生するデバイスに応じて適切なものを選択すべきです。

  • Profile: H.264でサポートされる動画の圧縮方法のうち、どれを使用できるかを定義します。 Profileがより高いものになると圧縮率や画質が改善しますが、エンコーダとデコーダの実装や処理が複雑になります。 主なものは、簡単な順から Baseline Profile, Main Profile, High Profileです。
  • Level: 解像度やビットレートなど、パラメータの最大値を定義します。 Levelがより高いものになると、画質が向上しますが、データ量と求められる機器性能はより高くなります。 同じLevelでもProfileによってビットレートなどが異なったりします。

スマートフォンやPCにおいても、ハードウェア上のエンコーダ、デコーダを使用するようで、
ソフトウェアが該当するProfile, Levelをサポートしていたとしてもハードウェアで対応されていない場合は、うまく再生できなかったりします。

Androidが対応するProfile/Level

Androidでは公式には(エンコーダ、デコーダのどちらなのか言及なしに)「Baseline Profileがサポートされている」としていますが、Levelについては特に言及がありません。

http://developer.android.com/guide/appendix/media-formats.html

少なくともNexus 5 (Android 4.4)ではMain Profile @ Level 4.0の(解像度を下げた)動画を再生することが出来ました。
また、Nexus 5で動画を撮影すると、Baseline Profile @ Level 4.0になりました。

Xperia acroについて調査した記事が見つかり、Baseline, Main, High @ 3.1は再生できるようでした。

http://d.hatena.ne.jp/shiku_otomiya/20110729/p1

前述のとおり、実際に対応可能なProfile/Levelは端末の性能に依存しているのでしょう。しかし少なくとも、Baseline Profileはサポートされるようです。

iOSが対応するProfile/Level

iOSはiPhone、iPod Touch、iPad上でしか動作しないので、それぞれの端末のスペックを見ることで、対応するフォーマットを確認することができます。

https://www.apple.com/jp/iphone-5s/specs/

また間接的な資料ですが、"HTTP Live Streaming"のドキュメントに、
iPhone 3G、3GS からBaseline Profile @ Level 3.1 のみ をサポートしていたとの記載があります。
それより古い端末の互換性を考えるならBaseline @ 3.0にすべき、また、iPhone 4以上のみ考えるならMain @ 3.1にしておいたほうがよいとの記述もあります。

https://developer.apple.com/library/ios/documentation/networkinginternet/conceptual/streamingmediaguide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html

ちなみにiPhone 4S (iOS 7.1)ではBaseline @ 4.1になりました。

オレが考えたAndroid/iOS両対応の最強Profile/Level

Androidは公式にはBaselineしかサポートしていないことを考えると、画質を優先する場合の選択肢は下記のとおりになると思います。

  • iPhone 3GSみたいな古い端末をサポートする: Baseline Profile @ Level 3.0
    • ffmpegに-profile:v baseline -level:v 3.0を指定
  • iPhone 4以降に絞ってしてしまう: Baseline Profile @ Level 3.1
    • ffmpegに-profile:v baseline -level:v 3.1を指定

paperclipの場合はgeometryと一緒に下記のような形で指定してください。

convert_options: { output: { :'profile:v' => 'baseline', :'level:v' => '3.1' } }

paperclipでffmpegに直接オプションを渡す方法

streamingする場合など、データ量を減らしたい場合は、より低いLevelを指定することも可能です。

※streamingする場合はstreaming: trueもお忘れなく・・! → コメント参照
※音声コーデックについてはガン無視しました、すみません・・。

追記:AndroidのドキュメントにMain Profileの記述が増えた

https://developer.android.com/guide/topics/media/media-formats.html
いつのまにかBaseline ProfileとMain Profileが別々に書かれていて、Main Profileのdecoderは必須とされています。
しかしながら、CDD (Compatibility Definition Document)に追加されたのがAndroid M (6.0)からだからアテにしないほうが良いとの記載もあります。
https://github.com/google/ExoPlayer/issues/1378#issuecomment-197447909