【问题标题】:In webrtc is it possible to get video frames without using canvas?在 webrtc 中是否可以在不使用画布的情况下获取视频帧?
【发布时间】:2021-06-22 06:09:57
【问题描述】:

我的实际项目是使用webrtc开发一个视频通话应用程序并为NDI SDK传输视频音频帧,NDI输入应该以帧为单位。为此,现在我使用画布完成了此操作,但延迟很高。是否可以直接从摄像头直接获取帧,或者有其他方法将流转为帧?

这是我现在获取帧的示例代码(var frame = this.ctx1.getImageData(0, 0, this.width, this.height);)

var processor = {
  timerCallback: function() {
    if (this.video.paused || this.video.ended) {
      return;
    }
    this.computeFrame();
    var self = this;
    setTimeout(function () {
      self.timerCallback();
    }, 16); // roughly 60 frames per second
  },

  doLoad: function() {
    this.video = document.getElementById("my-video");
    this.c1 = document.getElementById("my-canvas");
    this.ctx1 = this.c1.getContext("2d");
    var self = this;

    this.video.addEventListener("play", function() {
      self.width = self.video.width;
      self.height = self.video.height;
      self.timerCallback();
    }, false);
  },

  computeFrame: function() {
    this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
    var frame = this.ctx1.getImageData(0, 0, this.width, this.height);
    var l = frame.data.length / 4;

    for (var i = 0; i < l; i++) {
      var grey = (frame.data[i * 4 + 0] + frame.data[i * 4 + 1] + frame.data[i * 4 + 2]) / 3;

      frame.data[i * 4 + 0] = grey;
      frame.data[i * 4 + 1] = grey;
      frame.data[i * 4 + 2] = grey;
    }
    this.ctx1.putImageData(frame, 0, 0);

    return;
  }
};

【问题讨论】:

  • 此视频是否来自本地摄像头?或者,远端?您如何与 NDI SDK 通信?在任何情况下,请考虑使用requestAnimationFrame() 而不是您的计时器。如果您正在制作自己的浏览器包装器,您可能会挂钩正在绘制视频的任何内容,并将该数据直接发送到 NDI SDK。几年前我已经看到过类似的代码,但现在找不到了。我认为标牌或记分牌公司已经开源了他们的 Chromium 构建......
  • 本地相机本身。从本地摄像头到必须获取帧,取决于这个过程,我必须决定如何将帧传输到 NDI,无论是作为远程用户还是套接字本身。谢谢@Brad,我现在正在检查标牌和记分牌。
  • 你需要什么格式? Possible duplicate?
  • @arunna 这就是我的想法:github.com/daktronics/cef-mixer 不是你要找的东西,但是如果你想转储整个东西,可以调查一下。但实际上,为什么不直接将相机连接到 NDI 呢?如果你需要一些特别的东西,也许可以通过 GStreamer 或其他东西。
  • 所以 WebCodecs 可能确实是一个解决方案,但我自己不知道 NDI,我认为你应该先考虑 Brad 的建议。

标签: javascript webrtc


【解决方案1】:

我认为没有其他方法可以实时访问(和编辑)视频帧。

但正如this answer 中所建议的那样,您可以使用(仅在 chrome 上)requestVideoFrameCallback API,而不是使用 requestAnimationFrame 函数。正如here 所说:

requestVideoFrameCallback() 方法允许 Web 作者注册一个回调,该回调在新视频帧发送到合成器时在渲染步骤中运行。这旨在允许开发人员对视频执行高效的每视频帧操作,例如视频处理和画布绘制、视频分析、[...]

另一方面,正如this post 中所说,画布操作对 CPU 的负担很大。要简单地编辑视频显示,您应该尝试使用一些 CSS3 转换。

【讨论】:

    【解决方案2】:

    您可以创建ImageCapture 对象并使用takePhoto 方法,而不是将MediaStream 分配给画布,请参阅

    https://developer.mozilla.org/en-US/docs/Web/API/ImageCapture

    对于音频,您可以使用: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorderrequestData方法和ondataavailable

    【讨论】:

    • 在这种情况下,我们不会得到正确的音频?
    • 此 API 不适用于流。它专为模拟相机的网页而设计。照片拍摄的工作方式不同,并且对拍摄照片应用不同的约束。
    • @brad 为什么你有这样的信息,你可以从上面的链接中查看示例:googlechrome.github.io/samples/image-capture/…,它按预期工作。
    • @mjpolak 我检查了示例这行 (imageCapture.grabFrame()) 是否提供帧?
    • 检查我的答案,我不建议使用grabFrame,而是使用takePhoto,它会返回带有图像数据的Blob
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 2021-09-07
    • 2013-05-06
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    相关资源
    最近更新 更多