Skip to main content

soda-stt

For education and testing purposes. This project exists to study and exercise the on-device speech engine Chrome ships; see Legal note below.

Chrome's on-device (offline) speech-to-text engine — the one behind Live Caption and ChromeOS dictation — as a Python library. Runs fully offline. First-class support for Brazilian Portuguese (pt-BR).

The engine is Google's SODA (Speech On-Device API), shipped as libsoda.so. This library can ship with the engine and language models bundled inside the package, so inference never touches the network; when they are not bundled, it downloads them once from Chrome's public component-update service and caches them. Either way it drives the engine through a small native helper.

  • docs/MODEL.md — how Google publishes the model, how it's downloaded, bundled, and integrated here.

Requirements

  • Linux x86-64 on glibc. libsoda.so is a glibc Linux x86-64 ELF, so the published wheel is tagged manylinux_2_34_x86_64 (glibc ≥ 2.34: Ubuntu 22.04+, Debian 12+, Fedora 36+). Older glibc distros build from the source distribution instead — pip does that automatically. macOS, Windows and other architectures are unsupported and get a clear error, not a crash.
  • Python 3.12+
  • ffmpeg on PATH (used to decode any audio/video input)
  • A C compiler (cc) — only for a build made without a bundle; both published artifacts ship the compiled helper

Install

pip install soda-stt      # or: uv add soda-stt

Two artifacts are published, both self-contained (engine, pt-BR pack and helper included, ~92 MB each):

artifact pip uses it when
soda_stt-…-py3-none-manylinux_2_34_x86_64.whl the platform matches (glibc ≥ 2.34) — installed directly
soda_stt-<version>.tar.gz (source) no wheel matches (older glibc) — built during install, same bundle inside

Building the artifacts yourself

uv run python scripts/bundle.py   # stage engine + pt-BR from artifacts/ into the package
scripts/build_release.sh          # manylinux wheel + sdist into dist/
pip install dist/*.whl

scripts/bundle.py --pack LOCALE=PATH.crx3 stages further locales; an artifact built without a bundle falls back to downloading components on first use.

Use

from soda_stt import SodaRecognizer

rec = SodaRecognizer.for_locale("pt-BR")   # bundled, else cached, else downloaded once

# Whole-file transcription (any ffmpeg-readable file or URL).
# Fast by default: splits on silence and transcribes chunks in parallel.
text = rec.transcribe("entrevista.mp3")
print(text)

On an 8-core desktop a 55-minute recording transcribes in about 90 seconds (~37x real time), complete and correctly punctuated.

Word timestamps and segments

for seg in rec.transcribe_detailed("entrevista.mp3"):
    print(f"[{seg.start_ms/1000:.1f}s] {seg.text}")
    for w in seg.words:
        print(f"    {w.start_ms/1000:6.2f}s  {w.text}  (speaker {w.speaker})")

Live streaming (in order, as it arrives)

for r in rec.stream("entrevista.mp3"):
    print("FINAL" if r.is_final else "partial", r.text)

Raw PCM (16 kHz, mono, s16le) if you already have samples:

text = rec.transcribe_pcm(pcm_bytes)

See examples/ for a live microphone script and a diarization script.

Command line

soda-stt download --locale pt-BR               # make engine + models available locally
soda-stt download --locale pt-BR --force       # ...and check the update service for newer ones
soda-stt transcribe entrevista.mp3             # plain text (fast parallel)
soda-stt transcribe entrevista.mp3 -f srt -o out.srt   # subtitles with timecodes
soda-stt transcribe entrevista.mp3 -f json     # segments + word timestamps + speakers
soda-stt transcribe call.wav --max-speakers 4  # experimental diarization
soda-stt transcribe long.mp3 --workers 4       # tune parallelism
soda-stt transcribe odd.aac --no-fast          # single-session paced streaming

How it's fast, and the pacing knob

SODA assumes audio arrives at roughly real time: fed a whole file at once it finalizes once and drops the rest. Two consequences:

  • Parallel path (default). The audio is split at silences into ~28-second chunks that are transcribed concurrently. Each chunk is still fed at a bounded multiple of real time (realtime_factor, default 6) so none of its content is dropped; the speed comes from running many chunks at once. Worker count defaults to half your cores — raising it too high makes the engine fall behind during processing bursts and lose words, so more workers is not always better.

  • Single-session path (stream(), or transcribe(..., fast=False)). One paced session, results strictly in order. Best for live display and for inputs ffmpeg can't probe. A 60-minute file takes about 10 minutes at the default pace.

For a live microphone you already produce audio in real time, so pass realtime_factor=None to stream_pcm and feed chunks as they arrive (see examples/microphone.py).

Speaker diarization (experimental)

The engine tags each word with a speaker label, exposed as Word.speaker (1-indexed). Enable it with SodaRecognizer.for_locale(..., max_speaker_count=N) and read labels from transcribe_detailed() or stream(). Speaker numbering is only consistent within a single session, so use stream() (not the parallel path) when you care about who-said-what across a whole recording. Quality is model-dependent: clean, turn-taking audio works best; on single-speaker audio everything is speaker 1.

Languages

pt-BR and en-US are wired up by CRX id. Other locales SODA supports can be added in soda_stt/_config.py (LANGUAGE_PACK_IDS). Locales that aren't bundled or cached are fetched from the update service on first use; to bundle one too, stage it with scripts/bundle.py --pack <locale>=<crx3> before building the artifacts.

This project is published for education and testing purposes. It downloads, bundles and runs Google's SODA engine and language models, which are Google's property and carry their own terms. It is an interoperability / research tool for the on-device speech engine you already receive with Chrome. Review Chrome's and Google's terms before relying on it beyond education and testing.

Metadata

Release files for soda-stt 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for soda-stt 0.1.1
File Size Uploaded Provenance
soda_stt-0.1.1.tar.gz 92.2 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for soda-stt 0.1.1
File Interpreter ABI Platform
soda_stt-0.1.1-py3-none-manylinux_2_34_x86_64.whl Python 3 none Linux glibc 2.34+ x86-64 Details

Total release size: 184.7 MB

Release files / soda_stt-0.1.1.tar.gz

Download URL soda_stt-0.1.1.tar.gz
Size 92.2 MB
Tags Source
SHA-256 checksum
How to use checksums
dc936a56f3d925219ec91434e3a122786a7806c3ab328515250a0637fb0951eb
BLAKE2b-256 checksum
How to use checksums
c1e19634e708e2f872e097c6f2f3e9721108d7ffab0a826e301b0260ea660fd3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.7

Release files / soda_stt-0.1.1-py3-none-manylinux_2_34_x86_64.whl

Download URL soda_stt-0.1.1-py3-none-manylinux_2_34_x86_64.whl
Size 92.5 MB
Tags Linux glibc 2.34+ x86-64 Python 3
SHA-256 checksum
How to use checksums
d1f481d01c131801ffaea4cac0c09ee648ee295f8be717559719e444c3489dff
BLAKE2b-256 checksum
How to use checksums
da2d14cb74d87d3fadf34bc7b62aee522c32a3dad67132ca6fbacfc77547f281
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.7

Security for soda-stt 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page