Skip to main content

tstrans

Python bindings (via PyO3) for the ts-transformer Rust workspace.

Status: tstrans covers file inspection + construction (Demuxer / Muxer / MuxerFileSink), typed KLV decode + encode for ST 0601 / ST 0102 / ST 0605 / ST 0903 (with VTargetPack), codec parsers for H.264 / H.265 / H.266 / AV1 / AAC / MPEG-2 audio, optional pandas DataFrame adapters + NumPy snapshot views via pip install tstrans[pandas], and live transports: SRT (tstrans.srt — Sender / Receiver / Builder / Socket / Listener / MuxSender / DemuxReceiver + Managed* auto-reconnect + ReconnectPolicy), RTP + RTSP (tstrans.rtp — Sender / Receiver / MuxSender / DemuxReceiver / RtspClient / RtspServer / MountHandle), and raw UDP / TCP / RIST (tstrans.udp / tstrans.tcp / tstrans.rist). 1,149 pytest tests. Minimum Python 3.10.

Install

pip install tstrans

Optional extras for DataFrame / NumPy integration:

pip install 'tstrans[pandas]'

Quickstart

Inspect a .ts file:

from tstrans.io import parse_file, probe
from tstrans.mpegts import DemuxEvent

# Quick summary
r = probe("capture.ts")
print(r.video_codecs, r.audio_codecs, r.has_klv)

# Full event stream
for event in parse_file("capture.ts"):
    match event:
        case DemuxEvent.Video(pts=p, codec=c, payload=b):
            print(f"Video {c.name} pts={p.ms}ms len={len(b)}")
        case DemuxEvent.Metadata(pts=p, payload=b):
            print(f"KLV pts={p.ms}ms len={len(b)}")

Build a .ts file (single-program H.264):

from tstrans.mpegts import (
    Muxer,
    MuxerConfigBuilder,
    MuxerProgramConfigBuilder,
    Pts90khz,
    VideoCodec,
)

prog = (
    MuxerProgramConfigBuilder(program_number=1, pmt_pid=0x100)
    .add_video(0x101, VideoCodec.H264)
    .build()
)
cfg = MuxerConfigBuilder().add_program(prog).build()
m = Muxer(cfg)

with m.write_file("out.ts") as proxy:
    proxy.push_video(nal_bytes, Pts90khz.from_raw(900_000))

RTP + RTSP transport

tstrans.rtp ships RTP-over-UDP and a full RTSP client + server. Available by default in published wheels — no extra needed (pip install tstrans already includes it). The Rust-side rtp cargo feature is on by default; source builds that don't need it can opt out with maturin develop --no-default-features for a smaller binary.

Connect to a camera and iterate demuxed events:

from tstrans.rtp import RtspClient, RtspClientConfig
from tstrans.mpegts import DemuxEvent

cfg = RtspClientConfig(url="rtsp://camera.local/live")
with RtspClient.connect(cfg) as session:
    demux = session.into_demux_receiver()
    for event in demux:
        if isinstance(event, DemuxEvent.Video):
            handle(event.payload)

Publish a stream from your own RTSP server:

from tstrans.rtp import RtspServer, RtspServerConfig
from tstrans.mpegts import MuxerProgramConfigBuilder, Pts90khz, VideoCodec

program = (
    MuxerProgramConfigBuilder(1, 0x100)
    .add_video(0x101, VideoCodec.H264)
    .build()
)
with RtspServer.start(RtspServerConfig(bind_addr="0.0.0.0:8554")) as server:
    mount = server.add_unicast_mount("/live", program)
    mount.push_video(nal_bytes, pts=Pts90khz.from_raw(0), key_frame=True)

The full surface — Sender / Receiver for raw RTP, MuxSender / DemuxReceiver for one-call mux/demux convenience, RtspClient / RtspSession with Basic + Digest auth and TCP-interleaved fallback, RtspServer + MountHandle with 16 push methods and multicast mounts — is documented in the per-class docstrings and the python/tstrans/rtp.pyi type stubs (mypy --strict clean).

SRT transport

