smelter-sdk
Python client for Smelter — a real-time, low-latency, programmable video and audio composition toolkit.
The SDK currently exposes Smelter's side channel: a Unix-socket stream of decoded RGBA video frames and PCM audio batches, so Python code can run ML inference (YOLO, Whisper, …) against live media and feed results back into the running pipeline via Smelter's HTTP API.
Status: alpha. The API may change between 0.x releases.
Install
pip install smelter-sdk
Requires Python 3.11+ and NumPy 1.26+. Tested on Linux and macOS. The Smelter server itself is a separate Rust binary — see the Smelter docs for installation.
Quickstart (sync)
The SDK reads its socket directory from the
SMELTER_SIDE_CHANNEL_SOCKET_DIR environment variable (the same one the
server publishes), falling back to the current working directory. With that
exported, the API takes one positional argument — the Smelter input id:
from smelter import subscribe_video_channel
for frame in subscribe_video_channel("cam1"):
# frame.rgba is a writable np.ndarray, shape (H, W, 4), dtype uint8.
# frame.pts_nanos is a presentation timestamp in nanoseconds.
process(frame.rgba, frame.pts_nanos)
Audio:
from smelter import subscribe_audio_channel
for batch in subscribe_audio_channel("cam1"):
# batch.samples is a (sample_count, channels) np.ndarray, dtype float32.
mono = batch.to_mono() # shape (sample_count,)
print(batch.start_pts_seconds, batch.duration_seconds)
If the env var isn't right for your process, pass an explicit
Context:
from smelter import Context, subscribe_video_channel
ctx = Context(socket_dir="/var/run/smelter")
for frame in subscribe_video_channel("cam1", ctx=ctx, timeout=10):
...
Quickstart (asyncio)
import asyncio
from smelter.aio import subscribe_video_channel
async def main():
async for frame in subscribe_video_channel("cam1"):
await process(frame.rgba, frame.pts_nanos)
asyncio.run(main())
The async client uses asyncio.open_unix_connection directly — no thread-pool
wrapper. Heavy synchronous work inside the loop (e.g. ML inference) should
still be wrapped in asyncio.to_thread(...) to avoid blocking other tasks.
Context
A Context bundles SDK-wide configuration. Today it carries one field — the
socket directory — but is the natural extension point for future options
(default timeouts, HTTP API base URL, …).
Context() # env var, then cwd
Context(socket_dir="/var/run/smelter") # explicit
Every public entry point (subscribe_video_channel, subscribe_audio_channel, list_channels,
wait_for_channel, …) accepts an optional ctx= keyword. When omitted, a
fresh default context is constructed per call.
Lower-level API
The top-level smelter module exposes the recommended high-level surface.
Lower-level building blocks live in smelter.sync (and smelter.aio for the
async equivalent) — reach for them only when the one-call
subscribe_*_channel helpers don't fit:
from smelter import SideChannelKind, list_channels
from smelter.sync import connect_video, wait_for_channel
# Enumerate everything currently published.
for info in list_channels():
print(info.kind, info.input_id)
# Wait for a specific channel, then connect.
info = wait_for_channel(kind=SideChannelKind.VIDEO, input_id="cam1", timeout=10)
with connect_video(info, timeout=5.0) as conn:
frame = conn.recv() # raises ConnectionClosed / RecvTimeout
for frame in conn: # iterates until peer closes
...
smelter.sync.connect_audio(info, dtype=np.float64) keeps full f64 precision;
the default is float32 to match Whisper / opus / librosa.
Errors
All exceptions inherit from smelter.SmelterError:
| Exception | Raised when |
|---|---|
ConnectionClosed |
Peer closed the socket — normal end-of-stream. |
RecvTimeout |
recv() exceeded the configured timeout. |
ChannelNotFound |
wait_for_channel timed out before a socket appeared. |
ProtocolError |
A message did not match the expected wire format. |
ChannelNotFound and RecvTimeout also inherit from the built-in TimeoutError.
Stability
The SDK is alpha — any 0.x release may break compatibility. Once 1.0 ships, the following surface will be governed by semver:
- Everything re-exported from the top-level
smelterpackage (seesmelter.__all__) andsmelter.aio(smelter.aio.__all__). - The synchronous building blocks in
smelter.sync(connect_video,connect_audio,wait_for_channel, theVideoConnection/AudioConnectionclasses) and theirsmelter.aioequivalents. - The data types in
smelter.types(VideoFrame,AudioBatch,SideChannelInfo,SideChannelKind) and the exceptions insmelter.errors.
Anything starting with an underscore (smelter._protocol, smelter._discovery)
is internal and may change without notice.
What's not in the SDK (yet)
- A typed client for the Smelter HTTP API. To send scene updates back to
Smelter today, use
requests/httpxagainst the/api/output/.../updateendpoint directly. - A way to push Python-generated frames into Smelter as an input. The side channel is unidirectional (Smelter → Python) at the moment.
Examples
The repository ships a complete demo that wires a video input through YOLO
object detection and Whisper speech-to-text, then renders the boxes and
subtitles back over the stream. See
sdks/python/example/.
License
MIT — see LICENSE.
Metadata
Release files for smelter-sdk 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| smelter_sdk-0.1.0.tar.gz | 12.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| smelter_sdk-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.7 kB
Release files / smelter_sdk-0.1.0.tar.gz
| Download URL | smelter_sdk-0.1.0.tar.gz |
|---|---|
| Size | 12.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5b7eb2355c9f3f1403e40179c3b4a9b4812e52682c2dd539abdcbb1455947589
|
|
BLAKE2b-256 checksum How to use checksums |
c085dac962c72b4b80b889326c365f237011471f874586e6f0a54f44ee68c084
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 28, 2026.
Transparency logRelease files / smelter_sdk-0.1.0-py3-none-any.whl
| Download URL | smelter_sdk-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
338fac872396e987154660b67613c0f2dc3883a5813e338cca9c7e15421e34a6
|
|
BLAKE2b-256 checksum How to use checksums |
67e406b44a65a9ece71aec7bd276a1f3e922162d324dedeeaea5158a915f845b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 28, 2026.
Transparency log