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やメモリ量)、圧縮率、画質といったパラメータが Profile と Level によって決められていて、用途に応じて変更することができます。機器やデコーダによってサポートされている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については特に言及がありません。
少なくともNexus 5 (Android 4.4)ではMain Profile @ Level 4.0の(解像度を下げた)動画を再生することが出来ました。
また、Nexus 5で動画を撮影すると、Baseline Profile @ Level 4.0になりました。
Xperia acroについて調査した記事が見つかり、Baseline, Main, High @ 3.1は再生できるようでした。
前述のとおり、実際に対応可能なProfile/Levelは端末の性能に依存しているのでしょう。しかし少なくとも、Baseline Profileはサポートされるようです。
iOSが対応するProfile/Level
iOSはiPhone、iPod Touch、iPad上でしか動作しないので、それぞれの端末のスペックを見ることで、対応するフォーマットを確認することができます。
また間接的な資料ですが、"HTTP Live Streaming"のドキュメントに、
iPhone 3G、3GS は からBaseline Profile @ Level 3.1 のみ をサポートしていたとの記載があります。
それより古い端末の互換性を考えるならBaseline @ 3.0にすべき、また、iPhone 4以上のみ考えるならMain @ 3.1にしておいたほうがよいとの記述もあります。
ちなみに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
を指定
- ffmpegに
- iPhone 4以降に絞ってしてしまう: Baseline Profile @ Level 3.1
- ffmpegに
-profile:v baseline -level:v 3.1
を指定
- ffmpegに
paperclipの場合はgeometryと一緒に下記のような形で指定してください。
convert_options: { output: { :'profile:v' => 'baseline', :'level:v' => '3.1' } }
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