どうもこんばんわ。
D.S. i.F. -Dal Segno- in Future 攻略しました。なんと本作は名前を呼んでくれます。
イベントCGがどれも可愛いのがいい!浴衣姿!!だ!
前作とは打って変わった挑戦のお話、新鮮だった
かわいい!!けど鳴ちゃんは攻略できない、かなしい
二人並んでるのがかわいい!!この中なら一番のシナリオかも?
この子のルートでクイズがあるんだけど全く分からんかった、、、むずかしい
いろんな服装が見れるので見ておくべきです
あたふたしてるのかわいー
ひまりちゃんが可愛かったです!!
おすすめ、イベントCGよかった
この服すき
天ルート短くて悲しすぎる、、なにかあるのかと思ったら何もなかった;;
えっちしーんもよかった、前作は寸止めばっかだったし、、
えちえちシーン良かったから R-18 ゲームまた作ってくれないかな、、、、どうか~
本題
Pixel 8 Pro
を買ってました、Xperia 1 V
も今年買ったのでお金ありません。
5 万の(Googleストアの)キャッシュバックがあった(発売直後くらいにやってた)とはいえ、値段がもろハイエンドなので同じ価格帯の端末と比べてボロボロに言われているイメージ。
Pro
の方は忘れがちですが、温度計が付いてますね。
API
で呼び出したいところではありますが、残念ながらサードパーティが使えない権限で保護されています。おもんね~~~
https://twitter.com/MishaalRahman/status/1715514224183484626
Pixel 8 シリーズには AV1 ハードウェアエンコーダーが搭載されている
リークで噂されてましたが、本当にPixel 8 シリーズ
にはハードウェアアクセラレーションされたAV1
エンコーダを載せているそうです。
AV1
のハードウェアエンコード、まだ値段が高いGPU
でしか出来ないとかでスマホとかには当分来ないと思ってたんですけどどういう事?
搭載しているエンコーダー一覧を出してみた結果(Pixel 8 Pro
)
重要そうな部分を抜き出しました。
マジだ!!AV1 エンコーダー
(c2.google.av1.encoder
)がソフトウェアではなくハードウェアで実装されていることが分かりますね。
あとすごくどうでもいいですがGoogle Tensor
の元がSamsung Exynos
であることもコレでバレちゃいますね。あは
ちなみにAV1
のハードウェアデコードはPixel 6
から搭載されてます(AV1 デコードも初だったかな)。Snapdragon
も8 Gen 2
からハードウェアでデコード出来るらしい。
今年出たiPhone 15 Pro
にもAV1
ハードウェアデコードが入っているらしい。
Apple
陣営はHEVC
じゃなかったんかい!
https://www.theverge.com/2018/1/4/16850402
AV1
の動画が流行ればより動画を圧縮してお届け出来るので、携帯の通信料が減らせるかもしれませんね。
ところで知ってる限り、スマホにハードウェアエンコーダ載せたのPixel 8 シリーズ
が初だと思うんだけど、なんかあんまり宣伝とかされてないな。。。
カメラアプリにはHEVC
でエンコードして保存するオプションがあるくらいだから、AV1
でエンコードする設定もあっても良いとは思う・・?
やっぱりハードウェアデコードがまだ浸透してないとかで辞めたんですかね?いい宣伝になるとは思うんだけど。
Android 14 からソフトウェアの AV1 エンコーダーが搭載されてそう
手元のPixel 6 Pro
でもエンコードが出来た。
Android 14
にするとAV1 ソフトウェアエンコーダー
がAOSP
に入っているんですかね?
これもすごくどうでもいいですが、NTT ドコモ
がAndroid API
を叩いた結果を公開してくれているので、ドコモ端末なら買わずに分かったりなんとか。
(叩いた結果を公開とか相当なもの好きだろこれ)
https://spec.nttdocomo.co.jp/spmss/spec/SO-51D__13_.html
HEVC
対抗馬としてHEVC(H.265)
っていう敵がいて、しかもこっちは既にハードウェアエンコード・デコードが入ってたりする。
なんならAV1
といい勝負をするらしい。
これでええやんって話ですが良くない。というのもなんか特許がよく分からん状態になってて、例えばブラウザで再生できないらしい?。
下手に手を出せない感じなんでしょうか
https://developer.mozilla.org/ja/docs/Web/Media/Formats/Video_codecs#hevc_h.265
AV1
はその辺きれいになっているらしく、ほとんどのブラウザで再生可能です。スマホもハードウェアデコーダーが載り始めたので時間が解決し始めてる。
後発組だから今ひとつだけど、HEVC 派閥の Apple が iPhone
にハードウェアデコーダーを載せたあたり未来は明るいかもしれない。
https://developer.mozilla.org/ja/docs/Web/Media/Formats/Video_codecs#av1
AV1 な動画を Android で作るには
映像コーデックをAV1
に設定するだけですね。
高レベルAPI
のMediaRecorder
と、低レベルAPI
のMediaCodec
にそれぞれ、AV1
用の値があるのでそれを設定すれば良いはず。
また、コンテナフォーマットはmp4
のみです。Android
だとWebM
には書き込めないみたいです。
(WebM
的にはAV1
を正式にサポートしてないみたい、ただ再生できるプレイヤーが結構あるので実質対応みたいな感じになってるらしい?)
もちろん自前でWebM
に書き込む処理を書けばAV1
も入れられると思う。
コンテナに書き込む処理を自前で作るのはとても大変ですが、、、
https://takusan.negitoro.dev/posts/tag/WebM/
setVideoEncoder
にMediaRecorder.VideoEncoder.AV1
を入れれば良いはず。
https://developer.android.com/reference/android/media/MediaRecorder.VideoEncoder#AV1
MediaFormat.createVideoFormat
にMediaFormat.MIMETYPE_VIDEO_AV1
を入れて、MediaCodec
をセットアップすれば良いはず。
https://developer.android.com/reference/android/media/MediaFormat#MIMETYPE_VIDEO_AV1
今回はMediaRecorder
/MediaCodec
どっちも試してみます。
動画を選んで AV1 で再エンコードするアプリを作ってみる
カメラアプリは作るのめっちゃクソ大変なので、すでにある動画を変換するアプリを作ろうと思います。
結局カメラアプリを作ります。
流れ
映像はコレで良いはず。音声に関しては入力する動画のコーデックがAAC
の場合は多分入れ直すだけでいいはず。
ただ、元データがWebM(VP9 + Opus)
の場合はAAC
に変換しないとダメですね。
多分OpenGL
をデコーダーとエンコーダーの間にかませる必要があります。
デコーダーの出力先Surface
にエンコーダーの入力Surface
をそのまま渡したんですが、なんかうまく動きませんでした。
(正確に言うと同じコーデックの場合は問題がない?AVC
→VP9
を試したらダメだった。なんかdequeueOutputBuffer
がずっと-1
とか返してて使えなかった)
ちなみに同じコーデックでもOpenGL
を一度経由させるメリットがあります。
複数の動画をつなげるとかの場合に、動画の幅高さが変化するような場合はOpenGL
を利用しないと映像がぶっ壊れます。
あとOpenGL
を使えば解像度の変更?が出来るので多分経由するメリットはあります。
もちろんGLSL ? ふらぐめんとしぇーだー ?
分かるならエンコーダーに渡す前にフレームにエフェクトを掛けることが出来ます。(モノクロとか左右反転とか)
が、AOSP
からコピーしてくることにするので何やってるかはよくわからない。。。
今回作ってみる動画は コンテナフォーマットこそ mp4 (拡張子 .mp4) ですが、プレイヤー側でAV1
がデコードできないと再生できません。(AAC
デコーダーは入ってるやろ)
紛らわしいかな?やっぱwebm
にも入れられるようにして欲しい。
箇条書きにすると
MediaExtractor
に動画データを入れる
- エンコーダー、デコーダーの
MediaCodec
とOpenGL
を用意
- デコーダーに
MediaExtractor
で取り出したデータを渡してデコードする
- テクスチャが来るので OpenGL で描画する
- エンコーダーからエンコードされたデータが出力されるのを待つ
MediaMuxer
に入れる
- データが終わるまで続ける
- 音声トラックを戻す
- 先述の通りコーデックが
AAC
以外の場合はこれも変換する必要があります
- AAC じゃなくても
mp4
に入れば良い気がしてきた
MediaStore
を使って端末の動画フォルダに入れる
Android
のファイルの仕様がなんか使いにくいので、作業中はJava
のFile API
を使っていきます
- が、
Java
のFile API
では端末の動画フォルダとかにはアクセスできないので、MediaStore
にお願いします。
ただ再エンコードして入れ直すので、MediaCodec
の記事をいくつか書いてきましたが、その中でおそらく一番楽かもしれない?
登場人物
コーデック
VP9
AV1
H.264 (AVC)
H.265 (HEVC)
とかの圧縮方式のやつ。お弁当箱に入れる食べ物です
音声なら AAC
とか Opus
。
パラパラ漫画をGIFで作るのと、パラパラ漫画を動画で作るので、サイズを比較すると動画のほうが圧倒的に小さいのはコーデックが圧縮してくれてるからなんですね。
(全てのフレームを持つとサイズが大きくなるので、前のフレームとの差分だけ持つなどの工夫をしている。らしい、キーフレームとかなんとか)
mp4
とかwebm
とかはコンテナフォーマットなので、コーデックではありません。
https://aviutl.info/ko-dekku-konntena/
コンテナフォーマット
mp4
とかwebm
とか。エンコードされたデータの入れ物です。お弁当箱です
AV1
でエンコードされたデータはそのままでは再生できないので、コンテナフォーマットに入れて保存します。
(メタデータが入っていないので再生するためのデコーダーが起動出来ない)
MP4 はコンテナなので
お弁当箱なので、実際に再生できるかどうかは中に入ってるコーデック次第なんですよね。
うーん、この辺の話をしてると、ffmpeg
ってほんと良しなにやってくれてたんだなあって。
.mp4
形式でちょうだいって言われて、中身AVC
じゃなくてHEVC
のコーデック入れたら大混乱になりそう。だってそのままだとHEVC
再生出来ないんだもん
コンテナフォーマット(mp4
、webm
)からメタデータや実際のエンコードされたデータを取り出すやつ
エンコーダー・デコーダーです。
エラーが分かりにくいというか分からない。
エンコーダーから出てきたデータを入れるやつです。
映像と音声をそれぞれmp4 / webm
に書き込んでくれるやつです。
OpenGL
よく分からん。今回も今回とてAOSP
のMediaCodec
のテストで使われているOpenGL
周りのコードをコピーしてくることにします。(Apache-2.0 license
)
作る
上で言った?とおりOpenGL
はコピペするのでKotlin
できれば良いはず
なまえ | あたい |
---|
Android Studio | Android Studio Hedgehog 2023.1.1 |
言語 | Kotlin 1.9.20 / OpenGL ES 2.0 |
端末 | Pixel 8 Pro / Pixel 6 Pro |
最低Android
バージョンは14 (SDK 34)
です。多分AV1
エンコーダーがソフトウェアでも乗ってるのが14
以降なはず?
手元の14
系の端末がPixel
しかない...
アプリの名前は特に思いつかなかったのでエロゲヒロインから取りました
OpenGL 周りを AOSP から借りてくる
返しませんが。借りパクです。
OpenGL
周りはこの2つで、これらをKotlin
化したものを使います。
Apache-2.0 license
MainActivity
Jetpack Compose
を使います。
HomeScreen
コンポーネントを作って表示させます。
動画を選ぶ処理
rememberLauncherForActivityResult
でフォトピッカーを開いて、動画を選んでもらいます。
ユーザーが選ぶタイプなので、権限は必要ないです。
選択した動画を解析してくれるMediaExtractor
を作ります。
実際のエンコードされたデータを取り出す + 動画のメタデータの解析をしてくれます。
適当なユーティリティークラスを作ってそこに書きました。
映像の再エンコード部分
もう一気に貼ります。
これがMediaExtractor
からデータを貰って、MediaCodec
でデコードしてOpenGL
でレンダリングしてそれをエンコーダーに渡す処理です。
解説というか説明はコメントに書いたのでそっちを見たら良いと思う!よ
音声トラックを追加する処理
AV1
でエンコードされたデータにはまだ音声トラックがない(映像だけしか入ってない)
ので、音声トラックを追加して音声データを入れる処理です。
音声データは元の動画からそのまま持ってこようと思います、が先述の通り、
AAC
以外(mp4
に入らないコーデックの場合)の場合は音声データの方も再エンコードが必要です。
大抵のファイルはmp4 (AVC / AAC)
なのでまあ...そのまま入れ直すだけで動くんじゃない?
端末の動画フォルダに保存する処理
完成した動画ファイルはgetExternalFilesDir
の中にあるので、端末の動画フォルダに移動させます
getExternalFilesDir
のパスはsdcard/Android/data/data/{パッケージ名}
になります。
AndroidStudio
のDevice Explorer
で見れば良いんじゃない
このファイルはサードパーティのファイラーでは見れず、Android 標準のファイラー(パッケージ名 : com.android.documentsui)
を使わないと見れなくなりました。
(アプリ一覧画面に無いので、自分でIntent
を投げる必要があります)
かなり不便だからなんとかして欲しい
組み合わせる
最後にこれらを組み合わせて、再エンコードをする処理を書きます。
後はこれをJetpack Compose
で作ったUI
側で呼び出せば良いはず
せっかくなので、ビットレートを入力できるようにしてみました。
使ってみる
動画を選んで、処理を開始を押せば始まります。
できました!
試した感じ私の設計が変なのか知らないのですが、動画によっては短くてもすごく時間がかかるときがありますね。なんか私やらかしたか?
うーん、かかった時間が安定しないな
再エンコード ソースコード
ここまでのコードです!
https://github.com/takusan23/HimariDroid/tree/d168e8572c1d3e485745f5420b5d4e25d7afb0a8
AV1 再エンコーダー apk
はい
UI が最低限なので使うべきではないです、
https://github.com/takusan23/HimariDroid/releases/tag/1.0.0
結果
うーん、
色々いじってみたけど、Android の MediaCodec
にはビットレートの最低値が存在するらしく?
そのせいである値を超えるとそれ以上下げてもファイルサイズが変わらないっぽいんですよね、、、
、、でそのビットレート最低値がどこにあるかわかんないんですけど・・・
比較対象はmp4
コンテナに入る、AVC
/HEVC
/AV1 ソフトウェア
/AV1 ハードウェア
です。
AV1 ソフトウェア
はPixel 6 Pro
でやりました(Pixel 8
だとハードウェアが優先されちゃうので指定めんどい、一応ソフトウェアも選べる)
あと、この結果は元データあんまり画質良くないのと、素人の私が適当にまとめただけなので過信してはいけない。
元データ
https://youtu.be/AC5oNvR23UU?si=Iu1buVsN7QvrOz5M&t=633
もとから画質というかビットレートが高くないので、結構厳しいのですが...
何かいい感じの動画があれば良いんだけど
1Mbps
AVC
はこれが最低ライン感ある。
AV1 ソフトウェア
よりAV1 ハードウェア
もしくはHEVC
かなあ。
AV1 ハードウェア
とHEVC
比較するとわずかにHEVC
かも。
コーデック | 切り抜き |
---|
元データ | |
AV1 ソフトウェア | |
AV1 ハードウェア | |
HEVC | |
AVC | |
700Kbps
AV1 ソフトウェア
の画質があんまりでなかった
ここはAV1 ハードウェア
よりHEVC
かなあ...つよい
コーデック | 切り抜き |
---|
元データ | |
AV1 ソフトウェア | |
AV1 ハードウェア | |
HEVC | |
AVC | |
500Kbps
コレより下は多分エンコーダーのビットレート最低値に引っかかって下がらない(と思う)。
AVC
はやっぱりというか、なんか転載されまくってカビカビになった動画みたいな雰囲気になってる(分からない例え)
HEVC
とAV1
はかなりいい勝負な気がする。
AV1
はソフトウェアよりハードウェアの方が境界線がきれいというか、シャープな気がする。
コーデック | 切り抜き |
---|
元データ | |
AV1 ソフトウェア | |
AV1 ハードウェア | |
HEVC | |
AVC | |
感想
ハードウェアエンコーダーのが綺麗な気がするけど、これGoogle Tensor
に入ってるやつなので、
今度Snapdragon
とかにもAV1
エンコーダーが搭載され始めたらまた変わってくるかもしれない。
AV1 で動画撮影は?
なんか面白くないので、今度はCamera 2 API
を使って、カメラの入力をAV1
エンコーダーに渡してエンコードさせようと思います。
リアルタイムエンコード?ってやつなんでしょうか
Camera2 API
は前触ったことあるからまあなんとかなるやろ!
https://takusan.negitoro.dev/posts/android_front_back_camera/
また、今回は面倒なのでMediaCodec
ではなく、MediaRecorder
で録画しようと思います。
ただでさえCamera2 API
コールバックばっかりでしんどいので
ちなみにCameraX
は今のところコーデック選べないらしい。
じゃあCamera2 API + MediaRecorder
するしか無いなあ。
https://developer.android.com/training/camerax/video-capture#bind-videocapture
CameraController
クラスを作りました。
ここにUI (Jetpack Compose)
側から呼び出す関数を作って(setupCamera
、startRecord
)、それぞれ実装しました。
カメラ画面
↑で作ったCameraController
を使う画面です。
カメラのプレビューを表示するSurfaceView
は、正方形じゃない表示が歪んでしまうのですが(正方形のソースはどこだか忘れてしまった...)
https://qiita.com/nakker1218/items/b9a592c93bde33de52aa
Jetpack Compose
のModifier
をいくつか組み合わせるだけで解消されます。
おそらくこういう感じの、SurfaceView(カメラのプレビュー)
を縦横同じ正方形にして、端末の画面サイズよりも大きくするようなことを、をやってくれているんだと思います。
動画撮影しつつ、AV1 でエンコードさせてみた
MediaRecorder
でAV1
を選ぶ!
ビットレートは、ニコニコ動画の推奨エンコーダー設定がH.264 で 6Mbps
みたいなので、とりあえず何も考えずに半分にしてみた。
https://qa.nicovideo.jp/faq/show/21908?site_domain=default
Camera 2 API で 60fps の録画をする
https://stackoverflow.com/questions/43628278/
このままでは60fps
でカメラの映像が流れてきません、MediaRecorder
でFPSを60
を指定しても30
のままになります。
修正ですが、Camera2 API
のcreateCaptureRequest
でset(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(30, 60))
を設定してあげる必要があります。
これで録画時は60fps
の映像がカメラから流れてきます。
プレビューはまあ30fps
で良いんじゃない?負荷かかりそうやし
Pixel 8 Pro(AV1 ハードウェアエンコーダーあり)
すごい!!!
これは高い端末買っただけあるわ。Google さん!カメラアプリにAV1エンコード
設定作ろうよ
- 1280x720 / 30fps
- 余裕そう。見てる分には映像がカクカクになる(フレームが落ちる?)ことは無さそう
- 1920x1080 / 30fps
- 1280x720 / 60fps
- 1920x1080 / 60fps
- 3840x2160
- ここから先はエラーになってしまう
- ハードウェアエンコードは 1080p まで?
- AVC / HEVC は起動可能
Pixel 6 Pro(AV1 ソフトウェアエンコーダーのみ)
ちなみに、Pixel 8 Pro
で明示的にソフトウェアエンコーダー(c2.android.av1.encoder
)を指定しましたが、やっぱりカクカクになりました。
ハードウェアすげ~~~
- 1280x720 / 30fps
- 640x480 / 30fps
- ちょっとカクついたけどどうしても使いたければここまで?
- 1280x720 / 60fps
- 640x480 / 60fps
Camera2 API で動画撮影するソースコード
どうぞ、AV1
用にパラメーターを直せば動きます。
ちなみに、MediaRecorder
に渡す解像度(動画の縦横サイズ)は、多分16
で割り切れる(あまりが出ない)値にする必要があり、なんか変な値を入れたら録画が開始されません。
あ、バージョン分岐とかはしてないので、古いAndroid
だと動かないかも。
検証のために作ったようなもんなのでNewApi
の警告は全部黙らせました、良くない。
https://github.com/takusan23/Camera2ApiVideoSample/tree/master
MediaRecorder
ではなくMediaCodec
を使う版。
エンコーダーガチ勢はどうぞ。
https://github.com/takusan23/Camera2ApiVideoSample/tree/master/app/src/main/java/io/github/takusan23/camera2apivideosample/recorder
APK 用意しました
バックグラウンドに移動すると真っ暗になる不具合がありますが直していません。。。
おそらくSurfaceView
が破棄されるので、onResume
でプレビューを開き直すと良いかもしれません。
https://github.com/takusan23/Camera2ApiVideoSample/releases/tag/1.0
終わりに
Pixel 8 Pro
すごい!!!買う価値ありかも
動画を貼ろうと思ったんだけど被写体良いの無いので、近いうちに撮って貼ります。