AndroidではVideoのファイルを圧縮したりするのは大変な苦しみを伴う(と思ってる)
FFmpegのライセンスの関係もあり、有効なライブラリはとても少ない。
ライブラリとしても
LightCompressor
https://github.com/AbedElazizShe/LightCompressor
が目立つぐらいで他はメンテナンスされてなかったりするのでとても不安だ。
上記のLightCompressを使用してみたが、
特定の端末の動画ではどうにも挙動がおかしく圧縮サイズがうまくいかず、想像以上にガビガビになったため中々手放しでは喜べない状況になってしまった。
なお、Coroutineなど使って実装しなおそうと試みたがMediaCodecAPIが激烈に使い辛くすぐやめた。
とにかく簡単に動画の容量を落としたいと思い、別の方法を模索した
Jetpack Media3ライブラリ
動画、音声などを扱うライブラリ(ExoPlayerなど)を統合し、Android Jetpackとして用意された新たなライブラリ群。
これを使い動画の容量を落としてみる。
対象の動画ファイル
1920*1080の1080pのMP4
総ビットレート12944kbps
61.4MB
最近の端末のカメラから直接撮ると大体こんな感じになると思います。
奇麗ですが、送信したりするにはちょっと大きい&奇麗すぎ。
実装
media3ライブラリ
def media3_version = "1.0.2"
implementation "androidx.media3:media3-transformer:$media3_version"
implementation "androidx.media3:media3-common:$media3_version"
stable版の1.0.2を利用しました。
プレイヤーに表示したりはしないので、コアなモジュールだけです。
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
fun videoFileResizeByMedia3(context: Context, videoUri: Uri) {
val transformationRequest = TransformationRequest.Builder()
.setVideoMimeType(MimeTypes.VIDEO_H264)
.setAudioMimeType(MimeTypes.AUDIO_AAC)
.setResolution(1280) //720p
.build()
val inputMediaItem = MediaItem.fromUri(videoUri)
val outputPath = context.applicationInfo.dataDir + File.separator + "sample.mp4"
val transformer = Transformer.Builder(context)
.setTransformationRequest(transformationRequest)
.addListener(object : Transformer.Listener {
override fun onTransformationCompleted(inputMediaItem: MediaItem, transformationResult: TransformationResult) {
super.onTransformationCompleted(inputMediaItem, transformationResult)
}
override fun onTransformationError(inputMediaItem: MediaItem, exception: TransformationException) {
super.onTransformationError(inputMediaItem, exception)
}
}).build()
transformer.startTransformation(inputMediaItem, outputPath)
}
内容
Transformer.startTransformationを使って動画をリサイズします。
RequestにはVideoのコーデックタイプ(主にMP4)
setAudioMimeTypeのコーデックタイプ(主にAAC)
setResolutionにビデオのサイズをセットします。 もう一辺は代表的なサイズで推論してる?のだと思います。
今回は1080pを720pにしたかったので1280をセット
あとは保存すべきUriを作りstartTransformation
処理が成功した場合、onTransformationCompleted
失敗したら、onTransformationErrorが返ってきます。
結果
1280*720の720pのMP4
総ビットレート4082kbps
19.96MB
結構小さくなりました。
問題点
-
Android13(SDK33)を要求される。
それですら実験的な機能なため、100%動作が保障されていない発展途上の状態な点 -
APIの仕様がコロコロ変わる
まだまだ実験的なのでよくAPIの仕様が変わります。
onTransformationCompleted、onTransformationErrorは既に非推奨になってる。
バージョンアップ毎に確認が必要になりそう。 -
結局細かい指定ができないまま
ビットレートを落として容量をさらに調整したり、なんてことはできない。
どちらかというとこちらだけやりたいケースもありそうなのでこれは惜しい...。
感想など
解像度を投げるだけで指定のサイズにリサイズによってファイル容量を多少落とした。
しかし、ビットレート、フレームレートを落とす術がないのがまだまだイマイチな点だと感じる。
そもそもこれが圧縮的な用途にも使えるのか知らない
まぁ結局のところMediaCodecAPIが複雑で使い勝手が悪すぎるのが諸悪の根源だと感じる...。
Media3については今後に期待です。