tstrans.srt ships full SRT (Secure Reliable Transport) bindings on top of libsrt 1.5.7 — 18 PyClasses spanning low-level Builder / Socket / Listener primitives, high-level Sender / Receiver for raw bytes, MuxSender / DemuxReceiver for one-call mux/demux convenience, and ManagedSender / ManagedReceiver / ManagedMuxSender / ManagedDemuxReceiver for auto-reconnect-with-gap-buffer ergonomics. Available by default in published wheels — no extra needed (pip install tstrans already includes it). The Rust-side srt cargo feature is on by default; source builds that don't need SRT can opt out with maturin develop --no-default-features for a smaller binary that drops the libsrt + mbedTLS link.

Hello world — caller-side send + listener-side receive:

import threading
import tstrans.srt

# Listener side (run on one host / thread):
def listen_side() -> None:
    with tstrans.srt.Receiver.from_url("srt://0.0.0.0:9000?mode=listener") as rx:
        chunk = rx.recv_bytes(max_len=1500)
        print(f"received {len(chunk)} bytes; sync byte = {chunk[0]:#04x}")

threading.Thread(target=listen_side, daemon=True).start()

# Caller side (the other host / thread):
with tstrans.srt.Sender.from_url("srt://127.0.0.1:9000?mode=caller") as tx:
    payload = (b"\x47" + b"\x00" * 187) * 7  # one 1316-byte TS bundle
    tx.send_bytes(payload)

Full mux + demux example — push H.264 NALs + KLV blobs from the caller, iterate DemuxEvents on the listener:

import threading
import tstrans.srt
from tstrans.mpegts import (
    DemuxEvent, KlvStreamType, MuxerProgramConfigBuilder, Pts90khz, VideoCodec,
)

program = (
    MuxerProgramConfigBuilder(program_number=1, pmt_pid=0x100)
    .add_video(0x101, VideoCodec.H264)
    .add_klv(0x102, KlvStreamType.SYNCHRONOUS_METADATA, carries_pts=True)
    .build()
)

def consumer() -> None:
    with tstrans.srt.DemuxReceiver.from_url("srt://:9001?mode=listener") as rx:
        for event in rx:
            if isinstance(event, DemuxEvent.Video):
                print(f"video pts={event.pts.ms}ms nals={len(event.payload)}")
            elif isinstance(event, DemuxEvent.Metadata):
                print(f"klv pts={event.pts.ms}ms len={event.byte_len}")

threading.Thread(target=consumer, daemon=True).start()

with tstrans.srt.MuxSender.from_url(
    "srt://127.0.0.1:9001?mode=caller", program
) as tx:
    # tx.push_video / tx.push_klv handle bundling, PSI emission, and
    # ts-packet framing transparently.
    tx.push_video(nal_bytes, pts=Pts90khz.from_raw(0), key_frame=True)
    tx.push_klv(klv_ls_bytes, pts=Pts90khz.from_raw(0))

Builder + Socket promotion for fine-grained control (passphrase, custom latency, stream id, congestion mode):

import tstrans.srt

# Caller side with encryption + a custom SRT latency.
sock = (
    tstrans.srt.Builder("srt://127.0.0.1:9000?mode=caller")
    .passphrase("hunter-too-long-thanks!!")  # >= 10 chars
    .latency_ms(200)
    .stream_id("cam-01")
    .caller()
    .connect()
)
sender = sock.into_sender()  # consumes the Socket
sender.send_bytes(b"...")
sender.close()

Auto-reconnect with ManagedReceiver — wraps the underlying SRT transport in a tst_pipeline::ManagedRecvTransport that catches connection breaks, reconnects per a ReconnectPolicy, and surfaces a DemuxEvent.ReconnectDiscontinuity to the consumer:

import tstrans.srt
from tstrans.srt import BackoffStrategy, ReconnectPolicy

policy = ReconnectPolicy(
    max_attempts=5,
    backoff=BackoffStrategy.exponential(base_ms=100, max_ms=10_000),
)

with tstrans.srt.ManagedReceiver.from_url(
    "srt://:9000?mode=listener", policy=policy
) as rx:
    while True:
        try:
            chunk = rx.recv_bytes(max_len=1500)
            print(f"received {len(chunk)} bytes; "
                  f"reconnects so far = {rx.reconnect_attempts()}")
        except KeyboardInterrupt:
            break

