ui-audiorecorder-html-sample

Reference implementation for recording independent, playable audio chunks in the browser to avoid WebM container header issues.

https://github.com/davidbmar/ui-audiorecorder-html-sample  ·  public  ·  shipped

ui-audiorecorder-html-sample screenshot

What it is

A set of progressive HTML/JS examples demonstrating how to record microphone audio into continuous, independently playable segments. It solves the common Chrome/WebM issue where intermediate fragments from a single MediaRecorder session lack necessary container headers, rendering them unplayable until the stream stops. The solution involves creating a new MediaRecorder instance for each time slice while reusing the same getUserMedia stream.

Features

Quickstart

git clone https://github.com/davidbmar/ui-audiorecorder-html-sample.git
cd ui-audiorecorder-html-sample
python3 -m http.server 8000

Architecture

flowchart TD
    User[User] -->|Clicks Start| UI[HTML UI]
    UI -->|Request Permission| Browser[Browser API]
    Browser -->|MediaStream| RecorderMgr[Recorder Manager]
    RecorderMgr -->|Loop| ChunkRec[New MediaRecorder Instance]
    ChunkRec -->|Audio Data| Blob[Blob Object]
    Blob -->|Store| Storage[(IndexedDB / Local)]
    Blob -->|Optional Upload| S3[S3 Cloud Storage]
    Storage -->|Retrieve| Player[HTML Audio Element]

How it's built

The project is built using vanilla JavaScript (ES5-safe) and HTML. It leverages the MediaRecorder API with a 'stop-and-restart' pattern per chunk rather than using timeslice data events. Advanced steps integrate IndexedDB for local persistence and include logic for generating pre-signed URLs for cloud storage uploads. Visualization is handled via Canvas API for waveform rendering.

How it runs

sequenceDiagram
    participant U as User
    participant UI as HTML Interface
    participant MR as Recorder Manager
    participant Stream as MediaStream
    participant Rec as MediaRecorder (Chunk N)
    participant DB as IndexedDB

    U->>UI: Click Start Recording
    UI->>Stream: getUserMedia({audio: true})
    Stream-->>UI: Return MediaStream
    UI->>MR: startLoop()
    loop For each chunk
        MR->>Rec: new MediaRecorder(stream)
        Rec->>Rec: start()
        Note over Rec: Wait for duration (e.g., 5s)
        Rec->>Rec: stop()
        Rec->>MR: ondataavailable (Blob)
        MR->>DB: saveChunk(blob, index)
        MR->>UI: renderChunk(blob)
        UI->>U: Display <audio> controls
    end

How to apply & reuse

Use this code as a reference pattern when building web-based voice recorders that require immediate playback of segments or reliable upload of partial recordings. It is particularly useful for applications needing to bypass browser-specific demuxer errors associated with fragmented WebM/Ogg streams.

At a glance

CapabilitiesChunked Audio RecordingLocal PersistenceWaveform VisualizationCloud Upload Preparation
Componentsindex-step1-example.htmlstep4-indexdb/app.jsstep4-indexdb/storage.jsaudio-lite.js
TechHTML5JavaScript (ES5)MediaRecorder APIIndexedDBCanvas APIFetch API
Depends onModern Web BrowserMicrophone AccessHTTP Server (for local testing)
Integrates withAWS S3 (via pre-signed URLs)CloudFront (for playback)
PatternsPer-Chunk Recorder PatternStream ReuseClient-Side StorageProgressive Enhancement
Reuse tagsaudio-recordingmedia-recorderwebm-fixindexeddbvanilla-jsbrowser-audio

Repo hygiene

✓ all on main — nothing unmerged.