如何为 Chrome 中从 MediaRecorder 录制的音频添加预定义长度?

新手上路,请多包涵

我正在用内置的 MediaRecorder 替换 RecordRTC,以便在 Chrome 中录制音频。然后使用音频 api 在程序中播放录制的音频。我无法使 audio.duration 属性正常工作。它说

如果视频(音频)是流式传输且没有预定义长度,则返回“Inf”(无限)。

使用 RecordRTC,我必须使用 ffmpeg_asm.js 将音频从 wav 转换为 ogg。我的猜测是 RecordRTC 设置预定义音频长度的过程中的某个地方。有没有办法使用 MediaRecorder 设置预定义长度?

原文由 Tom Chen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 892
2 个回答

这是一个 chrome 错误

FF 确实公开了录制媒体的持续时间,如果您确实将录制媒体的 currentTime 设置为超过其实际 duration ,则该属性在 chrome 中可用…

 var recorder,
  chunks = [],
  ctx = new AudioContext(),
  aud = document.getElementById('aud');

function exportAudio() {
  var blob = new Blob(chunks);
  aud.src = URL.createObjectURL(new Blob(chunks));

  aud.onloadedmetadata = function() {
    // it should already be available here
    log.textContent = ' duration: ' + aud.duration;
    // handle chrome's bug
    if (aud.duration === Infinity) {
      // set it to bigger than the actual duration
      aud.currentTime = 1e101;
      aud.ontimeupdate = function() {
        this.ontimeupdate = () => {
          return;
        }
        log.textContent += ' after workaround: ' + aud.duration;
        aud.currentTime = 0;
      }
    }
  }
}

function getData() {
  var request = new XMLHttpRequest();
  request.open('GET', 'https://upload.wikimedia.org/wikipedia/commons/4/4b/011229beowulf_grendel.ogg', true);
  request.responseType = 'arraybuffer';
  request.onload = decodeAudio;
  request.send();
}

function decodeAudio(evt) {
  var audioData = this.response;
  ctx.decodeAudioData(audioData, startRecording);
}

function startRecording(buffer) {

  var source = ctx.createBufferSource();
  source.buffer = buffer;
  var dest = ctx.createMediaStreamDestination();
  source.connect(dest);

  recorder = new MediaRecorder(dest.stream);
  recorder.ondataavailable = saveChunks;
  recorder.onstop = exportAudio;
  source.start(0);
  recorder.start();
  log.innerHTML = 'recording...'
  // record only 5 seconds
  setTimeout(function() {
    recorder.stop();
  }, 5000);
}

function saveChunks(evt) {
  if (evt.data.size > 0) {
    chunks.push(evt.data);
  }

}

// we need user-activation
document.getElementById('button').onclick = function(evt){
  getData();
  this.remove();
}
 <button id="button">start</button>
<audio id="aud" controls></audio><span id="log"></span>

所以这里的建议是给 错误报告 加注星标,这样 Chromium 的团队就会花一些时间来修复它,即使这个解决方法可以解决问题……

原文由 Kaiido 发布,翻译遵循 CC BY-SA 4.0 许可协议

感谢@Kaiido 识别错误并提供工作修复。

我准备了一个名为 get-blob-duration 的 npm 包,你可以安装它来获得一个很好的 Promise 包装函数来完成肮脏的工作。

用法如下:

 // Returns Promise<Number>
getBlobDuration(blob).then(function(duration) {
  console.log(duration + ' seconds');
});

或者 ECMAScript 6:

 // yada yada async
const duration = await getBlobDuration(blob)
console.log(duration + ' seconds')

原文由 Ezekiel Victor 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题