docs(examples): add microphone live transcription example - #780
Conversation
|
dg-coreylweathers
left a comment
There was a problem hiding this comment.
What this PR does
Adds example 18: live microphone transcription through Listen V1 using the optional sounddevice package, plus its line in examples/README.md. The microphone callback hands audio to a bounded 20-slot queue that a separate thread drains, so a slow network can never block the audio driver; dropped chunks are counted and reported, and Ctrl-C sends Finalize + CloseStream before exiting.
What I checked
- Does every SDK call it makes exist? Yes — all seven
connect()parameters and every method (send_media,send_finalize,send_close_stream,start_listening), event, and response field it uses match the Listen V1 surface by name. - Is the threading sound? Yes — I traced callback → queue → sender thread → error propagation → shutdown; sender failures and SDK error events both stop the run and surface as a non-zero exit, and both worker threads are daemons so exit can't hang.
- Can the API key leak? No — the key comes from the environment only and is never printed.
- Not verified here: the live macOS microphone run is author-attested; a real mic can't be exercised headlessly.
One fix before merge
When the connection fails (a bad key is the most common case), the developer sees only Microphone transcription failed: ApiError — the status code and message are discarded. This SDK's ApiError already masks the Authorization header at construction, so printing the exception is safe and makes the failure actionable. In examples/18-transcription-live-microphone.py, line ~183:
print(f"Microphone transcription failed: {type(exc).__name__}: {exc}", file=sys.stderr)|
Thank you @dg-coreylweathers could you please re-review this? |
dg-coreylweathers
left a comment
There was a problem hiding this comment.
What this PR does
Adds example 18: live microphone transcription through Listen V1 using the optional sounddevice package, plus its line in examples/README.md. Closes #779. No SDK code changes.
Re-review of the earlier fix
The requested change is in (f600496): connection failures now print the exception type and message. I ran the script with a deliberately bad key and got Microphone transcription failed: InvalidStatus: server rejected WebSocket connection: HTTP 401, exit code 1, with the key absent from all output. One note on my earlier wording: the SDK surfaces a rejected handshake as the websockets library's InvalidStatus, not ApiError, because the generated compat shim binds the wrong exception class. Your fix handles either, so nothing to change there.
The widened type: ignore[import-not-found,import-untyped] is correct: mypy reports the first code when sounddevice is absent and the second when it is installed without stubs. Both environments pass under mypy 1.13.
One fix before merge
On Debian or Ubuntu with sounddevice installed but the PortAudio system library missing, import sounddevice raises OSError, not ImportError. The script's friendly install hint only catches ImportError, so the developer gets a full traceback and exit 1. I reproduced this in a python:3.12 container. Fix is to catch both and name the apt package. In examples/18-transcription-live-microphone.py, line ~41:
except (ImportError, OSError) as exc:
raise RuntimeError(
"Microphone capture requires sounddevice and the PortAudio library. "
"Install them with: pip install sounddevice "
"(on Debian/Ubuntu also: sudo apt install libportaudio2)"
) from excWhat I checked
- Every
connect()argument, socket method, event type, and response field the script uses exists on the Listen V1 surface. - Every
RawInputStreamargument exists in sounddevice 0.5.6. - Sample rate and channel count flow from the CLI args into both the mic stream and the websocket, never hardcoded.
- ruff, mypy, py_compile,
git diff --check, and CI on 3.10-3.13 all pass. - Not verified here: the live macOS microphone run (author-attested; no mic headlessly).
Nits, optional
on_close(line 117) sets the stop flag silently, so a clean server close exits 0 with no output after "Recording..."; example 13 prints "Connection closed". Suggest printing the same.- README entry: "Live microphone transcription (Listen V1) with the optional sounddevice dependency", matching how entries 13 and 14 name the API version.
dg-coreylweathers
left a comment
There was a problem hiding this comment.
What this PR does
Adds example 18: live microphone transcription through Listen V1 using the optional sounddevice package, plus its line in examples/README.md. Closes #779. No SDK code changes.
Re-review of the requested fix
Commit 3157d39 applies the PortAudio change as suggested: load_sounddevice() now catches OSError alongside ImportError and names libportaudio2 in the hint. I reproduced the Debian case in a python:3.12 container with sounddevice installed and no PortAudio library on the system: the script prints the one-line install hint, exits 2, no traceback. Same result for --list-devices in that environment and for the no-sounddevice environment. Only those four lines changed since the last review.
What I checked
- ruff check and ruff format pass; mypy 1.13 passes with and without
sounddeviceinstalled; py_compile passes. - CI at 3157d39: compile and test on 3.10-3.13, Title Check, all green.
- Not verified here: the live macOS microphone run (author-attested; no mic headlessly).
The two earlier nits (printing "Connection closed" in on_close, and naming Listen V1 in the README entry) were not taken and remain optional. Approving.
🤖 I have created a release *beep* *boop* --- ## [7.8.1](v7.8.0...v7.8.1) (2026-09-03) ### Bug Fixes * **TextBuilder:** `ssml_to_deepgram()` now preserves a `<phoneme>` pronunciation when its valid `ph` and `alphabet` attributes appear in either order. ([#741](#741)) ([7fd4b63](7fd4b63)) * **Credentials:** Explicitly passing `api_key=None` continues to disable ambient `DEEPGRAM_API_KEY` lookup, which is important for multi-tenant and test environments. ([#778](#778)) ([e675990](e675990)) * **Credentials:** `DeepgramClient()` and `AsyncDeepgramClient()` now resolve `DEEPGRAM_API_KEY` when constructed, so `load_dotenv()` can run after importing the SDK. Closes [#734](#734). ([#767](#767)) ([ec362ec](ec362ec)) * **Custom transports:** Speak V2 WebSocket connections now honor `transport_factory`, matching the routing behavior of other WebSocket APIs for proxies, test doubles, and custom-hosted transports. ([#766](#766)) ([0980663](0980663)) ### Documentation * **Transcription:** Clarified that Nova-3 assumes English when `language` is omitted; non-English and multilingual audio require an explicit language such as `fr` or `multi`. ([#771](#771)) ([4574337](4574337)) * **Examples:** Added Listen V1 live microphone transcription with optional `sounddevice`, device selection, bounded audio buffering, transcript output, and clean Ctrl-C shutdown. ([#780](#780)) ([08f0471](08f0471)) * **Examples:** Added a resilient Listen V1 live transcription pattern with exponential backoff, reconnect-aware audio buffering, timestamp continuity, and clean shutdown. ([#776](#776)) ([96b2d11](96b2d11)) * **Examples:** Added an application-owned Voice Agent session recorder that serializes received transcripts, function calls, and latency reports as JSON while leaving consent, redaction, retention, and storage policy to the application. Closes [#775](#775). ([#781](#781)) ([30ad152](30ad152)) * **Text-to-Speech:** Corrected streaming synthesis snippets to iterate the response byte chunks instead of accessing a nonexistent `.stream` attribute. ([#749](#749)) ([178724e](178724e)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Greg Holmes <greg.holmes@deepgram.com>
Closes #779
Summary
sounddevicedependencyexamples/README.mdScope
This is an example only. It adds no core microphone capture abstraction, optional package extra, or platform-audio dependency to
deepgram-sdk; microphone drivers, permissions, and backend installation remain owned bysounddeviceand the host platform.Validation
sounddevicepath prints the install command without a traceback--list-deviceswith an isolated fake backend1019 passed, 1 skippedgit diff --checkpasses