Skip to content

Releases: facebookresearch/spdl

v0.3.0

23 Mar 15:42
138fcea

Choose a tag to compare

SPDL v0.3.0 Release Notes

Highlights

Polymorphic Aggregate API — The pipeline's aggregation stage now supports custom aggregation logic via the new Aggregator abstract base class. Subclass Aggregator and implement accumulate() / flush() methods for custom batching strategies (e.g., size-based batching, time-windowed aggregation, conditional grouping).
The built-in Collate class provides the previous fixed-size batching behavior. (#1289, #1291)

Streaming decoding now returns Iterators — Streaming decode methods (streaming_decode_packets and flush methods of AudioDecoder and VideoDecoder) now return proper Python iterators instead
of Optional[Frames]. This makes the interface more Pythonic and naturally handles cases where feeding packets or flushing produces multiple batches of frames. (#1280)

Fraction-based failure rate thresholds — Pipeline stages now support Fraction-based failure thresholds (e.g., Fraction(1, 10) for 10% max failure rate) in addition to absolute integer counts. (#1296)

BC-Breaking Changes

  • Streaming decoding returns Iterator instead of Optional[Frames] (#1280): Decoder.streaming_decode_packets() and Decoder.flush() now return iterator objects.
    Code that checked return values for None must migrate to iteration (for frames in decoder.streaming_decode_packets(packets)). ImageDecoder has been removed as a public class.
  • TaskHook.task_hook() signature changed (#1287): The task_hook() method now accepts an input_item parameter, allowing hooks to inspect which input item caused a failure. All existing TaskHook subclasses must update their signature from async def task_hook(self) to async def task_hook(self, input_item=None).
  • AggregateConfig now requires op parameter (#1291): AggregateConfig no longer accepts num_items directly. Migrate from AggregateConfig(..., num_items=N, ...) to AggregateConfig(..., op=Collate(N), ...), or use the convenience function Aggregate(N).

New Features

  • Add polymorphic Aggregate API with Aggregator base class and Collate built-in implementation (#1289)
  • Add set_buffer_size() for VideoDecoder to control the number of frames yielded per iteration during streaming decode (#1284)
  • Add GNU/PAX long filename extension support to iter_tar, enabling correct handling of archives with filenames exceeding the 100-byte TAR limit
    (#1283)
  • Add Fraction-based failure rate threshold support for pipeline stages (#1296)
  • Add p90 and p99 percentile tracking to pipeline performance stats (#1306)

Bug Fixes

  • Fix off-by-one error in max_failures threshold check — max_failures=N now correctly allows N failures before stopping (#1297)
  • Fix symbol resolution for removed ImageDecoder in __init__.py (#1292)
  • Fix implicit string concatenation issues (#1275)

Other Changes

  • Extract duplicated failure error raising logic into _FailCounter.raise_for_failures() (#1303)
  • Remove unused Python imports (#1282)
  • Add defaults for python_version and free_threaded fields in benchmark utilities (#1286)

Documentation

  • Fix docstrings (#1273, #1277)
  • Update installation docs — mention Windows support and component packages (#1281)

v0.2.0

07 Jan 12:31
91e1b7f

Choose a tag to compare

BC-breaking Changes

What's Changed

  • [io] Update the annotation of the high-level functions by @mthrok in #1247
  • [io] Warn only once about the fraction reduction by @mthrok in #1238
  • [io] Transfer only CPU tensors by @mthrok in #1254

Performance Improvements

  • [io] Pre-allocate output buffer when decoding with NVDEC by @mthrok in #1260

New Features

  • [io] Allow passing name to demuxer by @mthrok in #1245
  • [io] Add parse_wav function for WAV header metadata extraction by @mthrok in #1242
  • [io] Add compact log mode by @mthrok in #1248

BC-breaking changes

  • [io] Default to per-thread default stream by @mthrok in #1255
    When a CUDA stream is not specified, the CUDA-related IO functions defaulted to use the legacy default stream. Since SPDL IOs are intended for data loading happening outside of model computation, this has been changed to par-thread default stream. This allows to execute CUDA kernels without interrupting the legacy default stream by default.
  • [libspdl/io] Use batch allocation in NVDEC decoder by @mthrok in #1271
    Previously, the CUDA frame was allocated par each decoded frame. This turned out to be inefficient (See #1260) therefore the NVDEC decoder has been rewritten to pre-allocate a buffer for a batch of frames. To accommodate this change, the interface of streaming GPU decoding has been changed. The APIs for one-off decoding and streaming decoding were split. The new implementation process media by the number of fixed frames par API call.
  • [libspdl/IO] Update NV12 color conversion function by @mthrok in #1269, #1272
    Following the change in NVDEC decoder, the function for converting NV12 frames in CUDA memory is updated. The input format has been changed from list of single CUDA frames to a batched CUDA frames.

Bug fixes

  • [io] Handle RASL frames on best-effort basis by @mthrok in #1236
  • [io] Fix Decoder caching mechanism by @mthrok in #1241
  • [io] Use the specified CU stream in CUDA functions by @mthrok in #1256
  • [libspdl] Fix Generator move implementation by @mthrok in #1262

Documentation updates

Other changes

  • [libspdl] Optimize batched NV12 color conversion by @mthrok in #1267
  • [libspdl] Refactor implementation of NvDecDecoderCore by @mthrok in #1259
  • [libspdl] Refactor NVDEC decoder impl by @mthrok in #1261
  • [libspdl] Tweak Generator impl by @mthrok in #1263
  • [libspdl] Add C++ iterator support to Generator by @mthrok in #1264
  • [libspdl] Remove StreamingDemuxer wrapper by @mthrok in #1265
  • [libspdl] Fix conditional operator argument copy in decoder by @mthrok in #1270
  • [libspdl] Encapsulate frame buffer in NVDEC by @mthrok in #1268

Full Changelog: v0.1.7...v0.2.0

v0.1.7

08 Dec 16:44
c5dc4f6

Choose a tag to compare

SPDL v0.1.7 Release Notes

New major features

  • Sub-interpreter support for pipelines & iteration

    See also [RFC] Add run_pipeline_in_subinterpreter function

    • Add iterate_in_subinterpreter helper for running iterators in Python sub-interpreters.
      PR: #1088
    • Add run_pipeline_in_subinterpreter for executing Pipeline in a sub-interpreter.
      PR: #1098
    • Support PipelineConfig in run_pipeline_in_subprocess.
      PR: #1070, #1073, #1075
  • Rational handling for demuxing/decoding

    • Support fractional timestamps for media demuxing, allowing to avoid rounding error when passing timestamp as float.
      PR: #1194
  • Pipeline builder enhancements

    • Add a build callback hook to pipeline building.
      PR: #1162, #1215, #1208, #1207

      Combining the locate_source bellow, this allows to log the source of the pipeline being built. This is useful for large teams/organizations where multiple teams may be using SPDL, and can help to identify the source code of a pipeline when debugging its performance.

  • New utilities

    • Add utility locate_source to locate the source of Python objects and include source location in PipelineConfig.__repr__, improving debuggability.
      PRs: #1156, #1160
    • Add benchmark and example for exploring video decoder thread configuration, including doc integration and a result image.
      PRs: #1196, #1199, #1203

Improvements

  • Type system & interface files

    • Introduce interface files and refactor how extension classes are imported during type checking; gradually remove mock type stubs.
      PRs: #1131, #1132, #1133, #1137
    • Use pyre-strict in spdl.io.
      PR: #1128
    • Add script to create interface stubs and a job to check stubs.
      PRs: #918, #1134
  • Improved timestamp & rational handling for demuxing/decoding

    • Refactor rational handling and timestamp handling across demux/decoder paths (including Frames objects) for correctness and consistency.
      PRs:
      • #1197 (Rational handling refactor)
      • #1153 (update timestamp handling)
      • #1185 (fix integer overflow converting PTS to rational)
      • #1192 (fix timestamp from Frames)
      • #1152 (use stream time base when seeking)
      • #1154, #1221 (tests for demuxing/decoding with timestamps)
  • Gateway API / C++ integration changes

    • Make the gateway API mechanism dynamic, allowing more flexible interaction with C++ classes.
      PR: #1145
    • Remove Python wrappers for low-level C++ encoder/decoder and filter components (now accessed via the standardized gateway).
      PRs:
      • #1138 (remove Python wrapper for _Encoder/_Decoder)
      • #1141 (remove Python wrapper for FilterGraph)
      • #1189 (remove NvDecDecoder Python wrapper)

Bug fixes

  • GPU / NVDEC video decoding

    • Fix stale state in NVDEC decoder when cropping.
      PR: #1165
    • Ensure decoder cache is correctly cleared when requesting a non-cached decoder.
      PR: #1184
    • Fix streaming_load_video_nvdec behavior.
      PR: #1224
    • Fix ffmpeg CLI redirection in NVDEC tests (affects reliability of GPU decoding tests).
      PR: #1155
  • CUDA / memory

    • Fix race condition in CUDACachingAllocator.
      PR: #1082
  • Timestamps & demuxing

    • Fix integer overflow when converting PTS to rational type (part of the broader timestamp refactor).
      PR: #1185
    • Use stream time base for seeking to avoid incorrect seek positions.
      PR: #1152
    • Fix timestamps returned from Frames objects.
      PR: #1192
    • Add tests to cover timestamped demuxing and decode windows.
      PRs: #1154, #1221
  • I/O, filters and frames

    • Fix function to fetch FFmpeg filters.
      PR: #1222
    • Store original data references in reference audio/video frames to prevent unwanted copies and lifetime issues.
      PR: #1176
    • Tweak bitstream filter (BSF) implementation for correctness/robustness.
      PR: #1144
  • Subprocess / pipeline / utilities

    • Make subprocess tests more robust.
      PR: #1090
    • Ensure pipeline global ID is inherited correctly in subprocesses.
      PR: #1091
    • Fix GC warning tests and improve cleanup behavior; generalize cleanup and ensure upstream pipelines are properly cleaned up.
      PRs: #1097, #1207, #1208
    • Fix the case where locate_source could hang.
      PR: #1216
    • Ensure pipeline global IDs are correctly inherited in subprocesses.
      PR: #1091
  • Type checking / stubs

  • OSS & packaging

    • Fix CUDA extension packaging.
      PR: #1168
    • Fix OSS build and OSS doc build issues.
      PRs: #1200, #1205

BC-breaking changes

  • Removal of deprecated API

    • Remove deprecated Demuxer.streaming_demux_video.
      PR: #1140
  • Removal of compatibility arguments and methods

    • Remove various compatibility arguments and methods that had been kept for backward compatibility.
      PR: #1225

Documentation updates

  • New and expanded docs on I/O

    • High-level I/O functions overview.
      PR: #1100
    • Low-level I/O functions.
      PR: #1101
    • Filtering in I/O pipelines.
      PR: #1102
    • Streaming decoding.
      PR: #1103
    • Remote iterable protocol doc fixes/updates.
      PR: #1104
    • NumPy I/O usage guide.
      PR: #1110
  • GPU video decoder / encoding docs

Read more

v0.1.6

28 Oct 18:43
b10f186

Choose a tag to compare

What's New

Bugfix

What's Changed

Examples

Packaging

Documentation Update

  • Mention diagnostic mode in profile_pipeline function by @mthrok in #1013

Internal / Refactor

Full Changelog: v0.1.5...v0.1.6

v0.1.5

15 Oct 14:24
09a52e9

Choose a tag to compare

What's new

New Python version support

The spdl-io packages now include binaries for Python 3.13t, 3.14 and 3.14t on all supported platforms (macOS, Linux aarch64, Linux x86_64 and Windows).
They are now compiled with CUDA 12.8.1.

(spdl-core remains pure Python package without any dependency.)

Pipeline profiling and self-diagnostic mode

Pipeline profiling function
The spdl.pipeline.profile_pipeline function is added.
This function executes each stage separately with different multi-threading concurrency and reports the speed of executions. This helps find how each stage function scales with multi-threading.
Please check out the example for the usage and what you can infer from the profiling result.

Self-diagnostic mode
By setting environment variable SPDL_PIPELINE_DIAGNOSTIC_MODE=1, the Pipeline is built with self-diagnostic mode.
In this mode, internally it calls the profile_pipeline and exit.
This helps profiling the pipeline in production environment without changing the code.

(contributed by @ncorriveau and @mthrok)

Support for sub-pipelines

A new pipeline definition component, spdl.pipeline.defs.MergeConfig and its factory function spdl.pipeline.defs.Merge
have been added.
This allows to merge multiple pipelines and attach downstream stages.
Please check out the example for the usage.

spdl.io.load_wav for loading WAV from memory without copy

The spdl.io.load_wav function is added. This function is specialized for loading WAV audio from memory. It does not make any copy, so it is very fast. Please refer to the benchmark.

spdl.io.iter_tarfile for iterating TAR files

The spdl.io.iter_tarfile function is added. This function can iterate on TAR file in memory or file-like object. It is at least as fast as Python's built-in tarfile module. If the input is bytes type, then it can perform zero-copy parsing. (Proposed by @nicolas-dufour, @npuichigo [discussion])

Updates on failure monitoring mechanism

Pass max_failures to spdl.pipeline.PipelineBuilder.pipe method, or spdl.pipeline.defs.Pipe function.

  • Fix the way failed stages are reported (#1006)
    When a pipeline stage fails more than it is allowed, the pipeline fails with error message. Previously all the stages were included in the message. Now, only the stages that actually failed are included.

What's Changed

  • zlib is statically linked in Linux/macOS binaries
    Previously, the spdl_io packages required an external installation of zlib for Linux and macOS, while it was statically linked in Windows packages. Now zlib is also statically linked in Linux/macOS, making NumPy the only required dependency of spdl-io,

  • Pipeline definitions are frozen by @mthrok in #966

New Contributors

Full Changelog: v0.1.4...v0.1.5

v0.1.4

10 Sep 19:37
a7cb787

Choose a tag to compare

New features

Config-based Pipeline constructions.

The newly introduced spdl.pipeline.defs module contains the definitions and helper functions you can use to build Pipeline object with declarative manner. For the detail, please refer to #902

You can now construct Pipeline in the following ways. Also please checkout the Hydra Integration Example.

PipelineBuilder (existing) PipelineDefinition (new) Hydra
builder = (
    PipelineBuilder()
    .add_source(Sampler())
    .pipe(
        funcA,
        concurrency=...)
    .pipe(
        funcB,
        concurrency=...,
        executor=...)
    .sink(...)
)
pipeline = builder.build(
    num_threads=...)
pdef = PipelineConfig(
    src=Sampler(),
    stages=[
        PipeConfig(
            funcA,
            concurrency=...),
        PipeConfig(
            funcB,
            concurrency=...,
            executor=...),
    ],
    sink=...
)
pipeline = build_pipeline(
    pdef, num_threads=...)
_target_: build_pipeline
num_threads: ...
definition:
  _target_: PipelineConfig
  src:
    _target_: Sampler
  stages:
  - _target_: PipeConfig:
    op: funcA
    concurrency: ...
  - _target_: PipeConfig:
    op: funcB
    concurrency: ...
    executor: ...
  sink:
    ...

[Experimental] Windows Support

SPDL I/O now supports building on Windows. The binary distribution contains CUDA integration and NVDEC support.

Logging change

Previously, if a function passed to a pipe fails, the error was logged in one line. Now the full stack trace is printed.

Bug fix

What's Changed

v0.1.3

01 Sep 15:21
0479641

Choose a tag to compare

New features

  • Support clases with __getitem__ method in pipe by @mthrok in #872
  • Add VideoPackets.get_timestamps method by @mthrok in #875
  • Add VideoFrames::get_timestamp method by @mthrok in #877
  • Add VideoFrames.get_pts / time_base attributes to VideoFrames by @mthrok in #883
  • Add support for FFmpeg 8 #869

Bug fix

  • Fix the handling of StopAsyncIterator for FailCounter by @moto-meta in #862
  • Fix include by @mthrok in #874
  • Correctly detect that callable is a generator when it is a class's call method by @yit-b in #870
  • Fix type stub by @mthrok in #884

What's Changed

  • Update imagenet example by @mthrok in #860
  • Add debug print for pipeline structure by @mthrok in #868
  • Define a dedicated type alias for pipe input by @mthrok in #885

Full Changelog: v0.1.2...v0.1.3

v0.1.2

21 Aug 14:27
55b6156

Choose a tag to compare

New features

What's Changed

Documentation updates

BC-breaking changes

Full Changelog: v0.1.1...v0.1.2

v0.1.1

01 Jul 10:43
e3286d2

Choose a tag to compare

BC-breaking changes

  • Replace run_pipeline_in_subprocess impl by @moto-meta in #780

    Previously run_pipeline_in_subprocess returned an iterator and was not reusable.
    Now it returns an iterable, which can be iterated multiple times.
    Following this change, the object returned from run_pipeline_in_subprocess does not provide iterator-specific method such as next

    Example
    # Construct a builder
    builder = (
        spdl.pipeline.PipelineBuilder()
        .add_source(...)
        .pipe(...)
        ...
        .add_sink(...)
    )
    
    # Move it to the subprocess, build the Pipeline
    iterable = run_pipeline_in_subprocess(builder, ...)
    
    # Iterate - epoch 0
    for item in iterable:
        ...
    
    # Iterate - epoch 1
    for item in iterable:
        ...

What's Changed

  • Support multiple initializers in iterate_in_subprocess and run_pipeline_insubprocess by @mthrok in #783
    Now you can pass multiple initializer functions to iterate_in_subprocess and run_pipeline_insubprocess which are called in the subprocess before the first iteration starts.
  • Allow Zero Weights in MergeIterator by @vbourgin in #784
    Previously, the MergeIterator did not allow 0 value as weights. Now this is relaxed and you can pass 0.
    The iterators with 0 weight are not iterated.
  • Shuffle Before Iterating by Default for embed_shuffle by @vbourgin in #785
    Previously, embed_shuffle defaulted to shuffle after each iteration, but this was counter-intuitive.
    Now the default behavior is to shuffle before each iteration.
  • Adhere to PEP 561 (Fixes a mypy bug) by @alxmrs in #790
    Now SPDL package contain py.typed file so that type-checkers can analyze the code.
  • Ensure core bindings is loaded when loading CUDA binding by @mthrok in #792
    When loading CUDA extension in spdl.io module, it ensures that the CPU extension is loaded.
  • Support batch loading images with NVJPEG by @mthrok in #794
    The spdl.io.decode_image_nvjpeg function supports loading multiple images. (Note that the function is still experimental.)
  • Enable compilation warnings by @mthrok in #806, #821
    The C++ code of spdl.io is hardened by turning few selected compiler warnings into error.
  • Fix nanobind option for archive module by @mthrok in #814
    The extension module for archive (zip) parsing was not compiled with free-threading support.
  • Mypy type-checking feedback for all "pyre safe" sources. by @alxmrs in #801
    Now CI mypy type checking. The mypy compatibility is not enforced at the moment as pyre has been (and still is) used. We plan to gradually make the codebase compatible with mypy.

New Contributors

Full Changelog: v0.1.0...v0.1.1

v0.1.0

10 Jun 22:50
7e0f36f

Choose a tag to compare

What's Changed

  • [BC-breaking] Replace load_npz implementation by @mthrok in #739
  • [BC-breaking] Remove fallback for API transition by @mthrok in #770
  • [BC-breaking] Replace iterate_in_subprocess implementation by #776 @mthrok in #779
  • Add support for DEFLATE algorithm by @mthrok in #744
  • Name threads by @mthrok in #728
  • Update load_npy to accept memoryview by @mthrok in #738
  • Remove libzip dependency by @mthrok in #746
  • Default to the default context by @mthrok in #762
  • Revise the way periodic task is terminated by @mthrok in #768
  • Add the funtionality to suppress repeated errors in spdl by @gregorpm in #773
  • Add function to convert IterableWithShuffle to Iterable by @mthrok in #775, #777

Examples

  • Add example to benchmark IO functions by @mthrok in #730

Docs

Full Changelog: v0.0.14...v0.1.0