Record sound of a webaudio api's audio context

2019-09-09 16:54发布

问题:

I am using web audio api in my project. Is there a way to record the audio data that's being sent to webkitAudioContext.destination? .wav files are playing in my browser, so there should be some way to store that data into a (.wav) file . i know this is possible, but not yet find any solution :( recorder.js can help me, but upto now i found it is only recording the microphone live input, is it possible to record my audio(.wav files) with the help of recorder.js? plz help

i am using this sample for recording https://github.com/mattdiamond/Recorderjs

回答1:

As found on the github: var rec = new Recorder(source [, config]), where source is an audio node. So it's up to you to put in the right node. If you play .wav files using <audio>, you can send it to the recorder:

<audio id="audio" src="" controls></audio>

var a = document.getElementById('audio');
var context = new webkitAudioContext();
var sourceNode = context.createMediaElementSource(a);
var rec = new Recorder(sourceNode);


回答2:

I have managed to achieve this through a pure WebAudio solution (no Recorderjs needed). You can see it working fully on my discJS project and use the relevant source file to see how my complete code is working. I imagine this is only relevant to recording WebAudio nodes that you are playing yourself programmatically.

First you will need an HTML <audio> to use as a final destination. In this case I choose to show the controls so that the user may easily download the resulting file.

<audio id='recording' controls='true'></audio>

Now for the Javascript mojo:

const CONTEXT = new AudioContext();
var recorder=false;
var recordingstream=false;

function startrecording(){
  recordingstream=CONTEXT.createMediaStreamDestination();
  recorder=new MediaRecorder(recordingstream.stream);
  recorder.start();
}

function stoprecording(){
  recorder.addEventListener('dataavailable',function(e){
    document.querySelector('#recording').src=URL.createObjectURL(e.data);
    recorder=false;
    recordingstream=false;
  });
  recorder.stop();
}

Now the final glue is that whenever you play an audio source, you also need to connect it to your recording stream:

function play(source){
  let a=new Audio(source);
  let mediasource=CONTEXT.createMediaElementSource(a);
  mediasource.connect(CONTEXT.destination);//plays to default context (speakers)
  mediasource.connect(recordingstream);//connects also to MediaRecorder
  a.play();
}

This is a relatively primitive setup that works fine (tested on Firefox 52 and Chrome 70). For a more proper implementation, see MediaRecorder on MDN.