MediaRecorderからサーバーにチャンクを送信し、ブラウザーで再生します

ヴァルディール

NodeJSの次のコードを使用して、サーバーから提供されるwebmファイルを再生できます。

app.get('/video', function(req, res){
    res.writeHead(200,{
        'Connection': 'close',
        'Cache-Control': 'private',
        'Content-Type': 'video/webm'
    });

    console.log('Http client connected: Streaming!');

    var readStream = fs.createReadStream('./small.webm');
    readStream.pipe(res);
});

ここで、getUserMedia()APIから直接WebMを取得したいと思います。そこで、Socket.IO内でMediaRecorderを使用しました。

 // Client
 var mediaRecorder = new MediaRecorder(stream, options);
 // ...
 mediaRecorder.ondataavailable = function(e) {
     console.log('Data', e.data);
     chunks.push(e.data);
     socket.emit('data', e.data);
 }


// Server
app.get('/video', function(req, res){
    res.writeHead(200,{
        "Content-Type": "video/webm",
        'Transfer-Encoding': 'chunked'
    });
    // Add the response to the clients array to receive streaming
    clients.push(res);
    console.log('Http client connected: Streaming!');
});

console.log("Starting server...");

httpServer.listen(9007);

var io = require('socket.io')(httpServer);
io.on('connection', function (socket) {
    console.log("Listening...");
    socket.on('data', function (data) {
        console.log("[data]", data);
        // Actual HTTP audio Streaming
        if (clients.length > 0){
            console.log("[http("+clients.length+")]", data);
            for (var client in clients){
                clients[client].write(data);
            }
        }
    });
});

だから今私はブラウザに戻ってストリームを受け取りますが、それを再生することができません:

    function getHttpStreaming() {
        console.log("Getting streaming");
        var d = new Date();
        var n = d.getTime();
        audio = document.getElementById('video-streaming');
        audio.src = 'https://localhost:9007/video?' + n;
        audio.load();
    }

ネットワークタブにはストリーミングが来るのが表示されますが、何も再生されません!何が足りないのですか?

編集済み

@Bradが指摘しているように、WebMが機能するには、getUserMediaからのストリームに含まれていない特別な構成が必要ので、ストリームの間にffmpegを追加し、ffmpeg出力をブラウザーに提供してビデオを再生しました。(icecastでも同じです)しかし、非常に遅れており、理由はわかりません。また、テストとして、ブラウザに直接送信する代わりに、icecastに送信しましたが、icecastで再生できず、ffmpegのパイプが壊れていました。私が使用したブラウザに送信するために:

const ffmpeg = child_process.spawn('ffmpeg', [
    '-i', 'pipe:0',
    '-f', 'webm',
    '-cluster_size_limit', '2M',
    '-cluster_time_limit', '5100',
    '-content_type', 'video/webm',
    //'-vf', 'scale=1280:-1',
    '-r', '30',
    '-ac', '2',
    '-acodec', 'libopus',
    '-b:a', '96K',
    '-vcodec', 'libvpx',
    '-b:v', '2.5M',
    '-crf', '30',
    '-g', '150',
    '-deadline', 'realtime',
    '-threads', '8',
    //'-y',
    //'icecast://xxx:xxxx@host:port/live',
    'pipe:1'
]);

私の出力は次のとおりです。

FFmpeg STDERR: ffmpeg version 2.8.11-0ubuntu0.16.04.1 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609
  configuration: --prefix=/usr --extra-version=0ubuntu0.16.04.1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libavresample   2.  1.  0 /  2.  1.  0
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100

FFmpeg STDERR: Input #0, matroska,webm, from 'pipe:0':
  Metadata:
    encoder         : Chrome
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0(eng): Audio: opus, 48000 Hz, mono, fltp (default)
    Stream #0:1(eng): Video: vp9 (Profile 0), yuv420p(tv), 640x480, SAR 1:1 DAR 4:3, 16.67 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      alpha_mode      : 1

FFmpeg STDERR: [libvpx @ 0x21c32a0] v1.5.0

FFmpeg STDERR: Output #0, webm, to 'pipe:1':

FFmpeg STDERR:   Metadata:

FFmpeg STDERR:     encoder         :
FFmpeg STDERR: Lavf56.40.101
FFmpeg STDERR:

FFmpeg STDERR:     Stream #0:0
FFmpeg STDERR: (eng)
FFmpeg STDERR: : Video: vp8 (libvpx), yuv420p, 640x480 [SAR 1:1 DAR 4:3], q=-1--1, 2500 kb/s
FFmpeg STDERR: ,
FFmpeg STDERR: 30 fps,
FFmpeg STDERR: 1k tbn,
FFmpeg STDERR: 30 tbc
FFmpeg STDERR:  (default)
FFmpeg STDERR:

FFmpeg STDERR:     Metadata:

FFmpeg STDERR:       alpha_mode      :
FFmpeg STDERR: 1
FFmpeg STDERR:

FFmpeg STDERR:       encoder         :
FFmpeg STDERR: Lavc56.60.100 libvpx
FFmpeg STDERR:
    Stream #0:1(eng): Audio: opus (libopus), 48000 Hz, stereo, flt, 96 kb/s (default)
    Metadata:
      encoder         : Lavc56.60.100 libopus
Stream mapping:
  Stream #0:1 -> #0:0 (vp9 (native) -> vp8 (libvpx))
  Stream #0:0 -> #0:1 (opus (native) -> opus (libopus))