The full surface — Sender / Receiver for raw bytes, MuxSender / DemuxReceiver for one-call mux/demux, Builder / Socket / Listener for low-level construction, ManagedSender / ManagedReceiver / ManagedMuxSender / ManagedDemuxReceiver for auto-reconnect, plus ReconnectPolicy / BackoffStrategy / OverflowPolicy policy types and SocketStats / SrtStats / CancelHandle — is documented in the per-class docstrings and the python/tstrans/srt.pyi type stubs (mypy --strict clean).

See also docs/languages/python.md for the broader Python binding guide.

See also

See docs/languages/python.md for the full guide and docs/languages/python.md for the DataFrame / NumPy integration.

Metadata

Release files for tstrans 0.6.0

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

Source distribution (sdist)

Source distribution for tstrans 0.6.0
File Size Uploaded
tstrans-0.6.0.tar.gz 6.8 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for tstrans 0.6.0
File
tstrans-0.6.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
tstrans-0.6.0-cp310-abi3-manylinux_2_28_x86_64.whl CPython 3.10 abi3 Linux glibc 2.28+ x86-64 Details
tstrans-0.6.0-cp310-abi3-manylinux_2_28_aarch64.whl CPython 3.10 abi3 Linux glibc 2.28+ ARM64 Details
tstrans-0.6.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details

Total release size: 22.4 MB

Release files / tstrans-0.6.0.tar.gz

Download URL tstrans-0.6.0.tar.gz
Size 6.8 MB
Tags Source
SHA-256 checksum
How to use checksums
ec139def42df0ed1e9f449ed6e1caea70a5ee301c9a2f3d8215404c95e849f0b
BLAKE2b-256 checksum
How to use checksums
080d5023947499cc0680ca13dd48ed8358cfebf563009a3b5479de00cc865e63
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 2, 2026.

Transparency log

Release files / tstrans-0.6.0-cp310-abi3-win_amd64.whl

Download URL tstrans-0.6.0-cp310-abi3-win_amd64.whl
Size 4.0 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
b5a4941470dc7346b062a98562c64a737029bbdc4953f777beab42a74b33f178
BLAKE2b-256 checksum
How to use checksums
5f6cabead1a49a20b7f1481f18087f540d008e63d05b57b924ceb8f508a5b763
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 2, 2026.

Transparency log

Release files / tstrans-0.6.0-cp310-abi3-manylinux_2_28_x86_64.whl

Download URL tstrans-0.6.0-cp310-abi3-manylinux_2_28_x86_64.whl
Size 4.2 MB
Tags CPython 3.10 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
1ad890fc5eef6d9517c7eef3ab03b1948f6619fb127086bf8aee104bb38b880e
BLAKE2b-256 checksum
How to use checksums
c05f568f25e1077c963ffac0642e37a88dc15ad63be7ef2dc9230f3f112e8b3d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 2, 2026.

Transparency log

Release files / tstrans-0.6.0-cp310-abi3-manylinux_2_28_aarch64.whl

Download URL tstrans-0.6.0-cp310-abi3-manylinux_2_28_aarch64.whl
Size 3.9 MB
Tags CPython 3.10 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
eb2d2019a741b03178084b6f1328b9af885145709c870615e674e8874d824e89
BLAKE2b-256 checksum
How to use checksums
db6d6e7f69b075bf680fa81885c4ecef2c08f1bc5d454523110851bcd72ff8b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 2, 2026.

Transparency log

Release files / tstrans-0.6.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL tstrans-0.6.0-cp310-abi3-macosx_11_0_arm64.whl
Size 3.5 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
bf4110b7a8dca7361db190c4500f7a2c37c88969fe66a5777bcb467b2ac5fe56
BLAKE2b-256 checksum
How to use checksums
47254ee6c2e147249d9d4232402fb81c46fc416bdc81e79c1b4fa3559689f19c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 2, 2026.

Transparency log

Release history Release notifications | RSS feed

0.8.0

5 release files

0.7.0

5 release files

This release

0.6.0 This release

5 release files

0.5.1

5 release files

0.5.0

5 release files

0.4.0

5 release files

0.3.0

5 release files

0.2.0

5 release files

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