I am trying to create individual chunks of a MediaRecorder stream and be able to play each chunk individually as it is recording. To clarify my question I have a sample website
Here's the code, I create a block object whenever I receive the dataavailable
event. This event is fired because I pass in a timesplit argument into mediaRecorder.start(2000)
so that the event is fired after collecting 2 seconds of data.
const container = document.querySelector(".container");
let count = 0;
function Block(chunk, index) {
const div = document.createElement("div");
div.className = "block";
div.onclick = () => {
const audioUrl = URL.createObjectURL(chunk);
const audio = new Audio(audioUrl);
audio.play();
};
div.innerText = index;
container.append(div);
}
const recordAudio = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream);
mediaRecorder.addEventListener("dataavailable", (event) => {
new Block(event.data, count);
count += 1;
});
mediaRecorder.start(2000);
};
recordAudio();
Out of all the chunks, only the first chunk can be played. How to I play the other chunks?
update 1 I tried grouping the chunks together and I created a helper function to do that that you can try in the console.
If I group the first chunk and any other chunk, the audio becomes playable. For example, play(3)
will create a blob of the first chunk (index 0) and the chunk at index 3.
Here's the play function (allChunks
is an array containing all the audio chunks)
const play = (idx) => {
const audioBlob = new Blob([allChunks[0], allChunks[idx]]);
const audioUrl = URL.createObjectURL(audioBlob);
const audio = new Audio(audioUrl);
audio.play();
};
I'm suspecting that the first audio chunk contains meta tags that if I added to the other audio chunks, I would be able to play them individually.
Update 2 To test out my theory to the above, when users click on a block I created a fileReader object so I can see the chunk data.
div.onclick = () => {
const audioUrl = URL.createObjectURL(chunk);
const audio = new Audio(audioUrl);
audio.play();
const reader = new FileReader();
reader.readAsDataURL(chunk);
reader.onload = () => {
console.log(reader.result);
};
};
The playable chunk and non-playable chunk looks like very similar base64 encoded strings.