MPEG-TS video + MISB KLV streaming — mux/demux, typed KLV (ST 0601/0102/0605/0903), codec parsers, and live SRT/RTP/UDP/TCP/RIST transports
Project description
tstrans
Python bindings (via PyO3) for the ts-transformer Rust workspace.
Status:
tstranscovers file inspection + construction (Demuxer/Muxer/MuxerFileSink), typed KLV decode + encode for ST 0601 / ST 0102 / ST 0605 / ST 0903 (withVTargetPack), codec parsers for H.264 / H.265 / H.266 / AV1 / AAC / MPEG-2 audio, optional pandas DataFrame adapters + NumPy snapshot views viapip 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.Klv(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.5 — 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.Klv):
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tstrans-0.2.0.tar.gz.
File metadata
- Download URL: tstrans-0.2.0.tar.gz
- Upload date:
- Size: 2.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
603782aca773a24ff3ff79b79504f43b0c060f9a12458dc49ffa51c3b3134169
|
|
| MD5 |
1699a8a092249f6b23fb9c5585c4945f
|
|
| BLAKE2b-256 |
fd152baed59125e7b9b5bd121787fe2d31b09ad6235aa924b177fa5afab3acfb
|
Provenance
The following attestation bundles were made for tstrans-0.2.0.tar.gz:
Publisher:
python-wheels.yml on aklofas/ts-transformer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tstrans-0.2.0.tar.gz -
Subject digest:
603782aca773a24ff3ff79b79504f43b0c060f9a12458dc49ffa51c3b3134169 - Sigstore transparency entry: 1921281723
- Sigstore integration time:
-
Permalink:
aklofas/ts-transformer@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/aklofas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-wheels.yml@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tstrans-0.2.0-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: tstrans-0.2.0-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 2.3 MB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7db3462d8495f0946a058765116ff558e86168aad03e964c72975781a7505671
|
|
| MD5 |
4978c1a6cc00a0719b218586327b4bc9
|
|
| BLAKE2b-256 |
3746e34cb2b530792ff5bc3d9e6b8e9fef1312ab4209bfd818f47a8798f2f516
|
Provenance
The following attestation bundles were made for tstrans-0.2.0-cp310-abi3-win_amd64.whl:
Publisher:
python-wheels.yml on aklofas/ts-transformer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tstrans-0.2.0-cp310-abi3-win_amd64.whl -
Subject digest:
7db3462d8495f0946a058765116ff558e86168aad03e964c72975781a7505671 - Sigstore transparency entry: 1921281896
- Sigstore integration time:
-
Permalink:
aklofas/ts-transformer@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/aklofas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-wheels.yml@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tstrans-0.2.0-cp310-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: tstrans-0.2.0-cp310-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc7a567e62247fd35e2cebf1d5dadd6fe791e32ffa3aaa7f32bcf8dc7d487147
|
|
| MD5 |
2133855e0ae651146b2271f5b8fad4e7
|
|
| BLAKE2b-256 |
91cd53f07d1c2e90d3ca20ad52ac1d6cd8ebbae8eb78bf0016f3d399b10413b5
|
Provenance
The following attestation bundles were made for tstrans-0.2.0-cp310-abi3-manylinux_2_28_x86_64.whl:
Publisher:
python-wheels.yml on aklofas/ts-transformer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tstrans-0.2.0-cp310-abi3-manylinux_2_28_x86_64.whl -
Subject digest:
dc7a567e62247fd35e2cebf1d5dadd6fe791e32ffa3aaa7f32bcf8dc7d487147 - Sigstore transparency entry: 1921281829
- Sigstore integration time:
-
Permalink:
aklofas/ts-transformer@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/aklofas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-wheels.yml@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tstrans-0.2.0-cp310-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: tstrans-0.2.0-cp310-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 2.3 MB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f9174d841a3c5b52e0cc023090526c5dbbf49c31c3032025f274a5f7564e548
|
|
| MD5 |
ead6b3fb197e740194162ae42fa4989c
|
|
| BLAKE2b-256 |
ece467cd08b8e2d909c42d3bf901f60ee08750b509b5f120e30d56a554e1d616
|
Provenance
The following attestation bundles were made for tstrans-0.2.0-cp310-abi3-manylinux_2_28_aarch64.whl:
Publisher:
python-wheels.yml on aklofas/ts-transformer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tstrans-0.2.0-cp310-abi3-manylinux_2_28_aarch64.whl -
Subject digest:
2f9174d841a3c5b52e0cc023090526c5dbbf49c31c3032025f274a5f7564e548 - Sigstore transparency entry: 1921281782
- Sigstore integration time:
-
Permalink:
aklofas/ts-transformer@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/aklofas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-wheels.yml@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tstrans-0.2.0-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: tstrans-0.2.0-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.9 MB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6dd2eedab2e8612d0a9dc4f242e0d79c166402d4bb75123bd13f48a5941b61c
|
|
| MD5 |
3d40b8920b53344bcedba6349d4d85d3
|
|
| BLAKE2b-256 |
7a39f49ac7f5e535e0f116f44bce5d1063f3ed47b1b37d203413b7232634a675
|
Provenance
The following attestation bundles were made for tstrans-0.2.0-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
python-wheels.yml on aklofas/ts-transformer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tstrans-0.2.0-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
a6dd2eedab2e8612d0a9dc4f242e0d79c166402d4bb75123bd13f48a5941b61c - Sigstore transparency entry: 1921281959
- Sigstore integration time:
-
Permalink:
aklofas/ts-transformer@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/aklofas
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-wheels.yml@1f6f86e0bb5e1694e832821f2fc4fbb1cca48d70 -
Trigger Event:
push
-
Statement type: