如何使用 webRTC 和基于服务器的对等连接录制网络摄像头和音频

IT技术 javascript c++ video-streaming webrtc audio-streaming
2021-01-30 20:28:37

我想记录用户的网络摄像头和音频并将其保存到服务器上的文件中。然后这些文件将能够提供给其他用户。

我在播放方面没有问题,但是在获取要录制的内容时遇到了问题。

我的理解是 getUserMedia.record()函数尚未编写 - 到目前为止只提出了一个建议。

我想使用 PeerConnectionAPI 在我的服务器上创建对等连接。我知道这有点 hacky,但我认为应该可以在服务器上创建一个对等点并记录客户端对等点发送的内容。

如果这是可能的,那么我应该能够将这些数据保存为 flv 或任何其他视频格式。

我的偏好实际上是在客户端录制网络摄像头 + 音频,如果客户端在上传前不喜欢他们的第一次尝试,则允许他们重新录制视频。这也将允许网络连接中断。我看过一些代码,它允许通过将数据发送到画布来从网络摄像头记录单个“图像”——这很酷,但我也需要音频。

这是我到目前为止的客户端代码:

  <video autoplay></video>

<script language="javascript" type="text/javascript">
function onVideoFail(e) {
    console.log('webcam fail!', e);
  };

function hasGetUserMedia() {
  // Note: Opera is unprefixed.
  return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia || navigator.msGetUserMedia);
}

if (hasGetUserMedia()) {
  // Good to go!
} else {
  alert('getUserMedia() is not supported in your browser');
}

window.URL = window.URL || window.webkitURL;
navigator.getUserMedia  = navigator.getUserMedia || navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia || navigator.msGetUserMedia;

var video = document.querySelector('video');
var streamRecorder;
var webcamstream;

if (navigator.getUserMedia) {
  navigator.getUserMedia({audio: true, video: true}, function(stream) {
    video.src = window.URL.createObjectURL(stream);
    webcamstream = stream;
//  streamrecorder = webcamstream.record();
  }, onVideoFail);
} else {
    alert ('failed');
}

function startRecording() {
    streamRecorder = webcamstream.record();
    setTimeout(stopRecording, 10000);
}
function stopRecording() {
    streamRecorder.getRecordedData(postVideoToServer);
}
function postVideoToServer(videoblob) {
/*  var x = new XMLHttpRequest();
    x.open('POST', 'uploadMessage');
    x.send(videoblob);
*/
    var data = {};
    data.video = videoblob;
    data.metadata = 'test metadata';
    data.action = "upload_video";
    jQuery.post("http://www.foundthru.co.uk/uploadvideo.php", data, onUploadSuccess);
}
function onUploadSuccess() {
    alert ('video uploaded');
}

</script>

<div id="webcamcontrols">
    <a class="recordbutton" href="javascript:startRecording();">RECORD</a>
</div>
6个回答

你绝对应该看看Kurento它提供了一个 WebRTC 服务器基础设施,允许您从 WebRTC 提要等进行记录。您还可以在此处找到您正在规划的应用程序的一些示例向该演示添加录制功能并将媒体文件存储在 URI(本地磁盘或任何地方)中非常容易。

该项目在LGPL Apache 2.0下获得许可


编辑 1

自这篇文章以来,我们添加了一个新教程,展示了如何在几个场景中添加记录器

免责声明:我是开发 Kurento 团队的一员。

找到上述问题的答案(贴在这里给别人),Kurento目前支持JDK 7.0,并不是必须依赖Ubuntu 14.04,它应该也支持更高版本,但Kurento没有在其他版本的Ubuntu上正式测试/ 其他 linux 版本。此外,Kurento 还发布了 64 位版本,可随时用于安装,但是您可以安装 32 位版本的服务器,但您必须先构建它。
2021-03-27 20:28:37
我只是用 Kurento 来做这样的录音。我并不复杂,但需要一点时间来理解这个概念——因为有些文档真的很刻薄——并且找到我可以发送给 kurento 的内容,或者事件的描述等有时真的很令人沮丧。但无论如何 - 像这样的开放项目确实是一项出色的工作,值得使用。Kurento 仅在 linux 中工作(windows 版本不是官方的,不能使用全部功能)。
2021-03-29 20:28:37
@user344146 那可能是我在回答。你介意分享那个帖子的链接吗?如果你得到了那个答案,那可能是因为你问了一些已经存在或在列表中的问题。看起来您正在尝试编译 SNAPSHOT 版本。这些工件不会在中央发布,因此您可以查看教程的版本或使用我们的内部开发存储库。这已经在列表中多次回答了,文档中有一个关于使用开发版本的条目......我们花时间写它,所以你花时间阅读它会很高兴。
2021-04-01 20:28:37
@Redtopia 在最近的一些负载测试中,我们能够在 i5/16GB RAM 上获得 150 个 webrtc 的 one2one 连接。您可以期待这些数字在未来会更好,但不要期待奇迹:SRTP 正在进行大量加密,这要求很高。我们正在研究硬件加速的加密/解密,数字会更高,尽管在我们更彻底地测试之前我不能向你保证它会有多好,但我们预计会有 3 倍的改进
2021-04-07 20:28:37
不幸的是,正如我在回答中所说,在 Twilio 收购之后,Kurento 的发展严重放缓。我建议改用 Janus。
2021-04-10 20:28:37

