0

HTML5 ビデオ要素で fmp4 を再生しようとしています。

ffmpeg の出力を MSE に渡す Websocket の作成に成功しました。

ただし、Firefox (72.0.1、64 ビット、Ubuntu 18.04LTS の下) でページを開こうとすると、常にエラーが発生します。

Media resource blob:http://localhost/XXXX could not be decoded, error: Error Code: NS_ERROR_FAILURE (0x80004005)
Details: virtual mozilla::MediaResult mozilla::MP4ContainerParser::IsInitSegmentPresent(const mozilla::MediaSpan &): Invalid Top-Level Box:f"

これは私のFFMPEGの行です:

ffmpeg -r 5 -i rtsp://IPCAMERA -c:v copy -an -movflags +frag_keyframe+empty_moov+default_base_moof -f mp4 pipe:1

これは、サーバー側 Java (Tomcat エンジンを使用) がこのコマンドの出力を解析する方法です (これは非効率的かもしれませんが、今のところ問題ありません)。

ProcessBuilder b = new ProcessBuilder(FFMPEGCOMMAND.split("\\s+"));
try {
    p = b.start();
} catch (IOException e) {
    e.printStackTrace();
}
InputStream input = p.getInputStream();
int bytes_read = 0;
byte buffer[] = new byte[512];
try {
    while (0 < (bytes_read = input.read(buffer, 0, 512))) {
        System.out.println("Bytes read:" + bytes_read);
        this.session.getBasicRemote().sendBinary(ByteBuffer.wrap(buffer));
    }
} catch (IOException e) {
    e.printStackTrace();
}

次に、クライアント側は、このリポジトリのような websocket-MSEです。

結果:

  1. サーバー側をデバッグし、sendBinary呼び出しの前にブレークポイントがあり、サーバー側を実行する前に数秒待機すると、ブラウザに最初の画像が表示されますが、すぐに上記のエラーが発生します。

  2. サーバー側を (ブレークポイントなしで) 実行すると、ブラウザーに画像が表示されず、すぐにエラーが発生します。

Invalid Top-Level boxエラー メッセージの後には、常にランダムなガベージ キャラクタが続きます。

これが機能することの証明は、ポイント 1 にあります。データをクライアントに転送する前にしばらく待つと、そのエラーに到達する前に 1 (またはそれ以上のフレーム) をデコードできます。

これは、ffmpeg コマンドラインのエラーである可能性があります。

しかし、このトピックに関する適切なリソースを実際に見つけることができませんでした (古いリリースの Firefox に関連するものしか見つかりませんでした)。

アップデート1

これは、同じコマンドがパイプの代わりに mp4 ファイルを作成するときの FFMPEG ログです: https://pastebin.com/Gjq2vxeT

これは、間違ったボックスを含む詳細な Firefox ログです。

Details: virtual mozilla::MediaResult mozilla::MP4ContainerParser::IsInitSegmentPresent(const mozilla::MediaSpan &): Invalid Top-Level Box:f

ポイント2でマークされたシナリオ(ブレークポイントなしで実行)を実行しているとき、トップレベルボックスは常に「f」であることに注意してください。

アップデート2:

ffmpeg の現在の出力は次のとおりです (最初の 128 項目を数値と英数字で表現): https://pastebin.com/DeJMfNYs

興味深いのは、最初の 4 バイトが無効に見えることです。しかし、byte4 (5 バイト目) からは問題ないようです ("ftyp")。

これを確認していただけますか?

4

1 に答える 1

1

問題はサーバー側にありました。

この行で:

this.session.getBasicRemote().sendBinary(ByteBuffer.wrap(buffer));

バッファに 0 があると、ByteBuffer の wrap メソッドが停止するため、これは良くありません。

良いものはこれです:

this.session.getBasicRemote().sendBinary(ByteBuffer.wrap(buffer, 0, bytes_read));

なんてばかげた間違い - 今では正常に動作します:)

于 2020-01-23T12:40:23.187 に答える