Skip to main content

streamcore (Python)

English | 简体中文

Python SDK for connecting to a streamcore server via WebRTC + WHIP, powered by aiortc.

Requirements

  • Python 3.10+

Installation

pip install streamcore

Or install from source:

cd python-sdk
pip install -e .

Quick Start

import asyncio
import numpy as np
import streamcore


async def main():
    def on_transcript(entry, all_entries):
        print(f"[{entry.role}] {entry.text}")

    client = streamcore.Client(
        config=streamcore.Config(whip_endpoint="http://localhost:8080/whip"),
        events=streamcore.EventHandler(
            on_transcript=on_transcript,
            on_error=lambda err: print(f"Error: {err}"),
        ),
    )

    await client.connect()

    # Send a 20 ms frame of silence
    pcm = np.zeros(streamcore.FRAME_SIZE, dtype=np.int16)
    await client.send_pcm(pcm)

    # Receive decoded audio from the agent
    audio = await client.recv_pcm()  # numpy int16 array

    await client.disconnect()


asyncio.run(main())

API

Client(config?, events?)

Creates a new voice agent client.

Config

Field Type Default Description
whip_endpoint str "http://localhost:8080/whip" WHIP signaling endpoint URL
token str "" JWT sent as Authorization: Bearer on the WHIP request
token_url str "" Token endpoint; when set, a JWT is fetched before each connection (overrides token)
api_key str "" Sent as Authorization: Bearer when fetching from token_url
resource_id str "" Who is on the call, forwarded to an external agent so it can scope memory to the person rather than the call. Sent in the token request body when token_url is set (the server signs it into the token), otherwise as an X-StreamCore-Resource-Id header
ice_servers list[str] ["stun:stun.l.google.com:19302"] ICE server URLs

EventHandler

All callbacks are optional.

Callback Signature Description
on_status_change (status: ConnectionStatus) -> None Fired when connection status changes
on_transcript (entry: TranscriptEntry, all: list[TranscriptEntry]) -> None Fired on new or updated transcript
on_agent_state_change (state: AgentState) -> None Fired when the agent starts listening, thinking, or speaking
on_timing (event: TimingEvent) -> None Fired with server-side pipeline timing info
on_error (error: Exception) -> None Fired on connection or server errors
on_data_channel_message (msg: DataChannelMessage) -> None Fired for every raw DC message

Methods

Method Description
await client.connect(track?) Connect via WHIP. Optionally pass an aiortc audio track.
await client.disconnect() Tear down connection and free resources.
await client.send_pcm(pcm) Send a numpy int16 PCM buffer (mono 48 kHz) to the agent.
await client.recv_pcm() Receive decoded PCM audio as a numpy int16 array.
client.status Current ConnectionStatus.
client.transcript Current conversation as list[TranscriptEntry].
client.remote_track Inbound audio track from the agent (available after connect).

Audio Constants

Constant Value Description
SAMPLE_RATE 48000 Audio sample rate in Hz
CHANNELS 1 Number of channels (mono)
FRAME_SIZE 960 Samples per 20 ms frame

Reconnection

A network change mid-call is recovered automatically, and the conversation survives it: the agent still knows who you are and does not replay its greeting.

The other SDKs run a two-phase ladder: an ICE restart first (which keeps the transport itself alive), falling back to a resume redial once the connection has failed. Python has only the second phase, and that is a hard aiortc limit rather than a choice: RTCPeerConnection.createOffer() takes no options, aioice fixes its ICE credentials at construction, and aiortc has no disconnected state to act on — it goes straight from connected to failed.

So Python recovers by redialling with a resume token: a brand new peer connection, reattached server-side to the session it was already running. The transport is new; the conversation is not. In practice the difference is a moment of silence where the other SDKs would have had none.

Status goes connectedreconnectingconnected:

import streamcore

client = streamcore.Client(
    streamcore.Config(
        whip_endpoint="http://localhost:8080/whip",
        reconnect_attempts=3,
        reconnect_delay=2.0,
    ),
    streamcore.EventHandler(
        on_reconnect=lambda e: print(f"redial {e.attempt}/{e.max_attempts}: {e.outcome}"),
    ),
)

One outcome deserves handling rather than logging:

  • RECOVERED — reattached; history intact.
  • RECOVERED_WITHOUT_HISTORYthe call works but the agent has forgotten everything. The server had already reaped the session, so the redial started a fresh conversation. Surface this to the user rather than letting them discover it by being asked their name again.
  • FAILED — every attempt failed; status becomes disconnected.

The window is the server's session_grace_ms (30s by default), measured from when the connection dropped — not the ~25s ICE deadline the other SDKs work against. Keep reconnect_attempts × reconnect_delay (doubling each retry) inside it. Set reconnect_attempts=0 to disable and handle drops yourself.

Two caveats specific to this stack:

  • Realtime (speech-to-speech) sessions cannot be resumed. Their history lives inside the provider, so the server issues no token and a redial starts a new conversation.
  • A caller-supplied user_track is reused across the redial. The built-in track (the send_pcm path) is rebuilt automatically; if you pass your own track to connect(), make sure it is still live, or reconnect yourself.

The wire-format helpers for ICE restart still ship in streamcore.icerestart for callers driving another WebRTC stack:

from streamcore import whip_restart_ice, ice_fragment_from_sdp, apply_ice_fragment

Audio I/O

The SDK handles aiortc track management, av.AudioFrame construction, and resampling internally. Callers only deal with raw PCM data as numpy int16 arrays:

# Send microphone audio (960 samples = 20 ms at 48 kHz)
await client.send_pcm(pcm_int16)

# Receive agent audio
audio = await client.recv_pcm()

If you need direct track access (e.g. for a custom aiortc pipeline), pass your own AudioStreamTrack via client.connect(user_track=my_track).

Dependencies

Package Purpose
aiortc WebRTC stack
aiohttp HTTP client for WHIP signaling
av Audio frame encoding/decoding
numpy PCM audio buffers

License

Apache-2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

streamcore-0.1.4.tar.gz (23.2 kB view details)

Uploaded Source

Built Distribution

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

streamcore-0.1.4-py3-none-any.whl (22.2 kB view details)

Uploaded Python 3

File details

Details for the file streamcore-0.1.4.tar.gz.

File metadata

  • Download URL: streamcore-0.1.4.tar.gz
  • Upload date:
  • Size: 23.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for streamcore-0.1.4.tar.gz
Algorithm Hash digest
SHA256 c75c404d5410300bec084de1ecc29e3f5852a585d33b36375699ee677a842c09
MD5 1e5f2df880004db74bf3c3e6ac103ae9
BLAKE2b-256 92dd09ed9a40f758b053e3935046df80bab7653c9359b0127a0107b42f188dbe

See more details on using hashes here.

Provenance

The following attestation bundles were made for streamcore-0.1.4.tar.gz:

Publisher: publish.yml on streamcoreai/python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file streamcore-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: streamcore-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 22.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for streamcore-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 e8bfa81eb28b1178b798f2f609f99f48bf21e3ddde3ae53be44846ec614f69ba
MD5 c4ff31a5660d57e25ece20a7ec5bf765
BLAKE2b-256 e7497e0424ca72a9cb043a1f1621fa6e4f2bdc8443703ea33edf34b92355b8b6

See more details on using hashes here.

Provenance

The following attestation bundles were made for streamcore-0.1.4-py3-none-any.whl:

Publisher: publish.yml on streamcoreai/python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 files

0.1.3

2 files

0.1.2

2 files

0.1.0

2 files

Supported by

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