Media Recording works once, but fails on subsequent dumps to endpoint

31 Views Asked by At

I have the following script being triggered on click by a button. There is some boilerplate for CSRFTokens etc I'm leaving in case I've done something weird there, but the crux of the script is to send an audioBlob (sendData) every thirty seconds to the transcribe endpoint. A 200 is returned, but on a somewhat substantial dely, hence the async so the audio can (in theory) move on to the next chunk of recording.

Right now, however, the script works on the first pass to the endpoint, but on all subsequent passes lead to a corrupt audio file.

Been debugging for a while, any help would be appreciated.

    let audioChunks = [];
    let isRecording = false;
    let intervalId;
    const retryLimit = 1;
    let retryCount = 0;
    let wakeLock = null;


    function getCSRFToken() {
      return document.querySelector("input[name=csrfmiddlewaretoken]").value;
    }

    function getQueryParam(param) {
      const urlParams = new URLSearchParams(window.location.search);
      return urlParams.get(param);
    }

    async function sendData(audioBlob) {
      try {
        const formData = new FormData();
        formData.append("file", audioBlob, "audio.wav");
        const session_id = getQueryParam("session_id"); // Get session_id from URL
        if (session_id) {
          formData.append("session_id", session_id); // Add session_id to the formData
        }
        const response = await fetch("transcribe", {
          method: "POST",
          headers: {
            "X-CSRFToken": getCSRFToken(), // Add CSRF token to the request headers
          },
          body: formData,
        });
        if (!response.ok) throw new Error("Upload failed");
        retryCount = 0; // Reset retry count on successful upload
      } catch (error) {
        if (retryCount < retryLimit) {
          retryCount++;
          sendData(audioBlob); // Retry sending data
        } else {
          console.error("Failed to upload after retries:", error);
          retryCount = 0; // Reset retry count
        }
      }
    }

    async function initiateMediaRecorder(stream) {
      mediaRecorder = new MediaRecorder(stream);
      mediaRecorder.ondataavailable = (event) => {
        if (event.data.size > 0) {
          audioChunks.push(event.data);
        }
      };
      mediaRecorder.onstop = async () => {
        const audioBlob = new Blob(audioChunks, { type: "audio/wav" });
        sendData(audioBlob); // Send the last chunk of audio
        audioChunks = []; // Reset chunks for the next recording
      };
      mediaRecorder.start();

      intervalId = setInterval(async () => {
        mediaRecorder.requestData(); // Get current audio chunk
        if (audioChunks.length) {
          const currentChunks = [...audioChunks]; // Copy current chunks
          audioChunks = []; // Clear the chunks for the next interval
          const audioBlob = new Blob(currentChunks, { type: "audio/wav" });
          await sendData(audioBlob); // Wait for sendData to complete
        }
      }, 30000); // 30 seconds
    }

    async function toggleRecording() {
      if (!isRecording) {
        if (!navigator.mediaDevices) {
          console.error("MediaDevices API not supported");
          return;
        }
        try {
          const stream = await navigator.mediaDevices.getUserMedia({
            audio: true,
          });
          initiateMediaRecorder(stream);
          document.getElementById("record_audio").textContent =
            "Stop Recording";
          document.getElementById("record_audio").className =
            "btn btn-lg btn-danger";
          isRecording = true;
    
          // Request a wake lock
          try {
            wakeLock = await navigator.wakeLock.request('screen');
            console.log('Wake Lock is active');
          } catch (err) {
            console.error(`${err.name}, ${err.message}`);
          }
    
        } catch (error) {
          console.error("Error accessing audio device:", error);
        }
      } else {
        mediaRecorder.stop();
        clearInterval(intervalId);
        document.getElementById("record_audio").textContent = "Start Recording";
        document.getElementById("record_audio").className =
          "btn btn-lg btn-outline-primary";
        isRecording = false;
    
        // Release the wake lock
        if (wakeLock !== null) {
          wakeLock.release().then(() => {
            console.log('Wake Lock was released');
            wakeLock = null;
          });
        }
      }
    }```
0

There are 0 best solutions below