kasra
kasra

Reputation: 372

Recording and playing sounds in Javascript using MediaSourceExtensions

I'm trying to record and play audio in html using MediaSourceExtensions and MediaRecorder.

here is my code:

async function recordAudio()
{
    let mediaDevices = navigator.mediaDevices;
    let MediaStream = await mediaDevices.getUserMedia({audio: true});
    let mediaRecorder = new MediaRecorder(MediaStream);
    let audio = document.querySelector('audio');
    let chunks = [];
    mediaRecorder.start(400);
    var mediaSource = new MediaSource();
    audio.src = URL.createObjectURL(mediaSource);
    var sourceBuffer = mediaSource.addSourceBuffer("audio/mp4; codecs="mp4a.40.2"");
    mediaRecorder.ondataavailable = (e) => 
    {
        sourceBuffer.appendSourceBuffer(e.data);
    };
}

here are the errors I'm getting(on Firefox):

Uncaught (in promise) DOMException: An attempt was made to use an object that is not, or is no longer, usable (line 11).

what I'm going for is for the voice to be played almost immediately/400ms after the input but I have no idea how to fix it.

Any help would be much appreciated.

Upvotes: 3

Views: 518

Answers (1)

Emiel Zuurbier
Emiel Zuurbier

Reputation: 20954

You can pass the stream directly to the audio element without having it going through the MediaRecorder instance. You can do this by assigning the MediaStream instance to the srcObject of the <audio> element.

audio.srcObject = MediaStream;

If you want to maniuplate the audio and create a controlled delay, then you could use the Web Audio API and manipulate the audio passing through.

In the example below the stream is passed through a DelayNode which can offset the playing time by a given value in seconds.

const audioContext = new AudioContext();

const mediaStreamSource = audioContext.createMediaStreamSource(MediaStream);
const delay = audioContext.createDelay();
const streamDestination = audioContext.createMediaStreamDestination();

delay.delayTime.value = 0.4; // Set delay to 400ms.

mediaStreamSource.connect(delay); // Pass the stream through the delay.
delay.connect(streamDestination); // Pass the delay into a new, modified stream.

Use the Web Audio API stream and set it to the <audio> element..

audio.srcObject = streamDestination.stream;

..or pass the audio signal directly to the speakers.

delay.connect(audioContext.destination);

Upvotes: 1

Related Questions