たくさんの自由帳
Androidのお話
たくさんの自由帳
投稿日 : | 0 日前
文字数(だいたい) : 3690
どうもこんばんわ、(お久しぶりです)
D.C.4 Sweet Harmony ~ダ・カーポ4~ スイートハーモニー 攻略しました。
めっちゃいいですね、ヒロインみんなかわいい!
ここの話ほんとかわいい
ここほんとすき
あぁぁぁ
本編では焦点があまり当てられなかったヒロインたちのストーリーが本作でちゃんとしてていい!
実用性もあるとおもう
ぜろみらーを作りました。ミラーリングアプリです。
とりあえずリリースしましたが、多分動く端末のほうが少ないと思う←!?
ニコ生のコミュの名前にありそうですが関係ないです。
VP9でエンコードする機能もあります。H.264と比べて同じビットレートだと多分きれいな気がする...ブラウザがあれば使える → ほぼ設定がない → Zero ( Config ) Mirroring → ぜろみらー
結構無理やりなので負荷がやばいかも
あと動画を細切れにしている以上、切り替えで一瞬ロードされちゃいます...
端末の画面録画と(あれば)端末内音声を集めて、動画を細切れにして、ブラウザへWebSocketで送信してます。
もっといい方法があったかもしれない...
Androidの画面録画、端末内音声の内容をMediaProjectionで受け取ります。
(画面録画はSurface、端末内音声はPCM)
受け取ったらMediaCodecでH.264か(設定したら)VP9にエンコードします。
エンコードしたらMediaMuxerを使いmp4かwebmの動画ファイルにします、一定期間経ったらファイルを切り替えてまた保存します。
できた動画ファイルをWebSocketを使ってブラウザへ通知して(動画ファイルのパス)、ブラウザの<video> タグで再生します。
動画ファイルを細切れで作って、ブラウザで再生しているだけです。はい
リアルタイム配信といえばこれ?
HLSはMediaMuxerがMPEG2-TSのコンテナフォーマットに対応していないので無理です!(これは後述)MPEG-DASHもMediaMuxerがFragmented MP4を作れないので多分無理です。
ブラウザで見たかったので(追加のアプリが必要とかは敷居が高い!)今回は動画ファイルを細切れにして送ることにした。iOSだと出来るみたいなのですが残念ですね...
(ffmpeg? バイナリが大きくなる上にライセンスがね...)
MediaMuxer#addTrackがスタート前じゃないと呼べないため、使いにくい!
それとは別なのですが、高レベルAPIのMediaRecorderにはMPEG2-TSのコンテナフォーマットに対応しているのですよね。
一方今回使った低レベルAPIのMediaMuxerにはMPEG2-TSのサポートはありません!え逆では
ならMediaMuxer / MediaCodecとかを使わずに、MediaRecorderを使えばHLSで配信出来たの!?って話になるんですが、
ならないです。内部音声を収録して一緒の動画ファイルにしたかったので。残念。
それに加えて、もし内部音声がなかった場合でも動画を短い間隔で作り直すのはMediaRecorderでは多分難しいような気がします。遅延が大きくなりそう。
MediaMuxerのインスタンスを作り直した場合は、MediaCodec.BufferInfoのpresentationTimeUsを0からスタートするようにする必要があるみたいです。動画エンコーダーも音声エンコーダーも、動画ファイル切り替え時にはpresentationTimeUsを0に戻すようにしないといけない。 · takusan23/ZeroMirror@3718678
そうしたら動いた。YATTA!
https://github.com/takusan23/ZeroMirror/commit/3718678180bea6037c0e23d2686b2265b2d4e58f
あとVP9の場合は解像度が厳しいです(1920x1080、1280x720 なら動く)、ディスプレイの画面解像度をそのまま入れたら落ちてしまう。
mp4ファイルをストリーミングできるように(ダウンロードしながら再生)するには、mp4ファイルの先頭にmoovブロックを置く必要があるらしい(?)のですが、MediaMuxerの場合は最後にmoovブロックを置くため、ストリーミング出来ません(全部ダウンロードしてから再生してしまう)
ffmpegが入ってる場合は以下のコマンドを叩くことで、moovブロックの位置が分かります。
ffmpeg -v trace -i ファイル.mp4 2>&1 | grep -e type:\'mdat\' -e type:\'moov\'多分こうなっていれば正解なのですが
$ ffmpeg -v trace -i publish74.mp4 2>&1 | grep -e type:\'mdat\' -e type:\'moov\'
[mov,mp4,m4a,3gp,3g2,mj2 @ 00000133f22a9a40] type:'moov' parent:'root' sz: 3844 32 1896645
[mov,mp4,m4a,3gp,3g2,mj2 @ 00000133f22a9a40] type:'mdat' parent:'root' sz: 1889577 7076 1896645MediaMuxerで出来たファイルはmoovブロックが一番下なのですよね...
$ ffmpeg -v trace -i publish29.mp4 2>&1 | grep -e type:\'mdat\' -e type:\'moov\'
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002461b249a40] type:'mdat' parent:'root' sz: 1420893 3232 1427957
[mov,mp4,m4a,3gp,3g2,mj2 @ 000002461b249a40] type:'moov' parent:'root' sz: 3840 1424125 1427957この問題はすでに先駆け者さんが対応してくれています!
すごい!

AndroidでMediaCodecを使いFFmpegなしで動画を圧縮する方法(ライブラリあり) - Qiita
追記:android-transcoderを参考に、iOSでいうGPUImageのような動画にエフェクトを掛けたりできるようにしたライブラリも登場したみたいです! Androidで、Mp4にウォータマークつけたり、フィルターかけたりする Androidにはまともな動画圧縮...
https://qiita.com/yuya_presto/items/d48e29c89109b746d000
GitHub - ypresto/qtfaststart-java: qt-faststart (make mp4 file streamable) in Java, MIT licensed.
qt-faststart (make mp4 file streamable) in Java, MIT licensed. - ypresto/qtfaststart-java
https://github.com/ypresto/qtfaststart-java
上記のプログラムをお借りすることで、moovブロックを先頭に移動できました、ありがとうございます!
$ ffmpeg -v trace -i publish74.mp4 2>&1 | grep -e type:\'mdat\' -e type:\'moov\'
[mov,mp4,m4a,3gp,3g2,mj2 @ 00000133f22a9a40] type:'moov' parent:'root' sz: 3844 32 1896645
[mov,mp4,m4a,3gp,3g2,mj2 @ 00000133f22a9a40] type:'mdat' parent:'root' sz: 1889577 7076 1896645ちなみにブラウザでもストリーミング再生なのでバッファリングの表示がされるようになります。
なおWebMの場合は特に何もせずともストリーミング可能なファイルにしてくれるみたい
新しめの端末じゃないと動かないっぽい?
動かない理由もよくわからん(MediaCodecのクラッシュログが不親切)
これはまじで謎です。
なんかエンコーダーの設定間違えたのかな。
追記:すいませんサンプリングレート間違ってただけでした。
わかりません、Chromeだと再生されませんでした。
Pixel 6 Pro のディスプレイちょっとだけ画面傷入っちゃって悲しい。
D.C.5 !?