FFmpeg STDERR: frame=  118 fps=3.6 q=0.0 size=     660kB time=00:00:15.05 bitrate= 359.4kbits/s
[data] <Buffer 43 c6 81 0b 03 80 fb 03 3f 22 89 95 18 c5 f0 68 67 7c 25 76 9d b6 e7 b4 2d dc 9c b4 da a3 0c 47 e1 aa ae 3d f2 84 1e 65 08 22 9e a7 af b6 50 7d a2 c7 ... >
FFmpeg STDERR: frame=  123 fps=3.6 q=0.0 size=     989kB time=00:00:15.65 bitrate= 517.6kbits/s
[data] <Buffer 43 c6 81 0d 20 80 fb 03 40 75 4b 59 48 46 42 79 37 d8 44 de f5 ef 7b ec ce 05 c4 44 48 bc 12 6e a2 a9 1e bd 73 59 bc 27 fd ab ec bf a1 8a 32 67 c4 ee ... >
FFmpeg STDERR: frame=  127 fps=3.5 q=0.0 size=     989kB time=00:00:16.19 bitrate= 500.4kbits/s
[data] <Buffer 43 c6 81 0f 77 80 fb 03 43 f6 ef d2 61 b5 47 bb e9 06 5f 7e 37 eb 58 a5 4d a2 30 ff e1 4c 41 28 90 f1 dd 4f 45 b0 44 5b d2 de c3 85 47 0d d5 36 44 39 ... >
FFmpeg STDERR: frame=  132 fps=3.5 q=0.0 size=     989kB time=00:00:16.79 bitrate= 482.5kbits/s
[data] <Buffer 43 c6 81 11 93 80 fb 03 52 2d 4d 14 48 6c 14 63 aa de e8 14 0f 31 31 c4 13 a5 f6 0b 06 ad a2 e3 99 ec 77 de c7 ae 92 13 73 df 8b 80 25 bc fc 21 14 33 ... >
FFmpeg STDERR: frame=  136 fps=3.5 q=0.0 size=     989kB time=00:00:17.33 bitrate= 467.5kbits/s
[data] <Buffer 43 c6 81 13 73 80 fb 03 40 3a 72 51 05 2d 5e 70 84 92 99 4f 1f 7b 39 05 b9 43 15 d9 a1 47 76 9b cc bf 58 ff dd 2f d7 af f2 56 9a b5 8c 1a af 30 48 f1 ... >
FFmpeg STDERR: frame=  140 fps=3.4 q=0.0 size=     989kB time=00:00:17.81 bitrate= 454.9kbits/s
[data] <Buffer 43 c6 81 15 53 80 fb 03 3f 66 84 ff f2 b9 44 64 c0 ed e4 40 bf e2 43 89 d7 44 4d f1 f7 10 fb 92 a7 1a 20 8a 5a c7 fa 9d ff 8a 83 aa 3f 70 e5 a3 05 00 ... >
FFmpeg STDERR: frame=  144 fps=3.4 q=0.0 size=     989kB time=00:00:18.29 bitrate= 442.9kbits/s
[data] <Buffer 43 c9 81 17 70 80 fb 83 ff 10 fc 11 43 d3 8f 64 b4 d3 a3 74 c6 87 be c0 94 39 78 a0 8c 12 60 76 cc 0b d5 a4 2e d8 7b ab 59 11 d2 44 bf a2 5a 76 32 04 ... >
FFmpeg STDERR: frame=  148 fps=3.3 q=0.0 size=     989kB time=00:00:18.83 bitrate= 430.2kbits/s
[data] <Buffer 43 c6 81 19 50 80 fb 03 1a 70 8a fe 75 d9 56 19 b3 91 cc 5d 17 d8 4c 29 c0 30 61 37 ae 53 c4 8b 18 a5 bc 74 0c ab 6d 7e 32 cc 8d 89 35 6a a3 3a eb 65 ... >
FFmpeg STDERR: frame=  152 fps=3.2 q=0.0 size=    1204kB time=00:00:19.31 bitrate= 510.8kbits/s
[data] <Buffer 43 c6 81 1b e3 80 fb 03 51 93 d5 35 c0 0b 06 13 d6 b2 67 86 98 1e 4b 8e 72 1d 3a a6 81 09 97 ef f8 d6 c2 b6 1a ee f3 bb c9 f3 3f 16 e8 be d3 d0 90 72 ... >
FFmpeg STDERR: frame=  157 fps=3.2 q=0.0 size=    1204kB time=00:00:19.97 bitrate= 493.9kbits/s
[data] <Buffer 43 c6 81 1d c3 80 fb 03 44 52 8f e0 6d db 60 9d 43 1d 0e ae dc 9c 0b 94 f8 b0 f1 13 d0 f5 1b b6 f9 8e 2b 0d f6 93 fa d5 99 d9 bb fe b5 29 3d 61 2d bf ... >
FFmpeg STDERR: frame=  161 fps=3.2 q=0.0 size=    1204kB time=00:00:20.45 bitrate= 482.4kbits/s
[data] <Buffer 43 c6 81 20 57 80 fb 03 4f c1 d1 78 88 0c 6b 82 a7 51 3e 65 71 a6 62 07 09 60 6f ce 7c 83 7d 15 4f 4b 46 3e e3 b7 78 49 e5 a7 3d bf e2 37 93 7a 17 1a ...

編集済み2

Chromeは、次のエラーでIcecastビデオストリームの再生に失敗します。

00:00:13 736    video_decoder   FFmpegVideoDecoder
00:00:13 736    info    Selected FFmpegVideoDecoder for video decoding, config: codec: vp8 format: 4 profile: vp8 coded size: [640,480] visible rect: [0,0,640,480] natural size: [640,480] has extra data? false encrypted? false rotation: 0°
00:00:13 739    error   Failed to send video packet for decoding: timestamp=24300000 duration=33000 size=201 side_data_size=0 is_key_frame=0 encrypted=0 discard_padding (ms)=(0, 0)
00:00:13 739    error   video decode error
00:00:13 739    audio_buffering_state   BUFFERING_HAVE_ENOUGH
00:00:13 739    pipeline_error  PIPELINE_ERROR_DECODE
00:00:13 739    pipeline_state  kStopping
00:00:13 740    pipeline_state  kStopped
00:00:13 731    duration    unknown

