2025, Nov 19 19:00
How to fix torchcodec VideoDecoder 'No valid stream found' in MP4 decoding: pin ffmpeg 6.1.1 or switch to PyAV
Fix torchcodec VideoDecoder 'No valid stream found' on MP4: pin ffmpeg 6.1.1 for stable decoding, or use PyAV/LeRobot backend when stability matters most.
When decoding video with torchcodec’s VideoDecoder, you might run into a runtime failure where the decoder refuses to find a valid stream in an otherwise normal-looking MP4. The error is concise and confusing at first glance, but the fix is straightforward once you know it.
Minimal reproduction
The following snippet initializes torchcodec’s video decoder and attempts approximate seeking:
import torchcodec
video_path = "/path/to/episode_000000.mp4"
decoder = torchcodec.decoders.VideoDecoder(video_path, seek_mode="approximate")
In failing setups, the error manifests as:
ValueError: No valid stream found in input file. Is -1 of the desired media type?
What’s actually going on
The exception is raised in the decoding path when torchcodec tries to add a video stream and cannot recognize a valid one in the provided input. In practice, this is tied to the media stack beneath torchcodec. The reliable way to resolve this is to use a specific, known-good ffmpeg build. If replacing ffmpeg isn’t an option in your environment, a pragmatic fallback is to switch the video backend to pyav, accepting a throughput penalty.
Fix that keeps torchcodec
Pin ffmpeg to version 6.1.1. This resolves the faulty stream detection and keeps the faster torchcodec path intact.
conda install -c conda-forge ffmpeg=6.1.1 -y
With ffmpeg 6.1.1 in place, the original decoder snippet works as intended, so you don’t need to change your torchcodec calls.
Fallback with pyav (slower, but stable)
If you can’t change the system ffmpeg, switch to pyav as a compromise. Be aware that pyav is about 40% slower than torchcodec, so use it when stability takes priority over raw speed.
import av
video_src = "/path/to/episode_000000.mp4"
stream = av.open(video_src)
for frm in stream.decode(video=0):
frm.to_image().save("frame-%04d.jpg" % frm.index)
If you’re working inside LeRobot, you can route decoding through pyav by selecting the backend directly in the dataset utilities, without refactoring your pipeline:
lerobot.common.datasets.video_utils(..., backend="pyav")
Why this matters
Video decoding sits at the base of many training and data processing pipelines, so small incompatibilities can cascade into hours of lost time. Using a compatible ffmpeg version restores torchcodec’s decoding path and keeps higher throughput. Falling back to pyav is a viable stopgap, but it comes with measurable performance overhead compared to torchcodec.
Takeaways
If you hit “No valid stream found” with torchcodec, first pin ffmpeg to 6.1.1. That preserves the faster torchcodec path. If changing the environment is not feasible, switch to a pyav backend, including via LeRobot’s backend parameter, and plan around the slower runtime. Keeping these two levers in mind helps you move past the error quickly and choose the right trade-off for your setup.