Introduction
Recording audio from a web page sounds like it needs JavaScript wizardry — and it does, but someone else already wrote it. The streamlit-audio-recorder component hands you a microphone button in one line, and your Python code receives raw WAV bytes. This app wraps that in a full toolkit: record, visualize the waveform, play it back, and download the file.
It is the audio counterpart to the webcam photo booth — both turn browser hardware into Python data — and it pairs naturally with the text-to-speech app for a record-and-compare workflow.
Features
st.audio player for instant review.Prerequisites
pip install streamlit streamlit-audio-recorder matplotlib numpyStep 1: Create the Script
Save as audio_recorder.py:
import streamlit as st
import numpy as np
import io
import wave
import matplotlib.pyplot as plt
from audio_recorder_streamlit import audio_recorder
st.set_page_config(page_title="Audio Recorder", page_icon="🎙️")
st.title("🎙️ Audio Recorder & Visualizer")
audio_bytes = audio_recorder(
text="Click to record",
recording_color="#e63946",
neutral_color="#10b981",
icon_name="microphone",
key="mic",
)
if audio_bytes:
# Parse the WAV bytes for stats
with wave.open(io.BytesIO(audio_bytes), "rb") as wf:
frames = wf.getnframes()
rate = wf.getframerate()
channels = wf.getnchannels()
duration = frames / rate
samples = np.frombuffer(wf.readframes(frames), dtype=np.int16)
c1, c2, c3 = st.columns(3)
c1.metric("Duration", f"{duration:.1f}s")
c2.metric("Sample rate", f"{rate} Hz")
c3.metric("Size", f"{len(audio_bytes) / 1024:.0f} KB")
# Waveform
fig, ax = plt.subplots(figsize=(9, 3))
step = max(1, len(samples) // 20000) # downsample for plotting
ax.plot(samples[::step], linewidth=0.4, color="#10b981")
ax.set_xlabel("Sample")
ax.set_ylabel("Amplitude")
ax.set_ylim(-32768, 32767)
ax.axis("off")
st.pyplot(fig)
st.audio(audio_bytes, format="audio/wav")
st.download_button("⬇️ Download WAV", audio_bytes, "recording.wav", "audio/wav")
else:
st.info("Click the microphone to start recording.")Step 2: Run the App
streamlit run audio_recorder.pyGrant microphone permission when the browser asks, record a sentence, and watch the waveform draw itself.
How It Works
The component handles the hard part — MediaRecorder in the browser — and hands your script a bytes object containing a complete WAV file. Everything after that is standard Python: the wave module parses the header (sample rate, channel count, frame count), and np.frombuffer turns the PCM payload into an int16 array where each value is one amplitude sample.
The waveform plot includes a subtle but important trick: downsampling. A 30-second recording at 44.1 kHz is 1.3 million points; matplotlib plotting all of them is slow and visually identical to plotting every 66th. samples[::step] takes an even slice — the same array-slicing idea that keeps the stock dashboard responsive.
Silence detection is one numpy expression away: np.abs(samples).mean() gives average amplitude — low values mean you recorded silence, which makes a friendly warning.
Common Errors & Fixes
localhost or HTTPS; opening the app via a LAN IP will silently fail.pydub.streamlit-audio-recorder, imported as audio_recorder_streamlit.Key Concepts
What to Try Next
numpy.fft — frequency bars instead of a waveform.FAQ
Where does the audio go?
Nowhere — the bytes flow browser → Streamlit server → your script in memory. Nothing is uploaded to third parties, unlike most online recorders.
Can I record longer than a minute?
Yes, though the component buffers in memory. For hour-long capture, write chunks to disk incrementally or use dedicated recording software.
Why WAV instead of MP3?
WAV is uncompressed and trivially parseable — no decoding libraries needed. Convert to MP3 with pydub + ffmpeg if size matters for downloads.