NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #2239 most downloaded on PyPI
A video decoder for PyTorch
Last release 4 days ago
30 Sep 2026
Ships fairly regularly
a new release about every 5 weeks
Most releases are documented
notes for 22 of 25 stable releases
Nothing withdrawn
no release was ever pulled
2 years old
26 releases · first in 2024
Nothing published for this version
These image decoders and encoders replace their torchvision counterparts, which are now deprecated.
TorchCodec 0.16 is out! It is compatible with torch >= 2.11. The headline feature of this release is image decoding and encoding: TorchCodec now natively decodes and encodes JPEG (CPU and CUDA), PNG, WebP, GIF, AVIF and HEIC. These image decoders and encoders replace their torchvision counterparts, which are now deprecated.
TorchCodec is the recommended way to decode and encode images in the PyTorch ecosystem. If you are coming from torchvision, we wrote a migration guide
TorchCodec exposes one entry-point per format, plus a generic decode_image() that automatically detects the format. The API is largely backward-compatible with TorchVision:
from torchcodec.decoders import decode_image, decode_jpeg, decode_png
img = decode_image("image.jpg") # CHW uint8 tensor, format auto-detected
img = decode_image("image.avif")
img = decode_image("image.heic")
# Or use the format-specific decoders for format-specific options
img = decode_jpeg("image.jpg", device="cuda")
Sources can be a path (str or pathlib.Path), bytes, or a 1D uint8 tensor of encoded bytes:
img = decode_image(open("image.png", "rb").read())
img = decode_image(torch.frombuffer(encoded_bytes, dtype=torch.uint8))
Animated and multi-image formats (WebP, GIF, AVIF, HEIC) decode into an (N, C, H, W) tensor:
from torchcodec.decoders import decode_gif
frames = decode_gif("animated.gif") # (N, C, H, W)
JPEG decoding is also supported on CUDA, through nvJPEG. For CUDA, prefer passing a batch of sources: the whole batch is decoded in a single nvJPEG call, which is much faster than decoding images one at a time.
from torchcodec.decoders import decode_jpeg
imgs = decode_jpeg(["a.jpg", "b.jpg", "c.jpg"], device="cuda") # list of CUDA tensors
Read more in our image decoding tutorial
Image encoders follow the same class-based design as our video and audio encoders: build the encoder from a CHW uint8 tensor, then choose where the encoded bytes go: a file, a file-like object, or a tensor.
from torchcodec.encoders import JpegEncoder, PngEncoder
JpegEncoder(img).to_file("image.jpg", quality=90)
PngEncoder(img).to_file("image.png", compression_level=9)
# ... or to a file-like object
import io
buffer = io.BytesIO()
JpegEncoder(img).to_file_like(buffer)
# ... or to a 1D uint8 tensor of encoded bytes
encoded = PngEncoder(img).to_tensor()
JPEG encoding is supported on CUDA as well: pass a CUDA tensor and the encoding happens on the GPU with nvJPEG, with to_tensor() returning a CUDA tensor (no host round-trip).
encoded = JpegEncoder(img_on_cuda).to_tensor(quality=90) # CUDA uint8 tensor
Read more in our image encoding tutorial
The image decoders and encoders were migrated from torchvision and torchvision-extra-decoders, with the same performance, and they are significantly more capable:
UNCHANGED, GRAY, GRAY_ALPHA, RGB, RGB_ALPHA. torchvision only supports GRAY for PNG and JPEG, and rejects or ignores it elsewhere.(N, C, H, W). torchvision rejects animated WebP, errors on multi-image AVIF, and only decodes the primary HEIC image.output_dtype control (torch.uint8, torch.uint16, or "auto") on every decoder. torchvision has no equivalent: the output dtype is dictated by the source.decode_image() auto-detects all six formats, including AVIF and HEIC. torchvision only handles four.str/Path/bytes/Tensor everywhere, non-contiguous encoded input accepted, and batched input for JPEG on both CPU and CUDA.libheif is found at runtime. We don't bundle it because it is LGPL, so install it yourself (e.g. conda install -c conda-forge libheif). Torchvision required the separate torchvision-extra-decoders package for both, and its decode_image couldn't dispatch to them.Along the way we fixed a number of correctness bugs inherited from torchvision, among them: PNG palette and tRNS transparency handling, GIF frame disposal (now aligned with Pillow), truncated JPEGs erroring instead of returning garbage, correct CMYK/YCCK handling, real grayscale for WebP, progressive AVIF stills, and full-range >8-bit HEIC output.
If you are coming from torchvision, we wrote a migration guide
import torchcodec no longer fails at import time if FFmpeg cannot be found. FFmpeg is still required for video and audio decoding and encoding, but the image decoders and encoders don't need FFmpeg and work in FFmpeg-free environments.
TorchCodec now support the recently released FFmpeg 9!
AudioDecoder seeks on MPEG-PS files (#1619).to_tensor() no longer emits a spurious warning (#1510).One column per month.
TorchCodec 0.15 is out! This is a small release compatible with torch >= 2.11, with the following improvements:
TorchCodec 0.15 is out! This is a small release compatible with torch >= 2.11, with the following improvements:
num_ffmpeg_threads is high.TorchCodec 0.14 is out! It is compatible with torch >= 2.11. It comes with two major additions: a fast audio `WavDecoder`, and support for HDR video d
TorchCodec 0.14 is out! It is compatible with torch >= 2.11. It comes with two major additions: a fast audio WavDecoder, and support for HDR video decoding!
Inspired by SDPL's fast wav decoder, TorchCodec now has a dedicated WavDecoder for decoding WAV files. It bypasses FFmpeg entirely and reads WAV data directly, resulting in significantly faster decoding. It supports multiple sample formats (int16, int32, float32, etc.), and can decode from files, bytes, or file-like objects.
from torchcodec.decoders import WavDecoder
decoder = WavDecoder("audio.wav")
samples = decoder.get_all_samples() # AudioSamples with data and sample_rate
VideoDecoder now supports HDR (High Dynamic Range) video decoding without losing precision. When output_dtype=torch.float32 is specified, the decoder outputs RGB float32 frames in [0, 1], preserving the full HDR color range. This is supported for both CPU and CUDA!
import torch
from torchcodec.decoders import VideoDecoder
decoder = VideoDecoder("hdr_video.mp4", output_dtype=torch.float32)
frame = decoder[0] # Full HDR precision in float32
⚠️ This feature is in beta stage, so behavior may slightly change depending on user feedback. Let us know if you encounter any issue!
AudioDecoder seeking is now much faster (#1449)TorchCodec no longer depends on NVIDIA's NPP library, which will simplify installing and using TorchCodec for CUDA decoding.TorchCodec 0.13 is out! It is compatible with torch >= 2.11, and it is packed with new features.
TorchCodec 0.13 is out! It is compatible with torch >= 2.11, and it is packed with new features.
This release comes with a new major feature: the multi-stream Encoder! The Encoder supports multiple streams and incremental encoding. Frames and samples can be added progressively, which is useful when data is generated on-the-fly or when encoding both audio and video into the same container.
from torchcodec.encoders import Encoder
encoder = Encoder()
video_stream = encoder.add_video(height=256, width=256, frame_rate=30)
audio_stream = encoder.add_audio(sample_rate=16000, num_channels=1)
with encoder.open_file("output.mp4"):
video_stream.add_frames(frames_tensor)
audio_stream.add_samples(samples_tensor)
# Add more frames by calling video_stream.add_frames again
# Add more samples by calling audio_stream.add_samples again
The Encoder also supports CUDA encoding! Read more in our docs!
Based on popular requests, we are now shipping aarch64 CPU wheels and Windows CUDA wheels. Both are in beta status, so let us know if you encounter any issue. See our installation instructions for more details.
TorchCodec now officially supports the following platforms:
pip install torchcodec should now install the CUDA wheels by default on Linux x86 and aarch64. Those wheels should still work even if you do not have a CUDA GPU, or if you are missing CUDA dependencies. Let us know if you encounter any issue.
To install the CPU-only wheels, please refer to our installation instructions.
TorchCodec 0.12 is out! This is a small release that focuses on completing the stable ABI migration and switching our default cuda backend to the fast
TorchCodec 0.12 is out! This is a small release that focuses on completing the stable ABI migration and switching our default cuda backend to the faster backend. In 0.12, we are also aligning with pytorch repo’s cuda support by dropping cuda 12.8 and adding support for cuda 13.2.
Starting in TorchCodec 0.12, the faster CUDA backend (previously known as ‘beta’) becomes the default backend. This will be a transparent and backward-compatible change.
# Previously, this used the slower 'FFmpeg' backend.
# Now this uses the faster backend by default.
decoder = VideoDecoder(..., device="cuda")
Users who want to stay on the less efficient FFmpeg backend should explicitly use set_cuda_backend:
with set_cuda_backend("ffmpeg"):
decoder = VideoDecoder(..., device="cuda")
TorchCodec 0.12 will be ABI stable from torch 2.11 (yes, 2.11)! Previously, each new version of torch required a corresponding version of TorchCodec, which made dependency management complex for users. From 0.12, TorchCodec should be largely forward-compatible with future versions of torch, simplifying the installation and dependency management process.
We are releasing TorchCodec 0.11.1 as a bug-fix release, and it is compatible with torch 2.11.
We are releasing TorchCodec 0.11.1 as a bug-fix release, and it is compatible with torch 2.11.
In 0.11, we began uploading CUDA 13.0 linux wheels to PyPI, so pip install torchcodec would install a CUDA enabled wheel. This caused an error at import time for users without the necessary CUDA libraries, or for users who only wanted to use CPU decoding.
Torchcodec 0.11.1 reverts this change, so pip install torchcodec will install the CPU wheel. We will resume uploading CUDA wheels as torch does in torchcodec version 0.12!
As before, CUDA wheels are available by specifying the index-url argument:
pip install torchcodec --index-url --index-url https://download.pytorch.org/whl/cu130
⚠️ Note that this is a BC-breaking change since we consider it a bug fix. Read more about this in the VideoStreamMetadata docs!
TorchCodec 0.11 is out! This release brings CUDA decoding improvements and improved HDR metadata and rotation support in VideoDecoder, as well as output fps support!
We made significant improvements to the CUDA decoder throughput, available via the “beta” backend:
These are available via the “beta” backend”.
⚠️ Note that in the next release, the “beta” backend will become the default backend. This will be a transparent and backward-compatible change. Users who want to stay on the less efficient FFmpeg backend should use:
with set_cuda_backend("ffmpeg"):
decoder = VideoDecoder(..., device="cuda")
Read more about this in the CUDA utilities section!
get_frames_played_in_range() now accepts a fps parameter to resample video at a target frame rate, duplicating or dropping frames as necessary to match the desired output FPS:
decoder = VideoDecoder(path)
# If a source video is 25 fps, a 1-second range will contain 25 frames.
# We can use the fps argument to resample to 5 fps, which gives us 5 frames:
frames_5fps = decoder.get_frames_played_in_range(start_seconds=1, stop_seconds=2, fps=5)
Read the VideoDecoder docs for more details!
(#1148)
TorchCodec now automatically applies rotation metadata during video decoding on CPU and Beta Cuda backend.
decoder = VideoDecoder(path)
print(decoder.metadata.rotation) # e.g. 90.0, or None
⚠️ Note that this is a BC-breaking change since we consider it a bug fix. Read more about this in the VideoStreamMetadata docs!
Video Decoder metadata now exposes color-related metadata and pixel format, making it easy to identify HDR content:
metadata = VideoDecoder(path).metadata
print(metadata.color_primaries) # e.g. "bt2020"
print(metadata.color_space) # e.g. "bt2020nc"
print(metadata.color_transfer) # e.g. "smpte2084"
print(metadata.pixel_format) # e.g. "yuv420p10le"
Read more about these fields in the VideoStreamMetadata docs!
pip install torchcodec now defaults to the CUDA 13.0 wheel to match the behavior of pip install torch. See updated instructions in our README.TorchCodec 0.10 is out! It is compatible with torch 2.10, and comes with exciting new features.
TorchCodec 0.10 is out! It is compatible with torch 2.10, and comes with exciting new features.
Decoder Transforms are available! We have released Resize, CenterCrop, RandomCrop, which can be used in VideoDecoder to transform data during preprocessing:
resize_decoder = VideoDecoder(
video_path,
transforms= [
torchcodec.transforms.RandomCrop(size=(1280, 1664)),
torchcodec.transforms.Resize(size=(480, 640)),
]
)
resized_frame = resize_decoder[5]
Read more about this in the tutorial!
Let us know any transforms you want to see added in https://github.com/meta-pytorch/torchcodec/issues/1134!
VideoEncoder now supports encoding on GPU! This can improve performance by ~3x! To use it, simply move the input frames onto the CUDA device before encoding:
encoder = VideoEncoder(frames=frames.cuda(), frame_rate=frame_rate)
encoder.to_file(dest="output.mp4", codec="h264_nvenc")
Check out our new performance tips guide to read about best practices to improve performance! The guide covers batch APIs, decoding seek modes, multi-threading, GPU decoding, and checking for CPU fallback during decoding.
TorchCodec 0.9.1 is out! This version is compatible with torch 2.9.
TorchCodec 0.9.1 is out! This version is compatible with torch 2.9.
This is primarily a bug-fix release which should resolve issues on Windows where FFmpeg couldn't be found.
TorchCodec 0.9 is out! This comes with a new highly requested feature: video encoding!
TorchCodec 0.9 is out! This comes with a new highly requested feature: video encoding!
Video encoding on CPU is available. It provides a simple API to encode video frames to tensors or bytes, and optionally enables a set of key parameters.
from torchcodec.encoders import VideoEncoder
encoder = VideoEncoder(frames=frame_tensor, frame_rate=frame_rate)
encoder.to_file(dest="output.mp4") # encode to mp4 file
encoded_bytes = encoder.to_tensor(format="mp4") # encode to tensor of bytes
Additionally, several key parameters are exposed to control the encoded video:
# Utilize a specific codec, choose a pixel format to control quality
encoder.to_file(dest="output.mp4", codec="libx264", pixel_format="yuv420p")
# Set quality parameter `crf` to 0 for lossless encoding, use fast `preset`
encoded_bytes = encoder.to_tensor(format="mp4", crf=0, preset="fast")
Read more about the available features in the video encoding tutorial!
seek_mode=approximate for some videos with missing metadata.seek_mode="approximate".device=None in VideoDecoder now uses the current torch device.We are releasing TorchCodec 0.8.1 which is bug-fix release, compatible with torch 2.9.
We are releasing TorchCodec 0.8.1 which is bug-fix release, compatible with torch 2.9.
In 0.8 we introduced our new "beta" backend which is much faster than our existing CUDA decoder (try it!!). But we also introduced a hard dependency on libnvcuvid.so, which isn't always available on the users machine. This would cause issues when import torchcodec was run.
We have now removed the hard dependency on libnvcuvid.so: if it cannot be found at runtime, the VideoDecoder will gracefully fallback to the CPU. This should resolve a lot of the ongoing import torchcodec errors. We're working on exposing an API that allows the user to know whether they're falling back to the CPU.
Thanks again to @traversaro for the original diagnosis and for the help testing the fix on Windows!
We also added support for FFmpeg 8 on Windows - we now support FFmpeg 4, 5, 6, 7, and 8 across all platforms (Linux, MacOS and Windows).
TorchCodec 0.8 is out, and is compatible with torch 2.9!
TorchCodec 0.8 is out, and is compatible with torch 2.9!
Faster video decoding on GPU is available, with our new Beta CUDA backend! We have observed up to 3x speedups compared to our previous GPU decoding implementation, and up to 90% NVDEC utilization.
We are releasing it as a Beta feature that we will polish over time, but we are confident it is ready to use, and we are eager to hear your feedback! Eventually, this Beta backend will become the default.
To use it, you just need to specify the "beta" backend when creating the VideoDecoder instance:
from torchcodec.decoders import set_cuda_backend, VideoDecoder
with set_cuda_backend("beta"):
dec = VideoDecoder("file.mp4", device="cuda")
# All existing methods are supported
batch = dec.get_frames_at(...)
Video decoding now accepts pre-computed frame index data for faster VideoDecoder instantiation speeds, while maintaining exact frame seeking accuracy.
Read more about this feature in our tutorial!
dec.get_frames_at(indices) and for timestamps in dec.get_frames_played_at(timestamps).clips_at_regular_timestamps()TorchCodec 0.7 is out and it's compatible with torch 2.8!
TorchCodec 0.7 is out and it's compatible with torch 2.8!
The main new feature is that TorchCodec now has BETA support for Windows! This is our most popular feature request to date. Windows users can try it out with pip install torchcodec for CPU, and use conda-forge for GPU support (thanks @traversaro !): conda install torchcodec -c conda-forge
This is currently in BETA support, so there may be rough edges. Let us know if you encounter any issue.
AudioDecoder on some wav files with FFmpeg 4This release also comes with a few bug fixes:
AudioEncoder.to_file() to accept a pathlib.Path instead of just a stringThis version is the same as 0.5, but adds compatibility with the latest PyTorch 2.8.
This version is the same as 0.5, but adds compatibility with the latest PyTorch 2.8.
Nothing published for this version
[TorchCodec 0.4](https://pytorch.org/torchcodec/0.4/index.html) is out! It is a small release with:
TorchCodec 0.4 is out! It is a small release with:
num_channels parameter to AudioDecoder, allowing you to directly specify whether you want to convert the audio to mono or stereo.AudioDecoder.get_samples_played_in_range(): if stop_seconds was before the first sample's start, we would return all the samples. Now, we raise a loud error.AudioDecoder.get_samples_played_in_range() when start_seconds == stop_seconds: the shape of the output is now (num_channels, 0) instead of (0, 0).[TorchCodec 0.3.0](https://pytorch.org/torchcodec/0.3/index.html) is out! It comes with two new major features: Audio decoding, and Streaming.
TorchCodec 0.3.0 is out! It comes with two new major features: Audio decoding, and Streaming.
You can now decode audio streams from videos, or from audio files! The AudioDecoder looks a lot like the existing VideoDecoder:
from torchcodec.decoders import AudioDecoder
decoder = AudioDecoder(path_to_audio)
samples = decoder.get_all_samples()
print(samples)
# AudioSamples:
# data (shape): torch.Size([2, 4297722])
# pts_seconds: 0.02505668934240363
# duration_seconds: 97.45401360544217
# sample_rate: 44100
Lean more in our tutorial.
You can now decode steaming videos and audio! That is, when files do not reside locally, TorchCodec now supports downloading only the data segments that are needed to decode the frames you care about. The API is generic and integrates nicely with existing file-like interfaces like fsspec and others.
Learn more in our tutorial.
VideoDecoder now accept a torch.device parameter (https://github.com/pytorch/torchcodec/pull/607)TorchCodec 0.2.1 is out! This version is compatible with pytorch 2.6. This is small release with two quality-of-life improvements:
TorchCodec 0.2.1 is out! This version is compatible with pytorch 2.6. This is small release with two quality-of-life improvements:
TorchCodec 0.2.0 is out! This version is compatible with pytorch 2.6.
TorchCodec 0.2.0 is out! This version is compatible with pytorch 2.6.
The main new feature is the addition of an approximate seeking mode, which can significantly improve the decoding performance:
decoder = VideoDecoder(video_path, seek_mode="approximate") # default value is "exact"
To learn more, check out our seek mode tutorial!
TorchCodec is still in development stage and some APIs may be updated in future versions without a deprecation cycle, depending on user feedback. For…
TorchCodec 0.1 is out ! It is packed with exciting features, and it is the first release of TorchCodec that we're pushing for wide adoption.
Decoding can now be done on CUDA GPUs by simply using the device parameter: decoder = VideoDecoder(..., device="cuda"). GPU decoding can lead to faster decoding pipelines in a variety of cases. To learn more on how to use GPU decoding and how to install it, follow our GPU decoding example!
TorchCodec now supports fast clip samplers in the torchcodec.samplers namespace. We support random and regular sampling for both index-based and time-based strategies. Read more about samplers in our sampling example!
VideoDecoderNote: SimpleVideoDecoder became VideoDecoder! See below for other changes.
The VideoDecoder class now exposes the following parameter to provide users with more control:
num_ffmpeg_threadsstream_indexTwo new methods were added: decoder.get_frames_at(indices=[3, 1, 10]) and decoder.get_frames_played_at(seconds=[10.5, 0.3]). When decoding multiple frames, calling these method is a lot faster than calling get_frame_at() or get_frame_played_at() repeatedly.
Read more on the docs.
Various performance improvements were made, including:
swscale and filtergraph libraries. These libraries are mainly used to convert YUV colors to RGB, and swscale usually leads to faster results. TorchCodec relies on one or the other when appropriate.You can find detailed benchmark results on the repo.
TorchCodec now supports MacOS! Just run pip install torchcodec and follow our normal installation instructions.
TorchCodec is still in development stage and some APIs may be updated in future versions without a deprecation cycle, depending on user feedback. For this release, a few important API changes were made, but we do not anticipate significant changes of the sort in future releases, and we now consider the existing APIs largely stable.
SimpleVideoDecoder class was renamed to VideoDecoderVideoDecoder containing the term "displayed" have been changed to the term "played". E.g. get_frame_displayed_at() is now get_frame_played_at(). This is to accommodate for future audio support.get_frames_at() and get_frames_displayed_at() methods have been renamed to get_frames_in_range() and get_frames_played_in_range(). The method names get_frames_at() and get_frames_played_at() still exist, but they do something else (see new features section).Nothing published for this version
This is a small release which fixes decoding frames for H265.
TorchCodec 0.0.3 is out !
This is a small release which fixes decoding frames for H265.
This is a small release which adds the `SimpleVideoDecoder.get_frames_displayed_at()` method.
TorchCodec 0.0.2 is out !
This is a small release which adds the SimpleVideoDecoder.get_frames_displayed_at() method.
This is the first release of TorchCodec!
This is the first release of TorchCodec!
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →