Playback Using Howler.js and Transcription Timing Logic

Full Howler Transcribe App Integration – Interactive Transcription UI

Welcome to the final lesson of this course! So far, you’ve built a robust foundation:

  • In the first unit, you implemented audio playback using Howler.js and controlled it through backend routes.
  • In the second unit, you learned how to clip audio segments and transcribe them using the OpenAI Whisper API.

Now, it’s time to bring everything together into a seamless browser experience. In this lesson, you'll learn how to:

  • Track when the user starts and stops playback
  • Send the correct audio segment to the backend
  • Display the transcription result in the browser

Let’s build the full interactive workflow!


What You’ll Learn

By the end of this lesson, you’ll be able to:

  • Capture the start and stop time of playback using Howler.js
  • Send the segment info to your backend
  • Transcribe and display the result directly in the frontend

This is the final version of your app. After this, you’ll have a fully working client-server audio transcription tool.


Tracking Start and Stop Times

To capture an audio segment, we need to know when the user wants to begin and end recording. We’ll use Howler.js’s seek() method to get the current playback position in seconds.

📌 `startRecording()`

function startRecording() {
  if (!currentSound || !isPlaying) {
    alert('Start playback before recording.');
    return;
  }

  playbackStartSec = currentSound.seek();
  console.log(`⏺️ Recording started at: ${playbackStartSec.toFixed(2)} sec`);
}

Explanation:

  • This function is triggered when the user clicks Start Recording.
  • It checks if the audio is playing and captures the current playback time.
  • This becomes the segment start.

📌 `stopRecordingAndTranscribe()`

async function stopRecordingAndTranscribe() {
  if (!currentSound || playbackStartSec === null) {
    alert("Please start recording during audio playback.");
    return;
  }

  const playbackEndSec = lastKnownPosition;
  const duration = playbackEndSec - playbackStartSec;

  if (duration <= 0) {
    alert("Invalid segment. Make sure playback has progressed.");
    return;
  }

  const filePath = document.getElementById('audioFile').value;
  if (!filePath) {
    alert('Please select an audio file.');
    return;
  }

  const resultPanel = document.getElementById("transcriptionResult");
  const textArea = document.getElementById("transcriptionText");

  resultPanel.classList.remove("hidden");
  textArea.textContent = "⏳ Transcribing selected audio segment...";

  try {
    const response = await fetch("/transcribe", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        filePath,
        start: playbackStartSec,
        duration
      })
    });

    const { transcription } = await response.json();
    textArea.textContent = transcription || "(No text returned)";
  } catch (err) {
    console.error("❌ Transcription failed:", err);
    alert("Transcription failed. See console.");
  }

  playbackStartSec = null;
}

Explanation: The stopRecordingAndTranscribe function is the final step in capturing and transcribing a user-selected audio segment. It’s designed to coordinate timing logic, perform input validation, and initiate communication with the backend transcription route—all within a user-friendly interface.

Let’s break it down:

  • When the user clicks Stop + Transcribe, the current playback position is used as the segment end.
  • We compute the duration and send the segment details to /transcribe.
  • Once the backend returns the text, it’s displayed in the UI.
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal