Delay before MediaRecorder starts recording audio in Firefox
Asked Answered
F

0

7

In a bare-bones demo, I find that there is a 1.5 second delay before MediaRecorder starts recording audio, on Firefox only.

Please find below a snippet that works well with MediaRecorder on Chrome, Opera and Edge. Apparently MediaRecorder is blocked when the snippet runs on Stack Overflow, so you can't test it here. You can find the same code on GitHub, with a demo here.

On Safari, there is also a delay, but for a different and more manageable reason: the promise that eventually resolves to a user media stream takes longer than in other browsers, but once the stream is available, recording can begin immediately. It is therefore possible to indicate to the end-user that recording has started.

On Firefox, the user media stream is available immediately, and an icon appears in the menu bar immediately in the menu bar to indicate that the microphone is busy. It seems that the stream starts flowing, but there is no data from the microphone for over a second. Recording only starts after about 1.5 seconds, when a second (yellow) icon appears in the menu bar. The recorded audio begins with 1.5 seconds of silence.

Is this due to a mistake in the way I am using MediaRecorder, or do I need to take some specific action on Firefox?

const startRecording = document.getElementById("startRecording")
const stopRecording = document.getElementById("stopRecording")
const playBack = document.getElementById("playBack")
const feedback = document.getElementById("feedback")

startRecording.addEventListener("click", startRecorder, false)
stopRecording.addEventListener("click", stopRecorder, false)
playBack.addEventListener("click", () => audio.play(), false)


const audio = new Audio()
const streams = []

let startTime
let mediaRecorder
let chunks


async function startRecorder() {
  navigator.mediaDevices
  .getUserMedia({ audio: true })
  .then(onSuccess, onError)
}


function onSuccess(stream) {
  startTime = new Date()
  // The System "recording" icon appears now there is a stream
  streams.push(stream)

  const mimeType = "audio/webm"
  mediaRecorder = new MediaRecorder(stream) //, { mimeType })
  chunks = [];

  mediaRecorder.onstop = saveRecording
  mediaRecorder.ondataavailable = ({data}) => {
    chunks.push(data);
  };

  mediaRecorder.start()
  showStartTime()
};


function onError(error) {
  alert(`An error occured with getUserMedia():
  ${error}`);
};


function stopRecorder() {
  if (!mediaRecorder) {
    return
  }

  mediaRecorder.stop()
  stopAllTracks()
  showEndTime()
}


function stopAllTracks() {
  // Switch off the System "recording" icon
  streams.forEach( stream => {
    stream.getTracks() // get all tracks from the MediaStream
      .forEach( track => track.stop() ); // stop each of them
  })
  streams.length = 0
}


function saveRecording() {
  const type = mediaRecorder.mimeType
  const blob = new Blob(chunks, { type })
  const src = window.URL.createObjectURL(blob)
  // Play the recording
  audio.src = src
  audio.play()
}



function showStartTime() {
  const text = `Started: ${startTime.toLocaleTimeString("en-gb") + "." + startTime.getMilliseconds()}`
  console.log("text:", text);
  feedback.textContent = text
}


function showEndTime(){
  const endTime = new Date()
  const duration = (endTime - startTime) / 1000
  const text = `
Ended:   ${endTime.toLocaleTimeString("en-gb") + "." + endTime.getMilliseconds()}
Duration:       ${duration} seconds`

  feedback.textContent += text
}
  <button id="startRecording">Start Recording</button>
  <button id="stopRecording">Stop Recording</button>
  <button id="playBack">Play Back</button>
  <pre id="feedback"></pre>
Fixed answered 11/2 at 11:32 Comment(3)
Other than recommending using the web app on a different browser, no, not yet.Fixed
alrighty glad im not the only one here, thought i was going crazy. Tried in safari and doesn't have the same issue.Denysedenzil
I'm experiencing a similar issue. When I use recorder.start(1000), occasionally (but quite frequently), the ondatavailable callback initially gets called with a first 130-byte payload, followed by 3 empty payloads (i.e., 0 bytes), and then starts recording. This does not happen with Chrome and Safari.Legra

© 2022 - 2024 — McMap. All rights reserved.