我相信仅使用 kurento 或其他 MCU 来录制视频会有点矫枉过正,尤其是考虑到 Chrome从 v47 和 Firefox 自 v25 开始就支持MediaRecorder API。所以在这个路口,你甚至可能不需要外部 js 库来完成这项工作,试试我制作的这个使用 MediaRecorder 录制视频/音频的演示:

演示- 可以在 chrome 和 firefox 中工作(故意省略将 blob 推送到服务器代码)

Github 代码源

如果运行 firefox,你可以在这里测试它本身(chrome 需要https):

'use strict'

let log = console.log.bind(console),
  id = val => document.getElementById(val),
  ul = id('ul'),
  gUMbtn = id('gUMbtn'),
  start = id('start'),
  stop = id('stop'),
  stream,
  recorder,
  counter = 1,
  chunks,
  media;


gUMbtn.onclick = e => {
  let mv = id('mediaVideo'),
    mediaOptions = {
      video: {
        tag: 'video',
        type: 'video/webm',
        ext: '.mp4',
        gUM: {
          video: true,
          audio: true
        }
      },
      audio: {
        tag: 'audio',
        type: 'audio/ogg',
        ext: '.ogg',
        gUM: {
          audio: true
        }
      }
    };
  media = mv.checked ? mediaOptions.video : mediaOptions.audio;
  navigator.mediaDevices.getUserMedia(media.gUM).then(_stream => {
    stream = _stream;
    id('gUMArea').style.display = 'none';
    id('btns').style.display = 'inherit';
    start.removeAttribute('disabled');
    recorder = new MediaRecorder(stream);
    recorder.ondataavailable = e => {
      chunks.push(e.data);
      if (recorder.state == 'inactive') makeLink();
    };
    log('got media successfully');
  }).catch(log);
}

start.onclick = e => {
  start.disabled = true;
  stop.removeAttribute('disabled');
  chunks = [];
  recorder.start();
}


stop.onclick = e => {
  stop.disabled = true;
  recorder.stop();
  start.removeAttribute('disabled');
}



function makeLink() {
  let blob = new Blob(chunks, {
      type: media.type
    }),
    url = URL.createObjectURL(blob),
    li = document.createElement('li'),
    mt = document.createElement(media.tag),
    hf = document.createElement('a');
  mt.controls = true;
  mt.src = url;
  hf.href = url;
  hf.download = `${counter++}${media.ext}`;
  hf.innerHTML = `donwload ${hf.download}`;
  li.appendChild(mt);
  li.appendChild(hf);
  ul.appendChild(li);
}
      button {
        margin: 10px 5px;
      }
      li {
        margin: 10px;
      }
      body {
        width: 90%;
        max-width: 960px;
        margin: 0px auto;
      }
      #btns {
        display: none;
      }
      h1 {
        margin-bottom: 100px;
      }
<link type="text/css" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<h1> MediaRecorder API example</h1>

<p>For now it is supported only in Firefox(v25+) and Chrome(v47+)</p>
<div id='gUMArea'>
  <div>
    Record:
    <input type="radio" name="media" value="video" checked id='mediaVideo'>Video
    <input type="radio" name="media" value="audio">audio
  </div>
  <button class="btn btn-default" id='gUMbtn'>Request Stream</button>
</div>
<div id='btns'>
  <button class="btn btn-default" id='start'>Start</button>
  <button class="btn btn-default" id='stop'>Stop</button>
</div>
<div>
  <ul class="list-unstyled" id='ul'></ul>
</div>
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>

Chrome 49 是第一个支持没有标志的 MediaRecorder API。
2021-03-14 20:28:37

请检查RecordRTC

RecordRTC 在github 上获得了麻省理工学院的许可

同意 - 很棒,但看起来它只单独记录数据。
2021-03-16 20:28:37
这种方法通过 Chrome 中的 Whammy.js 起作用。这是有问题的,因为与 Whammy 为 Chrome 缺少 MediaStreamRecorder 提供的仿真相比,质量往往要低得多。本质上发生的是 WhammyRecorder 将视频标签指向 MediaStream 对象 URL,然后以特定帧速率拍摄画布元素的 webp 快照。然后它使用 Whammy 将所有这些帧组合成一个 webm 视频。
2021-03-16 20:28:37
@BrianDear 有一个RecordRTC-together
2021-03-22 20:28:37
这太棒了——我的问题是:可以一起录制视频和音频吗(直播一个真实的视频而不是两个单独的东西?)
2021-04-12 20:28:37

是的,正如您所理解的,MediaStreamRecorder 目前尚未实现。

MediaStreamRecorder 是一个用于记录 getUserMedia() 流的 WebRTC API。它允许网络应用程序从实时音频/视频会话创建文件。

或者,您可以这样做http://ericbidelman.tumblr.com/post/31486670538/creating-webm-video-from-getusermedia但缺少音频。

是的,您可以捕获音频文件,将其发送到服务器,然后在那里将它们组合起来,在服务器端创建一个真正的视频文件。但是这个解决方案在客户端可能会很慢,这取决于它的计算机配置,因为它必须使用画布创建图像文件并捕获音频,所有这些都在 RAM 中......顺便说一句,firefox 团队正在研究它,所以希望他们很快就会发布它。
2021-03-21 20:28:37

您可以使用基于 RecordRTC 的 RecordRTC-together

它支持在单独的文件中一起录制视频和音频。您将需要像ffmpeg在服务器上将两个文件合并为一个的工具

这是一个浏览器解决方案,而不是服务器端。
2021-04-02 20:28:37