編集済み3

クロムの問題はffmpegの出力に関連しているようです。以下を使用して、ChromeとFirefoxの両方でIcecastストリームを再生できました。

const ffmpeg = child_process.spawn('ffmpeg', [
    '-i', 'pipe:0',
    '-f', 'webm',
    '-cluster_size_limit', '2M',
    '-cluster_time_limit', '5100',
    '-content_type', 'video/webm',
    '-r', '30',
    '-ac', '2',
    '-acodec', 'libopus',
    '-b:a', '96K',
    '-vcodec', 'libvpx',
    '-b:v', '1M',//'2.5M',
    '-crf', '60',
    '-bufsize', '2M',
    '-g', '10',
    '-deadline', 'realtime',
    '-threads', '8',
    '-keyint_min', '10',
    'icecast://source:hackme@localhost:8004/live'
]);
ブラッド

WebMストリームにただ針を落とすことはできません。WebM / Matroskaでは、トラック情報を初期化するためのセットアップが必要です。その後、クラスターが作成され、クラスターから開始する必要があります。さらに、Chromeでは、各クラスターがキーフレームで開始する必要があります。これは、MediaRecorderからのデータでは保証できません。したがって、サーバー側のトランスコーディング(または、少なくともVP8ストリームでの厄介なハッキング)が必要です。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

PCブラウザからQRコードをキャプチャして、モバイルで自分のWebサイトにログインします。

分類Dev

方法:ブラウザはJSONをサーバーに送信しますか?

分類Dev

Javaサーバーはhtmlページをファイルからブラウザに送信します

分類Dev

ブラウザでトークンを再生成(更新)します

分類Dev

AndroidスクリーンレコーダーからキャプチャしたビデオはWebブラウザで再生できません

分類Dev

キャプチャした写真を(ブラウザから-キャンバスから)ノードサーバーにアップロードするにはどうすればよいですか?

分類Dev

セロリのバックグラウンドタスクからDjangoチャネルを使用してブラウザにメッセージを送信します

分類Dev

サーバーからクライアントに IP を送信します。ジャワネットワーク

分類Dev

ブラウザで圧縮ファイルをgolangサーバーからダウンロードします

分類Dev

MediaRecorder BLOBをサーバーに送信し、バックエンドでファイルをビルドします

分類Dev

ブラウザはどのようにサーバーにキャンセルを通知しますか?

分類Dev

ビデオをライブストリーミングし、ユーザーからの入力をキャプチャして、Raspberry PiRobotに送信します

分類Dev

ブラウザウィンドウの一部をPDFに印刷し、ファックスで送信するサーバーに送信する

分類Dev

HttpRequestをキャンセルした後、サーバーからのタイムアウトまでブラウザがハングする

分類Dev

接続を開いている間、ブラウザからWebSocketサーバーにユーザーIDを送信します

分類Dev

Firefox WebExtensionsはブラウザから拡張機能にメッセージを送信し、コールバック関数で応答を取得します

分類Dev

コンピューターのカメラでキャプチャしたビデオをWebサイトからサーバーに送信する

分類Dev

最初のブラウザリクエスト時にJWTトークンをサーバーに送信します(ローカルストレージを使用)

分類Dev

ブラウザから「blocked:other」エラーステータスを取得する-Angularアプリケーションで、サーバーから情報をフェッチするためにRESTAPI呼び出しを行いました

分類Dev

ブラウザネットワークキャプチャからHttpWebRequestコードを生成します

分類Dev

ChromeのContent-Typeヘッダーに準拠していないチャンク応答ブラウザを再生します

分類Dev

バックグラウンドで何かを実行し、完了したらユーザーに通知します

分類Dev

