Skip to main content

pixtreme-transport-ndi

Full NDI® video and audio output for pixtreme.transport. NDI® is a registered trademark of Vizrt NDI AB. See NDI.

Send processed GPU frames from a transport core FrameBuffer to NDI receivers. The package provides the Python Output factory, a C++ shared library, public headers, a CMake package, and a bundled libndi runtime. It provides output only.

Installation

pip install pixtreme-transport-ndi

Supported wheels target Linux x86_64 (including WSL2), CPython 3.12 and 3.13, and manylinux_2_28_x86_64 (glibc 2.28 or newer). Processing requires an NVIDIA GPU and a driver that supports CUDA 13. The transport core supplies CUDA kernels for sm 86, sm 89, and sm 120. The wheel requires no CUDA Toolkit or NDI SDK installation.

Avahi's libavahi-client.so.3, libavahi-common.so.3, and their dependencies must be installed on the host. Install libavahi-client3 on Debian/Ubuntu or avahi-libs on RHEL-family systems. NDI mDNS discovery also needs a running avahi-daemon. Import errors identify a missing Avahi library and the packages to install.

The dependency pixtreme-transport>=0.17.1 installs the transport core, which supplies frame types, buffers, worker threads, audio processing, and pixel serialization. Its native ABI must match the ABI used to build this module; import rejects an incompatible core before loading the NDI extension. The core library stays in its own wheel. This package installs libndi under its own _ndi directory and uses relative library paths, so LD_LIBRARY_PATH is not needed to locate the installed NDI and core libraries.

Using the output

from fractions import Fraction
from pixtreme.transport.ndi import Output
from pixtreme.transport.session import ExitSettings, FrameBuffer

post = FrameBuffer(2)
settings = ExitSettings(Fraction(1001, 30000))  # 30000/1001 fps
settings.audio.enabled = True
settings.audio.accepted_formats = [
    (48000, 2, "stereo", "s16le"),
    (48000, 2, "stereo", "f32le"),
]
settings.audio.output_format = (48000, 2, "stereo", "f32le")
settings.audio.target_format = "FLTP"
settings.ancillary_kinds = ["caption"]

output = Output(0, post, settings, "Processed output")
output.open()
try:
    for frame in processed_frames:  # TransportFrame values from your pipeline.
        post.put(frame)
    post.close()
    output.join()
finally:
    output.close()

Output(device, buffer, settings, name) requires all four arguments. Device numbers follow the core's CUDA device selection. Output returns the core's Exit, with open, request_stop, join, close, check, and inspection. open() creates the NDI source; video begins after the first frame is acquired. The output never closes the caller's buffer. Output is a factory function; use isinstance(output, Exit) to check the returned session, with Exit imported from pixtreme.transport.session.

ExitSettings.prefill_frames defaults to 2. Set it to 1 to start with one buffered frame. The value must be positive and fit the buffer's capacity. Closing the buffer drains its remaining frames even below that count. While an open buffer has no new frame, the output repeats the latest picture with silent audio. request_stop() stops acquisition and drains accepted work; close() joins the workers and destroys the source.

Video, audio, and timecode

The NDI SDK video clock controls the sending interval. The output uses Pacing.SDK_CLOCK with clock_video enabled and clock_audio disabled. Resolution follows each input image, and frame rate follows ExitSettings.frame_period. Image widths must be divisible by two.

RGB images (without a matrix) are serialized as RGBA; images without alpha receive opaque alpha. YCbCr images (with a matrix) are serialized as UYVY: 8-bit 4:2:2, legal range, with byte order Cb0, Y0, Cr0, Y1. The output preserves the input matrix, colorspace, and transfer function. Convert incompatible images in your pipeline before submitting them.

NDI interprets UYVY colour according to the image resolution:

Resolution Required matrix Required colorspace
Width > 1920 or height > 1080 BT.2020 Rec.2020
Otherwise, width > 720 or height > 576 BT.709 Rec.709
Otherwise BT.601 Preserved from the input

An incompatible YCbCr image stops the output before reaching the SDK. The error identifies its matrix, colorspace, resolution, and the required NDI standard. The core serializes pixels into page-locked host memory, which the output passes directly to the SDK. That memory remains valid until serialization and SDK reads finish, including during shutdown.

