【问题标题】:new MediaRecorder(stream[, options]) stream can living modify?new MediaRecorder(stream[, options]) 流可以修改吗?
【发布时间】:2020-03-15 08:38:51
【问题描述】:

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())
    }
    
    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
    }

【问题讨论】:

    标签: mediarecorder getusermedia audiocontext web-mediarecorder mediarecorder-api


    【解决方案1】:

    不,我们仍然无法录制在录制开始后轨道发生更改的 MediaStream,这样做将 stop() MediaRecorder。 Here is a very related Q/A 更多的是关于录制视频。

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

    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>

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

    【讨论】:

    • 可以混音吗?
    • @zhishaofei3 是的,当然,您可以将多个音频节点连接到您的目标流,它们都会被记录下来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-05
    • 2013-09-23
    • 1970-01-01
    • 2011-01-28
    • 2019-08-08
    • 2020-01-02
    相关资源
    最近更新 更多