ウェブカメラから画像をキャプチャし、フラスコサーバーにアップロードします

分類Dev

ActionCableを使用して、チャネル内からのサブスクライバーの数をカウントする方法はありますか?

分類Dev

ギャラリーからマルチイメージを選択して、react-nativeでサーバーに送信します

分類Dev

サーバーからexeファイルを返し、ブラウザを介してクライアントにダウンロードする

分類Dev

iOSにブラウザからのディープ/ユニバーサルリンクを*強制しない*ようにする方法はありますか?

分類Dev

firebase動的リンク、最初にユーザーをウェブサイトに送信しますか?

分類Dev

グーグルクロームブラウザコンソールからNetflixでビデオ再生速度を設定します

Related 関連記事

  1. 1

    PCブラウザからQRコードをキャプチャして、モバイルで自分のWebサイトにログインします。

  2. 2

    方法:ブラウザはJSONをサーバーに送信しますか?

  3. 3

    Javaサーバーはhtmlページをファイルからブラウザに送信します

  4. 4

    ブラウザでトークンを再生成(更新)します

  5. 5

    AndroidスクリーンレコーダーからキャプチャしたビデオはWebブラウザで再生できません

  6. 6

    キャプチャした写真を(ブラウザから-キャンバスから)ノードサーバーにアップロードするにはどうすればよいですか?

  7. 7

    セロリのバックグラウンドタスクからDjangoチャネルを使用してブラウザにメッセージを送信します

  8. 8

    サーバーからクライアントに IP を送信します。ジャワネットワーク

  9. 9

    ブラウザで圧縮ファイルをgolangサーバーからダウンロードします

  10. 10

    MediaRecorder BLOBをサーバーに送信し、バックエンドでファイルをビルドします

  11. 11

    ブラウザはどのようにサーバーにキャンセルを通知しますか?

  12. 12

    ビデオをライブストリーミングし、ユーザーからの入力をキャプチャして、Raspberry PiRobotに送信します

  13. 13

    ブラウザウィンドウの一部をPDFに印刷し、ファックスで送信するサーバーに送信する

  14. 14

    HttpRequestをキャンセルした後、サーバーからのタイムアウトまでブラウザがハングする

  15. 15

    接続を開いている間、ブラウザからWebSocketサーバーにユーザーIDを送信します

  16. 16

    Firefox WebExtensionsはブラウザから拡張機能にメッセージを送信し、コールバック関数で応答を取得します

  17. 17

    コンピューターのカメラでキャプチャしたビデオをWebサイトからサーバーに送信する

  18. 18

    最初のブラウザリクエスト時にJWTトークンをサーバーに送信します(ローカルストレージを使用)

  19. 19

    ブラウザから「blocked:other」エラーステータスを取得する-Angularアプリケーションで、サーバーから情報をフェッチするためにRESTAPI呼び出しを行いました

  20. 20

    ブラウザネットワークキャプチャからHttpWebRequestコードを生成します

  21. 21

    ChromeのContent-Typeヘッダーに準拠していないチャンク応答ブラウザを再生します

  22. 22

    バックグラウンドで何かを実行し、完了したらユーザーに通知します

  23. 23

    ウェブカメラから画像をキャプチャし、フラスコサーバーにアップロードします

  24. 24

    ActionCableを使用して、チャネル内からのサブスクライバーの数をカウントする方法はありますか?

  25. 25

    ギャラリーからマルチイメージを選択して、react-nativeでサーバーに送信します

  26. 26

    サーバーからexeファイルを返し、ブラウザを介してクライアントにダウンロードする

  27. 27

    iOSにブラウザからのディープ/ユニバーサルリンクを*強制しない*ようにする方法はありますか?

  28. 28

    firebase動的リンク、最初にユーザーをウェブサイトに送信しますか?

  29. 29

    グーグルクロームブラウザコンソールからNetflixでビデオ再生速度を設定します

ホットタグ

アーカイブ