new MediaRecorder(stream[, options]) 流可以修改吗? [英] new MediaRecorder(stream[, options]) stream can living modify?

查看:85
本文介绍了new MediaRecorder(stream[, options]) 流可以修改吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

new MediaRecorder(stream[, options]);

我想记录用户的摄像头和音频

我需要在录音时将 song.mp3 混合到音轨中.

并导出视频文件以通过链接下载.

但是MediaRecorder的第一个参数流可以修改吗?

但是当我使用 recoder.stop()

提示错误:无法在MediaRecorder"上执行stop":MediaRecorder 的状态为inactive".

我的代码:

 function getFileBuffer(filepath) {return fetch(filepath, {method: 'GET'}).then(response => response.arrayBuffer())}函数 mp3play() {getFileBuffer('song.mp3').then(buffer => context.decodeAudioData(buffer)).then(缓冲区=> {控制台日志(缓冲区)const 源 = context.createBufferSource()源.缓冲区 = 缓冲区让音量 = context.createGain()音量.增益.值 = 1source.connect(音量)dest = context.createMediaStreamDestination()音量.connect(dest)//volume.connect(context.destination)源.开始(0)const _audioTrack = stream.getAudioTracks();如果(_audioTrack.length > 0){_audioTrack[0].stop();stream.removeTrack(_audioTrack[0]);}////console.log(dest.stream)//console.log(dest.stream.getAudioTracks()[0])//stream.addTrack(dest.stream.getAudioTracks()[0])})}功能开始录音(){记录器 = 新媒体记录器(流,{mimeType: '视频/网络'})recorder.start()stopBtn.removeAttribute('禁用')startBtn.disabled = true}

解决方案

不,我们仍然无法录制在录制开始后轨道发生变化的 MediaStream,这样做将 stop() MediaRecorder.这是一个非常相关的问答,更多的是关于录制视频.

但可以做的是创建一种合并 MediaStream.
音频更容易,而且因为您已经在使用 WebAudio API:您需要做的就是创建另一个 MediaStreamDestination 节点,并连接/断开不同的源.

const base = "https://upload.wikimedia.org/wikipedia/en/d/";常量网址 = ["d3/Beach_Boys_-_Good_Vibrations.ogg","dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg"].map( url => base + url );const context = new AudioContext();const button = document.querySelector('button');button.onclick = async() =>{button.disabled = true;上下文.resume();const audiobuffers = await Promise.all( urls.map( fetchAsAudioBuffer ) );button.remove();const streamNode = context.createMediaStreamDestination();const 流 = streamNode.stream;const recorder = new MediaRecorder(stream);常量块 = [];recorder.ondataavailable = evt =>块.push(evt.data);recorder.onstop = evt =>exportAudio(new Blob(chunks));document.getElementById('record-stopper').onclick = evt =>{recorder.stop();current_source.stop( 0 );};让 current_index = 0;让 current_source = null;document.getElementById( 'switcher' ).onclick = switchAudioSource;switchAudioSource();录音机开始();功能 switchAudioSource() {如果(当前来源){current_source.stop( 0 );}current_index = (current_index + 1) % audiobuffers.length;current_source = context.createBufferSource();current_source.buffer = audiobuffers[ current_index ];current_source.loop = true;current_source.connect(streamNode);current_source.connect( context.destination );current_source.start( 0 );}};函数 exportAudio( blob ) {const aud = new Audio( URL.createObjectURL( blob ) );aud.controls = true;document.body.prepend(aud);}异步函数 fetchAsAudioBuffer( url ) {const buf = 等待 fetchAsBuffer( url );返回 context.decodeAudioData( buf );}异步函数 fetchAsBuffer( url ) {const resp = await fetch( url );返回 resp.arrayBuffer();}

button+.recording-controls,音频+.录音控制{显示:无;}

<button>begin</button><div class="recording-controls"><label>录音...</label><button id="switcher">切换音频源</button><button id="record-stopper">停止录制</button>

对于意味着录制 CanvasMediaStreamTrack 并在源上绘制不同视频流的视频,但这样做通常会降低很多质量...

new MediaRecorder(stream[, options]);

I want record the user camera and audio

I need mixing the song.mp3 to the audio track in recording.

and result export a video file to download by link.

But the MediaRecorder first params stream can living modify ?

But When I use recoder.stop()

It tips error: Failed to execute 'stop' on 'MediaRecorder': The MediaRecorder's state is 'inactive'.

My code:

    function getFileBuffer(filepath) {
      return fetch(filepath, {method: 'GET'}).then(response => response.arrayBuffer())
    }
    
    function mp3play() {
      getFileBuffer('song.mp3')
      .then(buffer => context.decodeAudioData(buffer))
      .then(buffer => {
        console.log(buffer)
        const source = context.createBufferSource()
        source.buffer = buffer
        let volume = context.createGain()
        volume.gain.value = 1
        source.connect(volume)
        dest = context.createMediaStreamDestination()
        volume.connect(dest)
        // volume.connect(context.destination)
        source.start(0)
    
        const _audioTrack = stream.getAudioTracks();
        if (_audioTrack.length > 0) {
          _audioTrack[0].stop();
          stream.removeTrack(_audioTrack[0]);
        }
        //
        // console.log(dest.stream)
        // console.log(dest.stream.getAudioTracks()[0])
        // stream.addTrack(dest.stream.getAudioTracks()[0])
      })
    }
    
    function startRecording() {
      recorder = new MediaRecorder(stream, {
        mimeType: 'video/webm'
      })
      recorder.start()
      stopBtn.removeAttribute('disabled')
      startBtn.disabled = true
    }

解决方案

No we still can't record a MediaStream whose tracks are changed after the recording began, doing so will stop() the MediaRecorder. Here is a very related Q/A which was more about recording video.

What can be done though is to create a kind of merger MediaStream.
It's way easier with audio, moreover since you are already using the WebAudio API: all you need to do is to create an other MediaStreamDestination node, and connect / disconnect the different sources.

const base = "https://upload.wikimedia.org/wikipedia/en/d/";
const urls = [
  "d3/Beach_Boys_-_Good_Vibrations.ogg",
  "dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg"
].map( url => base + url );
const context = new AudioContext();
const button = document.querySelector( 'button' );

button.onclick = async () => {
  button.disabled = true;
  context.resume();
  const audiobuffers = await Promise.all( urls.map( fetchAsAudioBuffer ) );
  button.remove();
  const streamNode = context.createMediaStreamDestination();
  const stream = streamNode.stream;
  
  const recorder = new MediaRecorder( stream );
  const chunks = [];
  recorder.ondataavailable = evt => chunks.push( evt.data );
  recorder.onstop = evt => exportAudio( new Blob( chunks ) );
  document.getElementById( 'record-stopper' ).onclick = evt => {
    recorder.stop();
    current_source.stop( 0 );
  };

  let current_index = 0;
  let current_source = null;
  
  document.getElementById( 'switcher' ).onclick = switchAudioSource;
  
  switchAudioSource();
  recorder.start();

  function switchAudioSource() {
    if( current_source ) {
      current_source.stop( 0 );
    }
    current_index = (current_index + 1) % audiobuffers.length;
    current_source = context.createBufferSource();
    current_source.buffer = audiobuffers[ current_index ];
    current_source.loop = true;
    current_source.connect( streamNode );
    current_source.connect( context.destination );
    current_source.start( 0 );
  }

};

function exportAudio( blob ) {
  const aud = new Audio( URL.createObjectURL( blob ) );
  aud.controls = true;
  document.body.prepend( aud );
}

async function fetchAsAudioBuffer( url ) {
  const buf = await fetchAsBuffer( url );
  return context.decodeAudioData( buf );
}
async function fetchAsBuffer( url ) {
  const resp = await fetch( url );
  return resp.arrayBuffer();
}

button+.recording-controls,
  audio+.recording-controls {
    display: none;
  }

<button>begin</button>
<div class="recording-controls">
  <label>Recording...</label>
  <button id="switcher">Switch Audio Sources</button>
  <button id="record-stopper">Stop Recording</button>
</div>

For video that would imply recording a CanvasMediaStreamTrack and drawing the different video streams on the source <canvas>, but we generally loose a lot of quality doing so...

这篇关于new MediaRecorder(stream[, options]) 流可以修改吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