在主线程上的chrome块中同时录制视频和音频,导致音频无效

时间:2015-03-23 18:08:51

标签: webrtc web-audio

所以,我认为这是一个相当有趣的,希望不是难以处理的问题。我有一个音频/视频getUserMedia流,我正在Chrome中录制。单独地,曲目记录完美。但是,当试图记录两者时,一个阻塞主线程,另一个阻塞。我知道有办法解决这个问题。 Muaz Khan有一些似乎无阻塞地运行的演示。

通过web audio API录制音频。我正在将音轨传送到处理器节点,该处理器节点将其转换为16b单声道通道并将其流式传输到node.js服务器。

通过通常的画布黑客和Whammy.js录制视频。录制时,视频帧被绘制到画布上,然后生成的图像数据被推入一个帧阵列,稍后由Whammy编码到webm容器中,随后上传到node.js服务器。

然后通过ffmpeg服务器端将两者复用在一起并存储结果。

我到目前为止的想法是:

  • 将一个委托给一个工作线程。不幸的是,就我所知,canvas和stream都是DOM的成员。
  • 在node.js中安装无头浏览器并与客户端建立rtc连接,从而暴露整个流服务器端

Audio Worker implementation最终将解决整个情况。工作组似乎已经停止了公共进展的更新,虽然事情有点拖延了。

有关解决线程阻止的任何建议吗?

网络音频连接:

var context = new AudioContext();
var source = context.createMediaStreamSource(stream);
var node = context.createScriptProcessor(2048, 1, 1);
node.onaudioprocess = audioProcess;
source.connect(node);
node.connect(context.destination);

网络音频处理:

if (!recording.audio) return;
var leftChannel = e.inputBuffer.getChannelData(0);
Socket.emit('record-audio', convertFloat32ToInt16(leftChannel));

视频帧缓冲:

if (recording.video) {
players.canvas.context.fillRect(0, 0, players.video.width, players.video.height);
players.canvas.context.drawImage(players.video.element, 0, 0, players.video.width, players.video.height);
    frames.push({
        duration: 100,
        image: players.canvas.element.toDataURL('image/webp')
    });
    lastTime = new Date().getTime();
    requestAnimationFrame(drawFrame);
} else {
    requestAnimationFrame(getBlob);
}

更新:我已经设法阻止两个操作完全相互阻塞,但它仍然做得足以扭曲我的音频。

2 个答案:

答案 0 :(得分:1)

有一些关键因素可以让目前在Chrome浏览器中成功录制getUserMedia,这是从原始问题附带的有用评论和我自己的经验中收集到的一系列信息中提取的。

  1. 从录制画布收集数据时,编码为jpeg。我一直在尝试使用webp来满足Whammy.js的要求。生成webp dataURI显然是一个循环猪。
  2. 尽可能多地将非DOM操作委派给工作线程。对于任何流/上传操作(例如,通过websockets的音频样本流)来说尤其如此。
  3. 避免requestAnimationFrame作为便于记录画布绘图的方法。这是资源密集型的,正如Aldel指出的那样,如果用户切换标签,则可能会失败。使用setInterval更有效/可靠。它还允许更好的帧速率控制。
  4. 至少对于Chrome,请暂时避免使用客户端AV编码。在服务器端流式传输音频样本和视频帧以进行处理。虽然客户端AV编码库非常酷,但它们看起来还不够高效。
  5. 另外,对于Node.js ffmpeg自动化,我强烈推荐fluent-ffmpeg。特别感谢Benjamin Trent的一些实际例子。

答案 1 :(得分:0)

@aldel是对的。增加bufferSize值会修复它。例如。 bufferSize= 16384;

在Chrome中尝试this demo并记录audio+video。您将听到与720p视频帧并行的清晰录制WAV。

BTW,我同意jesup应该首选MediaRecorder解决方案。

Chromium家伙非常接近,希望M47 / 48能带来MediaRecorder的实施!至少对于视频(vp8)录制。

whammy.js还有基于铬的替代方案: