Skip to main content

A client library for the Voxium real-time transcription service

Project description

Voxium Real-Time Transcription Client

This project provides a Python client library for interacting with the Voxium real-time speech-to-text (ASR) WebSocket service. It captures audio from the microphone, streams it to the Voxium server, and processes the received transcriptions via callbacks.

Key Features:

  • Real-time Audio Streaming: Captures microphone audio using sounddevice.
  • WebSocket Communication: Connects to and communicates with the Voxium ASR WebSocket endpoint using websockets.
  • Asynchronous Operation: Built using asyncio for efficient non-blocking I/O.
  • Thread-Safe Audio Handling: Safely transfers audio data from the sounddevice callback thread to the main asyncio event loop using asyncio.Queue.
  • Configurable Parameters: Allows setting language, VAD thresholds, API keys, and other parameters for the Voxium service.
  • Callback-Based API: Provides asynchronous callbacks for handling transcription results, errors, connection events (open/close).
  • Simplified Usage: Offers a high-level LiveTranscriber class with a blocking start_transcription method for easy integration.

Table of Contents

Prerequisites

  • Python: Version 3.7+ (due to asyncio usage)
  • Microphone: A working microphone connected to your system and recognized by sounddevice.
  • PortAudio: The sounddevice library depends on the PortAudio library. Installation varies by OS:
    • macOS: brew install portaudio
    • Debian/Ubuntu: sudo apt-get install libportaudio2 libportaudiocpp0 portaudio19-dev
    • Windows: Often included with Python distributions or audio drivers. Check the sounddevice documentation for details.
  • Voxium API Key: You need an API key from Voxium to authenticate with the service.

Installation

  1. From Source
git clone https://github.com/nathanmfrench/voxium-client
pip install -r requirements.txt
  1. From Package Manager:
pip install voxium

(or you can use your package manager of choice)

Configuration

Configuration is primarily done within your Python script (like example_usage.py):

  • VOXIUM_API_KEY: Required. Replace the placeholder "YOUR_API_KEY_HERE" with your actual Voxium API key. This is sent as a query parameter (apiKey) for authentication.
  • VOXIUM_SERVER_URL: The WebSocket endpoint URL for the Voxium ASR service. Defaults to "wss://voxium.tech/asr/ws".
  • VOXIUM_LANGUAGE: The language code for transcription (e.g., "en", "es", "fr"). Defaults to "en".
  • Other Parameters: You can customize other parameters when initializing LiveTranscriber or VoxiumClient:
    • vad_threshold (float): Voice Activity Detection threshold (client-side hint for server).
    • silence_threshold (float): Server-side silence duration parameter, controls length of silence before sending an audio chunk.
    • sample_rate (int): Audio sample rate (hardcoded to 16000 Hz in live_transcribe.py).
    • input_format (str): Expected audio format on the server after base64 decoding (hardcoded to "base64" in live_transcribe.py as the client sends base64).
    • beam_size (int): Beam size controls number of search candidates at each step (set to 1 for greedy decoding).
    • language (str): 2 digit ISO-code for the desired language. 'None' to auto-detect (language and probability passed to client as language, language_probability respectively)

50 Supported languages: Arabic (ar), Armenian (hy), Azerbaijani (az), Belarusian (be), Bosnian (bs), Bulgarian (bg), Catalan (ca), Chinese (zh), Croatian (hr), Czech (cs), Danish (da), Dutch (nl), English (en), Estonian (et), Finnish (fi), French (fr), German (de), Greek (el), Hebrew (he), Hindi (hi), Hungarian (hu), Icelandic (is), Indonesian (id), Italian (it), Japanese (ja), Kannada (kn), Korean (ko), Latvian (lv), Lithuanian (lt), Macedonian (mk), Malay (ms), Nepali (ne), Norwegian (no), Persian (fa), Polish (pl), Portuguese (pt), Romanian (ro), Russian (ru), Serbian (sr), Slovak (sk), Slovenian (sl), Spanish (es), Swedish (sv), Tagalog (tl), Tamil (ta), Thai (th), Turkish (tr), Ukrainian (uk), Urdu (ur), Vietnamese (vi)

Usage

The example_usage.py script demonstrates how to use the LiveTranscriber.

  1. Import: Import the necessary classes and modules.
  2. Configure Logging: Set up Python's logging module (the example provides a basic console logger).
  3. Define Transcription Handler: Create an async function that will receive transcription results (dictionaries). This is where you integrate the text into your application logic.
  4. Set Parameters: Define your API key, server URL, and language.
  5. Initialize LiveTranscriber: Create an instance, passing the configuration parameters.
  6. Start Transcription: Call the start_transcription method, providing your handler function. This method is blocking and will run until interrupted (e.g., Ctrl+C) or a critical error occurs.
import logging
from voxium_client import LiveTranscriber 

# --- 1. Configure Logging  ---
# This basic setup logs WARNING level messages and above to the console.
# It's sufficient for most examples (you can implement more complex logging if needed).
# Set level=logging.DEBUG for debugging logs, and level=logging.INFO for normal logs.

logging.basicConfig(
    level=logging.WARNING,
    format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger("MyVoiceAgentExample")


# --- 2. Define Your Transcription Handler (Required) ---
# This asynchronous function will receive transcription results.
async def handle_transcription(result: dict):
    """
    Callback function to process transcription results from Voxium.
    'result' is a dictionary.
    """
    try:
        text = result.get('transcription', '')
        print("Transcription: ", text)

        # Now, you can ntegrate the transcription text into your voice agent's pipeline. For example:
            # await send_to_my_agent_logic(text)

    except Exception as e:
        logger.error(f"Error within handle_transcription callback: {e}", exc_info=True)


# --- 3. Main Execution ---
if __name__ == "__main__":
    logger.info("Starting Voxium LiveTranscriber Integration Example...")

    # --- Configuration Parameters ---
    VOXIUM_API_KEY = "YOUR_API_KEY_HERE"

    if VOXIUM_API_KEY == "YOUR_API_KEY_HERE":
        logger.warning("Using placeholder API Key. Please set the VOXIUM_API_KEY environment variable or replace the placeholder.")

    VOXIUM_SERVER_URL = "wss://voxium.tech/asr/ws"
    VOXIUM_LANGUAGE = "en"

    # --- Initialize the Transcriber ---
    logger.info(f"Initializing LiveTranscriber for {VOXIUM_LANGUAGE}...")
    transcriber = LiveTranscriber(
        server_url=VOXIUM_SERVER_URL,
        language=VOXIUM_LANGUAGE,
        api_key=VOXIUM_API_KEY
        # Add/override other parameters if needed:
        # vad_threshold=0.5,
        # silence_threshold=0.5,
    )

    # --- Start the Transcription Process ---
    # This is a blocking call that runs the transcriber until stopped (Ctrl+C or error).
    # It requires your 'on_transcription' callback function.
    logger.info("Starting transcription. Press Ctrl+C to stop.")
    try:
        transcriber.start_transcription(
            on_transcription=handle_transcription
            # --- Optional Callbacks ---
            # You can provide your own async functions for other events:
            # on_error=my_async_error_handler,
            # on_open=my_async_open_handler,
            # on_close=my_async_close_handler
        )
    except Exception as e:
         logger.critical(f"Failed to run transcription: {e}", exc_info=True)

    logger.info("Transcription process finished.")

Run script from your terminal with

python3 example_usage.py

Core Components

VoxiumClient (client.py)

  • Manages the low-level WebSocket connection lifecycle (connect, close).
  • Handles URL construction with query parameters (including the API key).
  • Formats outgoing audio messages (encodes audio bytes to Base64 JSON).
  • Runs a persistent _receiver task to listen for incoming messages (transcriptions, status, errors) from the server.
  • Parses incoming JSON messages and routes them to the appropriate asynchronous callbacks.
  • Provides setter methods (set_transcription_callback, set_error_callback, etc.) for registering custom handlers.
  • Implements async context manager protocols (__aenter__, __aexit__) for automatic connection setup and teardown.
  • Handles WebSocket connection errors and state changes.

LiveTranscriber (live_transcribe.py)

  • Acts as the primary interface for users.
  • Initializes and manages the VoxiumClient.
  • Uses sounddevice.InputStream to capture audio from the default microphone in a separate thread.
  • The _audio_callback function (running in the sounddevice thread) converts audio chunks (numpy.ndarray) to bytes.
  • Uses loop.call_soon_threadsafe to safely put the audio bytes onto an asyncio.Queue from the sounddevice thread.
  • An _audio_loop async task runs in the main event loop, consuming audio bytes from the queue.
  • Sends audio chunks to the server via the VoxiumClient.send_audio_chunk method.
  • Manages the starting (start) and stopping (stop, cleanup_audio) of the audio stream and processing loop.
  • Provides the simplified, blocking start_transcription method which:
    • Sets up default callbacks if user doesn't provide them.
    • Assigns user-provided callbacks to the underlying VoxiumClient.
    • Checks basic sounddevice settings before starting.
    • Uses asyncio.run() to manage the event loop and run the main start coroutine.
    • Handles KeyboardInterrupt for graceful shutdown.

Callbacks

The LiveTranscriber.start_transcription method accepts several optional async callback functions:

  • on_transcription(result: dict): (Required) Called whenever a transcription message (partial or final) is received from the server. The result dictionary typically contains keys like "transcription" (the text) and "is_final" (boolean).
  • on_error(error: Union[Exception, str]): Called when the server sends an error status message or when certain client-side processing errors occur (like in the audio loop or message handling).
  • on_open(info: dict): Called once after the WebSocket connection is successfully established and the initial server handshake is complete. The info dictionary contains details sent by the server (e.g., model info).
  • on_close(code: int, reason: str): Called when the WebSocket connection is closed, either cleanly or due to an error detected by the underlying websockets library within the receiver task. Provides the close code and reason.

If you don't provide on_error, on_open, or on_close, default handlers that log the event will be used.

Note: The underlying VoxiumClient also has a connection_error_callback specifically for errors during the connection phase or WebSocket-level close errors not caught by the receiver loop's ConnectionClosed... exceptions. This isn't directly exposed via start_transcription but is used internally and logs errors.

Logging

The code uses Python's standard logging module.

  • example_usage.py sets up a basic configuration that logs INFO level messages and above to the console.
  • client.py and live_transcribe.py obtain their own loggers (logging.getLogger(__name__)).
  • You can customize the logging level and format in example_usage.py (e.g., set level=logging.DEBUG for verbose output, or add file handlers).

How it Works

  1. LiveTranscriber.start_transcription is called.
  2. It configures callbacks on the VoxiumClient instance.
  3. It runs asyncio.run(_run_internal), which calls LiveTranscriber.start.
  4. LiveTranscriber.start gets the current event loop.
  5. It enters the VoxiumClient async context (__aenter__), which calls client.connect.
  6. client.connect establishes the WebSocket connection, handles authentication, receives initial info, and starts the client._receiver task in the background.
  7. LiveTranscriber.start calls setup_audio, which creates and starts sounddevice.InputStream. The _audio_callback begins running in a separate thread.
  8. _audio_callback captures audio chunks, converts them to bytes, and uses loop.call_soon_threadsafe to put them on the audio_queue.
  9. LiveTranscriber.start starts the _audio_loop task.
  10. _audio_loop waits for audio bytes from the audio_queue.
  11. When audio arrives, _audio_loop calls client.send_audio_chunk.
  12. client.send_audio_chunk base64 encodes the audio and sends it as a JSON message over the WebSocket.
  13. Concurrently, client._receiver listens for messages from the server.
  14. When a transcription message arrives, _receiver parses it and calls the registered on_transcription callback (your handle_transcription function).
  15. This continues until start_transcription is interrupted (Ctrl+C) or a fatal error occurs.
  16. On exit (interrupt or completion/error of start), asyncio.run handles task cancellation. The finally blocks in start and the client's __aexit__ method (close) ensure the audio stream and WebSocket connection are cleaned up.

Dependencies

  • websockets: For WebSocket client implementation.
  • numpy: For handling audio data arrays from sounddevice.
  • sounddevice: For accessing the microphone and capturing audio streams.
  • typing: For type checking

Troubleshooting

  • PortAudioError / No Sound / "Invalid input device":
    • Ensure a microphone is plugged in and enabled in your system settings.
    • Verify PortAudio is installed correctly (brew install portaudio, apt-get install ...).
    • Check if another application is exclusively using the microphone.
    • Try specifying a device ID in sd.InputStream(device=...) if the default is wrong. Use python -m sounddevice to list devices.
    • Ensure the microphone supports the required settings (16000 Hz, Mono, 16-bit Integer - RATE, CHANNELS, SD_DTYPE).
  • Connection Refused / Invalid Status Code / Timeout:
    • Double-check the VOXIUM_SERVER_URL.
    • Verify your VOXIUM_API_KEY is correct and valid.
    • Check your internet connection and any firewall/proxy settings that might block WebSocket connections (port 443 for wss://).
  • Authentication Errors:
    • Ensure the apiKey query parameter is being sent correctly (check logs if DEBUG level enabled) and matches what Voxium expects.
  • No Transcriptions Received:
    • Check if the microphone is picking up sound (enable DEBUG logging to see audio chunk scheduling/sending).
    • Verify the correct VOXIUM_LANGUAGE is set.
    • Look for error messages in the logs from the client or server.
  • Import Errors:
    • Ensure the Python files (client.py, live_transcribe.py) are located where Python can find them (e.g., same directory as your main script, or installed as part of a package). Adjust import statements (from .client ... vs from voxium_client ...) as needed based on your project structure.

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

voxium-0.2.0.tar.gz (16.2 kB view details)

Uploaded Source

Built Distribution

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

voxium-0.2.0-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

Details for the file voxium-0.2.0.tar.gz.

File metadata

  • Download URL: voxium-0.2.0.tar.gz
  • Upload date:
  • Size: 16.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.1

File hashes

Hashes for voxium-0.2.0.tar.gz
Algorithm Hash digest
SHA256 41059d2d6c9ce2c303363b67d61096bf9d9664d34775d28af469f4ad5c014e12
MD5 1027ef784d150c5b593d5f852e46c230
BLAKE2b-256 6fc194357cf861720463733235db6c39983043113d54f12856f197e56fd69466

See more details on using hashes here.

File details

Details for the file voxium-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: voxium-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.1

File hashes

Hashes for voxium-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 69645d07d1db877037d93b48e57503751455695f15a795d7c73611ff6cba74d3
MD5 e35a189a93cd72b11eef034ee55c5458
BLAKE2b-256 f2159af569123e34a989f98bf29d3b9e5bd6f4a18896575b2bc8d78d3858f71a

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