When audio is enabled, the core supplies interleaved f32le PCM at the requested sample rate and channel layout. The output rearranges it into NDI's planar float layout without changing sample values or counts. The core handles dropped frames, repeats, padding, and trimming. At 48 kHz and 30000/1001 fps, five periods contain 8008 samples per channel. Disabled audio is not sent.

An input FrameTiming.source_timecode is converted to the NDI video frame's 100 ns timecode units. Its displayed hours, minutes, seconds, and nominal-rate frame fraction are preserved, including for drop-frame labels. Fractional ticks round to the nearest integer, with halves rounding up. Repeated pictures retain that input timecode. Pictures without an input timecode receive the current system time on every send, including repeats.

Ancillary metadata

Declare accepted kinds in settings.ancillary_kinds; the core rejects undeclared kinds. Each new picture's AncillaryData.items becomes XML in the NDI video frame's metadata:

<pixtreme_ancillary encoding="base64"><item kind="Y2FwdGlvbg==">PCY=</item></pixtreme_ancillary>

The example carries kind caption and payload bytes <&. Each AncillaryItem becomes one item; its kind and payload use standard padded base64. Order, duplicate kinds, opaque bytes, and empty payloads are preserved. Empty collections produce no metadata. Repeats omit the original ancillary metadata.

C++ integration

The wheel installs its CMake package under pixtreme/transport/ndi/cmake. Set pixtreme-transport-ndi_DIR to that directory and pixtreme_transport_DIR to the core's CMake directory, call find_package(pixtreme-transport-ndi CONFIG REQUIRED), and link pixtreme::ndi. Include <pixtreme/transport/ndi/output.hpp> to use Output. Public headers require the core SDK and do not require NDI SDK headers. The C session owns the NDI sender; the C++ Output is a view of that session. Close the session explicitly or release its last owning handle to stop it. Overriding the C++ view's processing hooks to replace NDI sending is not supported.

License

This module's code is distributed under the MIT license.

The bundled libndi is subject to the NDI SDK License Agreement and the notices in libndi_licenses.txt. The wheel includes the complete nanobind and robin_map license texts and a libndi notice in its .dist-info/licenses/ directory.

NDI terms and attribution

libndi is bundled with libndi_licenses.txt. NDI SDK redistribution remains subject to its license conditions. Applications using NDI must supply the applicable SDK license terms and notices to users, link to NDI, and show the NDI® trademark and the attribution “NDI® is a registered trademark of Vizrt NDI AB” near NDI selection or use, in their About box, and in their trademark notices.

Metadata

Release files for pixtreme-transport-ndi 0.3.0

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

Built distributions (wheels)

Table of built distributions (wheels) for pixtreme-transport-ndi 0.3.0
File Interpreter ABI Platform
pixtreme_transport_ndi-0.3.0-cp313-cp313-manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64 Details
pixtreme_transport_ndi-0.3.0-cp312-cp312-manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64 Details

Total release size: 7.0 MB

Release files / pixtreme_transport_ndi-0.3.0-cp313-cp313-manylinux_2_28_x86_64.whl

Download URL pixtreme_transport_ndi-0.3.0-cp313-cp313-manylinux_2_28_x86_64.whl
Size 3.5 MB
Tags CPython 3.13 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
fa96c2dee09f1d50e4d5e3b398e809c9b9c2d92e13a7579fcc0b00d84f87d383
BLAKE2b-256 checksum
How to use checksums
023bfbcd929ad89fec0fbe205c1fe1f76ec143abd462190ff550b2b1adb78a75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.22

Release files / pixtreme_transport_ndi-0.3.0-cp312-cp312-manylinux_2_28_x86_64.whl

Download URL pixtreme_transport_ndi-0.3.0-cp312-cp312-manylinux_2_28_x86_64.whl
Size 3.5 MB
Tags CPython 3.12 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
68d8e4fa65c48be199bf6dda27fec5e94bcfed3d031a962febd8a0a4c6551c27
BLAKE2b-256 checksum
How to use checksums
e30e34a921b52d28f893f47e0233bdad2bc9f5d2f2d18507c8cf8b3b6620ae28
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.22

Security for pixtreme-transport-ndi 0.3.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files No provenance

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