将块从 MediaRecorder 发送到服务器并在浏览器中播放

2023-12-23

使用 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();
    }

网络选项卡显示正在播放流媒体,但没有播放任何内容!我缺少什么?

EDITED

As pointed out by @Brad WebM needs some special configs https://wiki.xiph.org/Icecast_Server/Streaming_WebM_to_Icecast_with_FFmpeg in order to work that doesn't contains in the stream coming from getUserMedia, so I added ffmpeg between the stream and served the ffmpeg output to the browser and the video played! (same on icecast) But is getting very lagged and I do not know why. Also, as a test instead of sending it directly to the browser I've sent it to icecast, but icecast was unable to play it resulting in ffmpeg's broken pipe. In order to send it to the browser I've used:

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 ...

EDITED2

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

EDITED3

看来 chrome 问题与 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 流进行一些令人讨厌的黑客攻击)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将块从 MediaRecorder 发送到服务器并在浏览器中播放 的相关文章

  • 使用 Node.js 访问用 C++ 编写的 SDK

    我有一个用 C 语言编写的 SDK 可以与我的扫描仪设备进行通信 我需要开发一个可以访问扫描仪设备的电子应用程序 我知道有很多库可用于扫描仪 但我想使用这个 SDK 因为它允许我访问设备的完整功能 而且它是由设备制造商提供的 那么 有没有什
  • Node.js 上的 Connect 出现“无法 GET /”

    我正在尝试使用以下方式开始提供一些静态网页connect像这样 var connect require connect var nowjs require now var io require socket io var app conne
  • 在 Node.js 中创建 JSON 数组

    我需要在用 Node js 编写的服务器中创建一个 JSON 字符串 以便在请求时发送到客户端 问题是这个 JSON 取决于服务器中的可用数据 因此 JSON 数组的大小并不总是相同 我已经尝试了一整天 但尽管我感觉很接近 但我仍然不明白
  • express-session:滚动会话过期配置

    所以我在 mongo 商店中使用快速会话 如下所示 app use session secret some secret here saveUninitialized false resave false store new MongoSt
  • 如何在 Sails.js 中嵌入和编写 mongo 对象(超过一层深度)?

    从 sails js 示例来看 Person js var Person attributes firstName STRING lastName STRING age type INTEGER max 150 required true
  • AWS Lambda 上的 NodeJS 集群

    是否可以在 lambda 函数中使用 cluster 模块 我试过这个 use strict var cluster require cluster var http require http var os require os var n
  • browserify 错误 /usr/bin/env: 节点: 没有这样的文件或目录

    我通过 apt get install 安装了 node js 和 npm 以及所有依赖项 然后安装了 browserify npm install browserify g 它完成了整个过程 看起来安装正确 但是当我尝试为此做一个简单的捆
  • Node.js:您什么时候知道异步任务集合何时完成?

    我想深入一个目录 并根据正则表达式检查我在其中看到的每个文件的名称 基本上是通用unix的一个版本find命令 仅用 Node js 编写 我不关心文件的顺序 但我确实想确保获得所有文件 我有以下代码 我认为 它接近我想要的 它需要一个 s
  • Node.js 中的 Twilio 短信回复

    我正在使用 node js 中的 twilio 编写移动通知系统 目前可以向用户发送短信 但我希望用户能够回复我 我需要收集用户发送文本的电话号码以及消息的内容 以查询我的 mongoosedb 我找不到太多这方面的信息 因此非常感谢您的帮
  • 未处理的拒绝:发送后无法设置标头

    我正在 Dialogflow 中创建一个聊天机器人 当我尝试将数据添加到数据库时 它抛出了 未处理的拒绝 错误 这是我的index js文件 use strict const functions require firebase funct
  • Multer 使用数据创建新文件夹

    I use multer https github com expressjs multer 问题1 当我将以下代码片段放入app js app use multer dest uploads single file 它在根文件夹下创建一个
  • Node.js 请求随机开始挂起,直到服务器重新启动后才会清除

    我在我们的网络应用程序上遇到了一个非常奇怪且看似随机的问题 我似乎无法成功调试 它可以正常运行 10 分钟到 6 小时 然后突然无法向服务器发出或从服务器发出远程请求 它们只是挂起 这包括常规的 http 和 Web 套接字请求 奇怪的是
  • 将新属性动态添加到 Node 中现有的 JSON 数组中

    我需要添加当前 JSON 中不存在的属性 json 对象如下所示 var jsonObj result OK data 我想在 数据 中添加温度 我可以像下面那样做 jsonObj data push temperature 然后 我想在
  • react-native-screens:compileDebugKotlin 错误

    失败 构建失败并出现异常 什么地方出了错 任务 react native screens compileDebugKotlin 执行失败 评估任务 react native screens compileDebugKotlin 的属性 fi
  • Sequelize 4.3.2 n:m(多对多)关联:未处理的拒绝 SequelizeEagerLoadingError

    我有 3 个模型 用户 项目 UserProject module exports function sequelize DataTypes var User sequelize define User title DataTypes ST
  • Node.js 中的startsWith:类型错误:未定义不是函数

    我在 Node js 中使用startsWith 时遇到错误 脚本sw js startswith var str Sein oder nicht sein dass ist hier die Frage console log str s
  • 在 AWS Lambda 中共享代码

    在 AWS Lambda 函数之间共享代码的首选方式是什么 我有这样的结构 functions a 节点模块 index js 包 json b 节点模块 index js 包 json c 节点模块 index js 包 json 这让每
  • 早于 0.4.12 的 Node.js 无法在 AWS EC2 上正常工作。为什么?

    我无法在 AWS EC2 Ubuntu 或 CentOs 没关系 上安装 node js v0 6 1 安装后我输入node 处理器负载达到100 但 v0 4 12 工作正常 可能只有我有这个问题 那不好意思了 请告诉我我做错了什么 提前
  • NodeJS - 将相对路径转换为绝对路径

    In my 文件系统我的工作目录在这里 C temp a b c d 在 b bb 下有文件 tmp txt C temp a b bb tmp txt 如果我想从工作目录转到该文件 我将使用以下路径 bb tmp txt 如果该文件不存在
  • 节点未找到全局模块

    所以我意识到这是一个相当通用的标题和问题 但我已经搜索了很多答案 但遗憾的是它们似乎都不适合我 我希望通过我自己提供更多信息 也许有人有一个具体的答案 或者确切地知道将我重定向到哪个答案 我的问题 当我全局安装节点模块时 例如npm ins

随机推荐