Skip to main content

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 ScriptProcessorNode used in v0.
  • sounddevice-compatible facade — expose play / rec / wait / query_devices so a library like pyquist works in the browser unchanged (a real sounddevice replacement, not a stub).
  • Streaming (stretch) — generator → ring buffer → AudioWorklet. Bounded by the browser: Python can't run in the audio thread, and SharedArrayBuffer needs 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

browseraudio-0.1.0.tar.gz (7.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

browseraudio-0.1.0-py3-none-any.whl (8.3 kB view details)

Uploaded Python 3

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

Hashes for browseraudio-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c47acac4f2930857ab6ce9516f5e9ad15ad55f1515ccfc8e449bd6753235aaf5
MD5 c9014f84cd5da663eadc89a940343e2b
BLAKE2b-256 dfa6cfb48526e6b7eb8f4935be69b650ea8f0ef151446c58f6fc67144f8c15b6

See more details on using hashes here.

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

Hashes for browseraudio-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0d5495d3e8437a6fc1042d1b07cd8b73dce87be8ddfe98776e6fb0b5cb838423
MD5 979079e07f19a10cc02a5c7993f77b88
BLAKE2b-256 98e83695aa5ab5c485b31ecd659a868fc2b60269f858cf365dc237632c8c1104

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page