Microphone capture for in-browser Python (Pyodide / JupyterLite) via the Web Audio API.
Project description
browseraudio
Microphone capture for in-browser Python — Pyodide, JupyterLite, thebe-lite — via the browser's Web Audio API.
When Python runs in the browser it usually lives in a Web Worker, where the
Web Audio API and getUserMedia don't exist and the DOM is out of reach. So
the classic audio stack (sounddevice → PortAudio) can't run, and libraries
that depend on it fall back to "not available" stubs. browseraudio bridges
that gap: it captures audio on the browser's main thread (through a tiny
anywidget frontend) and hands the samples back to the
Python kernel over the widget comm channel.
Status: v0 — recording only, and a foundation to build on. The full round-trip is proven end-to-end under thebe-lite (Pyodide 0.27.7): a 1-second capture returned a float32 array, shape
(48000, 1)at 48 kHz, with real signal. See the roadmap for what's next.
Install
pip install browseraudio # in a normal environment
In a browser kernel, install at runtime with micropip:
import micropip
await micropip.install("browseraudio")
Use
The recording finishes after you click the button, so read the result in a separate cell from the one that shows the widget:
from browseraudio import Recorder
rec = Recorder(duration=3.0)
rec # shows a "● Record 3s" button — click it, then speak
After it captures, an inline player appears so you can hear the take. Then, in the next cell, use the audio:
rec.samples # float32 ndarray, shape (n_frames, 1)
rec.sample_rate # e.g. 48000
Why two cells? A single-cell
await record()can't work in Jupyter/thebe — the kernel doesn't process the widget's reply while that same cell is still running, so the recording would never arrive. Display in one cell, use it in the next.
With pyquist installed, get an Audio
object directly:
clip = rec.to_pyquist() # pyquist.Audio
How it works
main thread (browser) worker (Python kernel)
───────────────────── ──────────────────────
getUserMedia → AudioContext ──comm (base64 float32)──► numpy float32
(anywidget frontend) Recorder.samples
The kernel→page direction (displaying the widget) and the page→kernel direction (sending samples back) both ride the standard Jupyter widget comm, which works in JupyterLite and thebe-lite.
Roadmap
- Playback — push a buffer to a main-thread
AudioContext(play). - AudioWorklet backend — replace the deprecated
ScriptProcessorNodeused in v0. - sounddevice-compatible facade — expose
play/rec/wait/query_devicesso a library like pyquist works in the browser unchanged (a realsounddevicereplacement, not a stub). - Streaming (stretch) — generator → ring buffer → AudioWorklet. Bounded by
the browser: Python can't run in the audio thread, and
SharedArrayBufferneeds cross-origin-isolation (COOP/COEP) headers.
Caveats
- Recording needs HTTPS (or
localhost), a user gesture (the button), and the browser's microphone-permission prompt. - v0 transfers samples as base64 over the comm — simple and robust; binary comm buffers would be more efficient.
- v0 uses
ScriptProcessorNode(deprecated but universally supported).
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file browseraudio-0.1.0.tar.gz.
File metadata
- Download URL: browseraudio-0.1.0.tar.gz
- Upload date:
- Size: 7.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c47acac4f2930857ab6ce9516f5e9ad15ad55f1515ccfc8e449bd6753235aaf5
|
|
| MD5 |
c9014f84cd5da663eadc89a940343e2b
|
|
| BLAKE2b-256 |
dfa6cfb48526e6b7eb8f4935be69b650ea8f0ef151446c58f6fc67144f8c15b6
|
File details
Details for the file browseraudio-0.1.0-py3-none-any.whl.
File metadata
- Download URL: browseraudio-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d5495d3e8437a6fc1042d1b07cd8b73dce87be8ddfe98776e6fb0b5cb838423
|
|
| MD5 |
979079e07f19a10cc02a5c7993f77b88
|
|
| BLAKE2b-256 |
98e83695aa5ab5c485b31ecd659a868fc2b60269f858cf365dc237632c8c1104
|