たくさんの自由帳
Androidのお話
投稿日 : | 0 日前
文字数(だいたい) : 4629
どうもこんばんわ、(お久しぶりです)
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からスタートするようにする必要があるみたいです。
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 1896645
MediaMuxerで出来たファイルは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
この問題はすでに先駆け者さんが対応してくれています!
すごい!
上記のプログラムをお借りすることで、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 !?
