Repository navigation
build(container): pin PyNvVideoCodec at 2.2.3 and move the in-tree FFmpeg to 9.0.1 (DYN-4044) - #14925
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (10)
Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review. WalkthroughChangesPyNvVideoCodec 2.2.3 compatibility
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Merge Risk: ⚪ Minimal · up to The dependency and runtime-image updates have no identified actionable merge risk. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 4 files. (6 skipped: 6 unsupported.)
Comment |
81b1548 to
2629b7c
Compare
2629b7c to
663eac8
Compare
663eac8 to
c7eb2fa
Compare
c7eb2fa to
0ba2c13
Compare
There was a problem hiding this comment.
Previously reported defects still present:
- Original discussion: The module docstring in tests/dependencies/test_pynvvideocodec_floor.py still recounts the prior
>=2.2.0to 2.2.3 drift. The lasting rationale is only that an unbounded lower bound can resolve newer releases, so the historical version sequence remains superfluous.
The spec has read `>=2.2.0` since it was introduced, when 2.2.0 was the newest release. A floor with no upper bound pins nothing, so builds resolved 2.2.1, 2.2.2 and now 2.2.3 as they were published without anything being restated: the runtime-test images for main@5e21f9c618 all carry 2.2.3 while every declared floor still read 2.2.0. `container/deps/README.md` already says why -- "Never use `>=` as it allows untested future versions" -- so the spec becomes `>=2.2.3,<3`, matching the bounded siblings in the same files. The TRT-LLM image installs a second, system-site copy of its own and takes the same specifier; its shell guards check the cap as a separate major-version test, because `sort -V` can express a floor but not an upper bound. 2.2.3 vendors FFmpeg 9.0.1 where 2.2.0-2.2.2 vendored 8.1.2, which moves the SONAMEs of the two libraries the wheel bundles: libavformat.so.62 -> .so.63 and libavutil.so.60 -> .so.61. They no longer collide with the in-tree FFmpeg 8.1.2, which ships .so.62/.so.60 built with different configure flags, so NVDEC decode no longer depends on which copy the loader resolves first. The bundled library content is unchanged by the FFmpeg major bump: enumerate_bundled_decoders.py reports 0 decoders and 0 encoders for libavformat.so.63 in all three images, the same as 2.2.0 reported for .so.62. Also replace the base image's copy explicitly rather than leaving it to the installer's upgrade path. Both the vLLM base (2.0.4, FFmpeg 8.1.1) and the TRT-LLM base (2.1.0, FFmpeg 7.0.2) ship a complete FFmpeg including a libavcodec, and both write files outside site-packages -- a version-stamped FFmpeg source tarball -- that a package-directory glob does not reach. The package manager uninstalls first, because its RECORD is the only complete list of what the wheel wrote (it also covers top-level samples/ and benchmarks/ trees), and the explicit rm follows it for the parts that must not depend on the installer honouring its own metadata. Each image then asserts what survived: exactly one distribution on sys.path inside the declared range, exactly one source tarball at the location its own RECORD names, a libavformat and libavutil present so the negative checks cannot pass vacuously, and none of the library families codec_policy.yaml denies. Presence is tested with importlib.util.find_spec, not an import: PyNvVideoCodec's __init__ dlopens libnvidia-encode.so.1, which no builder has, so an import raises whether or not the wheel is installed and could never fail a build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
… written The spec is written in three requirements files; the TRT-LLM template installs a system-site copy with its own inline specifier, and all three templates repeat the lower bound as a guard constant. The templates cannot parse the requirements file they are checking, since the point of those guards is to fail when the installed version and the declared one disagree, so the duplication is deliberate and needs a test rather than a comment. Three things are pinned. The whole specifier in each requirements file; the inline specifier in any template that installs the package, which is what catches a template left at a floor while the requirements file gained a cap; and every version literal the shell guards compare against. The last of those is mutation-checked -- each of the ten floor-bearing lines individually fails the suite. Two only became reachable after the scan was widened: a shell guard's two sides sit on different lines (`printf '%s\n2.2.3\n'` and `[ "$newest" != "2.2.3" ]`), and pinning only the side carrying the package name let a half-finished bump invert the comparison. Diagnostic lines are excluded, because that is where versions the guard is deliberately not comparing against appear. `test_the_spec_is_bounded_above` is kept deliberately, though it looks like a weaker subset of the exact-spec cases. It is the only one that survives an edit which drops the cap and updates EXPECTED_SPEC to match: mutating all three requirements files and every constant self-consistently leaves six cases green and fails only that one. .dockerignore keeps `container/templates/*.Dockerfile` out of every build context, so the component images that run this suite have the requirements files but not the templates; those cases skip there, as `test_aisimulate_consistency` already does for the planner Dockerfile. The `pynvvideocodec-spec` pre-commit hook runs the module as a script against a real checkout, so the template half stays enforced in CI rather than only on a developer's machine. The codec-gate waiver fixture moves to the SONAMEs the shipped floor bundles (.so.61/.so.63); it had been written against .so.60/.so.62, which no version at or above the floor ships. One series is enough: the waiver globs are SONAME-agnostic, and pinning either of them to any single series unwaives the bare `.so` symlinks and fails the fixture whichever series it names. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
0ba2c13 to
a18618f
Compare
There was a problem hiding this comment.
Previously reported defects still present:
- Original discussion: The module docstring in tests/dependencies/test_pynvvideocodec_floor.py still recounts the prior
>=2.2.0to 2.2.3 drift; the durable test rationale is only that a lower-bound requirement can resolve newer releases, so the historical version-specific narration remains superfluous. - Original discussion: The module docstring still recounts the prior
>=2.2.0to 2.2.3 drift. The durable rationale is that an unbounded lower bound can resolve newer releases; the historical version sequence remains present. - Original discussion: The module docstring still recounts the prior
>=2.2.0to 2.2.3 drift. The lasting rationale is only that a lower bound can resolve newer releases, so the historical version sequence remains superfluous. - Original discussion:
test_source_fps_prefers_stream_metadatastill has a docstring that merely restates the test name and constructed assertion. The earlier version-specific wording was removed, but the remaining comment is still redundant.
`>=2.2.3,<3` still resolves whatever is newest inside the major at build time, so the declared version stayed a floor rather than a record of what was validated -- the same shape of failure that let the images run 2.2.3 while the spec read `>=2.2.0` and nothing noticed. container/deps/README.md asks that every installed version be explicitly tested, and here the wheel's bundled FFmpeg is what the codec gate inspects, so an unaudited bundle must not be able to arrive on its own. The template guards follow the specifier. TRT-LLM's `sort -V` floor test and its separate `case "$v" in 2.*)` cap collapse into `[ "$v" = "2.2.3" ]`, and the venv cross-check becomes `[ "$vv" = "$v" ]`, which compares the image's two copies to each other rather than each to a bound. The vLLM and SGLang heredocs replace `parse(...) < parse(FLOOR)` with an equality against PINNED, so the now-unused `parse()` helper goes. The obsolete-base tripwire in trtllm_runtime.Dockerfile now also fires when the base ships exactly 2.2.3, not only something newer: with an exact pin, a base that already carries the pinned version makes the removal-and-reinstall block a no-op that should be deleted. Renames tests/dependencies/test_pynvvideocodec_floor.py to `..._spec.py`. Nothing here is a floor any more, and a stale name is precisely the drift that file exists to catch. Validation: the renamed module passes 8/8 under pytest and exits 0 as the pre-commit hook script, printing "PyNvVideoCodec spec ==2.2.3 is consistent across 3 requirements files and 3 templates." `pre-commit run` over the changed files passes every hook. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
…ix=_dynamo
PyNvVideoCodec 2.2.3 vendors FFmpeg 9.0.1, so moving the in-tree build to the
same release gives two independently configured builds the same DT_SONAMEs --
libavformat.so.63, libavutil.so.61, libavcodec.so.63. The loader resolves a
needed name to exactly one library per process, so whichever is loaded first
serves both, and the two builds enable disjoint feature sets. Reproduced on a
GPU box with both trees present: PyNvVideoCodec's own capability collapses from
359 demuxers to 3, 50 bitstream filters to 6, and 183 muxers to 4.
`--build-suffix=_dynamo` renames the libraries and their SONAMEs, so ours ship
as libavformat_dynamo.so.63 and cannot be mistaken for a vendored copy. Three
things follow from the rename and each needed fixing:
- pkg-config. The .pc files are renamed too, so `pkg-config libavformat` stops
resolving and ffmpeg-sys-next's probe fails the Rust build outright.
Canonical-name symlinks restore it; each still reports -lavformat_dynamo, so
consumers link the suffixed library.
- The codec gate. `**/libav*.so*` does not match a suffixed name. Measured by
rescanning one tree with and without the three new deny globs: violations
1 -> 0 and allowed 6 -> 0, i.e. the scanner went blind to every suffixed
library, ours and a planted third-party one alike. allow_paths re-permits ours
by path prefix, so a third-party suffixed libavcodec still fails.
- auditwheel. fnmatch('libavcodec_dynamo.so.63', 'libavcodec.so.*') is False, so
leaving the excludes unsuffixed silently re-enables the library grafting they
exist to prevent.
video-rs 0.12 requires ffmpeg-next =9.0.0 -- cargo reports `dependency
ffmpeg-next = "=9.0.0" of package video-rs v0.12.0` when asked to resolve it
against 8.1.0 -- so lib/llm moves both together, with the lockfiles re-resolved.
Separately, the codec absence guard was checking nothing. It ran
/usr/local/bin/ffmpeg with stderr discarded before ldconfig, and the binary
carries no RPATH, so against a stale cache it could not start, produced empty
output, matched no disallowed codec and passed. ldconfig now runs first and a
positive VP9-encoder check precedes the absence tests, so an unstartable binary
fails loudly instead of quietly.
tests/dependencies/test_ffmpeg_version_consistency.py is new: context.yaml
decides what is compiled, native_packages.yaml is what the SBOM claims, and the
codec policy's deny_components floor is what that SBOM is measured against.
Nothing compared them, and only one direction failed loudly. All three read
8.1.2 before this change, so it pins an invariant the repo already held.
Validation on a GPU box (RTX 6000 Ada):
- The ffmpeg RUN block extracted verbatim from the rendered vLLM runtime
Dockerfile builds clean. pkg-config resolves all five canonical names to
-l*_dynamo; the positive VP9 check fires; encoders, decoders and parsers carry
no denied codec; no unsuffixed libav* is installed.
- cargo test -p dynamo-llm --no-default-features --features media-ffmpeg:
65/65 media tests pass, including test_sampled_decode_matches_video_rs and the
decode paths. The test binary's DT_NEEDED entries are libavutil_dynamo.so.61,
libavformat_dynamo.so.63, libavcodec_dynamo.so.63 and libswscale_dynamo.so.10.
Injecting a call to a nonexistent ffmpeg-next API into video.rs fails the
build, so the check is not vacuous.
- container/compliance/tests: 93 passed. Deleting the three new deny globs fails
exactly the two tests that pin them. All 11 Dockerfile flavours render, and
`pre-commit run` over the changed files passes every hook.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
Four files conflicted. Each resolution keeps both sides.
In container/deps/requirements.{vllm,sglang,trtllm}.txt, main added
redis>=6.2.0,<9.0.0 right after the PyNvVideoCodec line. This branch
rewrote that line. The resolution keeps the PyNvVideoCodec==2.2.3 block
and adds main's redis lines after it.
In container/templates/trtllm_runtime.Dockerfile, main updated the note
about the pip resolver complaint for its new base image. This branch
rewrote the same note for the exact pin. The resolution keeps the
exact-pin text and takes main's wording where it is more precise. The
quoted pip message names 1.3.0rc28, the tag that container/context.yaml
now pins. The resolution drops main's sentence about treating 2.2.3 as
whatever the build resolved. Under ==2.2.3, that sentence is false.
Checks on the merged tree:
- Both Cargo.lock files pass cargo metadata --locked.
- cargo test --locked in lib/llm with --features media-ffmpeg passes
65 of 65 media tests against the suffixed FFmpeg 9.0.1.
- The new base images match what the removal blocks expect.
TensorRT-LLM 1.3.0rc28 ships PyNvVideoCodec 2.1.0, vllm-openai
v0.30.0 ships 2.0.4, and SGLang v0.5.19 ships none.
tests/dependencies/test_pynvvideocodec_spec.py fails on this tree,
because a new DALI error message from main names PyNvVideoCodec. The
next commit fixes the test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
main added a DALI guard to trtllm_runtime.Dockerfile whose error message says "the way PyNvVideoCodec 2.2.0 links it into libavformat". The spec test decided which instructions guard PyNvVideoCodec by looking at every code line, including echo lines. So it counted the whole DALI instruction, read DALI's own 2.2.0 pin as a PyNvVideoCodec version, and failed the template for the wrong reason. The test now leaves diagnostic lines out of that decision too, as it already did when it collects versions. A new test feeds it a DALI-shaped guard and a PyNvVideoCodec guard in one template and expects only 2.2.3. Checks: - With the fix, the module passes 9 of 9. With the previous logic restored, the new test and the real trtllm_runtime.Dockerfile case both fail. - Each non-comment template line that carries 2.2.3 was changed to 2.2.2, one at a time. All 6 code lines fail the check. The one line that passes is the "wanted PyNvVideoCodec 2.2.3" error text, which the test leaves out on purpose. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
Some comments on this branch were false after the merge, and some were already false before it. This branch made them false: - trtllm_runtime.Dockerfile said "The in-tree FFmpeg is 8.1.2" and that the SONAME change alone keeps the two FFmpeg copies apart. The in-tree build is 9.0.1 now. The --build-suffix=_dynamo rename in wheel_builder.Dockerfile keeps them apart, and the note now says so. - The same note put both 2.2.0 and 2.2.3 "at or above the floor". The floor is 9.0.1, so 2.2.0 (FFmpeg 8.1.2) sits below it. - vllm_runtime.Dockerfile and the spec test still described the old range: "REPLACED at >=2.2.3", "held to the floor", FLOOR, and a >=2.2.3,<3 example. - wheel_builder.Dockerfile kept a remark about an 8.1 -> 8.1.2 bump. The merge made them false: - TensorRT-LLM: the note named rc26 as the pinned base. main now pins rc28. Both rc27 and rc28 still ship PyNvVideoCodec 2.1.0. - vLLM: 0.30.0 moved its PyNvVideoCodec consumer to vllm/multimodal/video_decoders/pynvvideocodec.py. It uses the same five names as before. Checks: vLLM 0.30.0 decodes the H.264 and H.265 test clips through PyNvVideoCodecVideoBackend.load_bytes with 2.2.3 installed. The result matches the base's own 2.0.4: shape (8, 240, 320, 3), uint8, fps 10.0, and the same frame indices. FFmpeg 9.0.1 still opens fd: for "-i -". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
…ner/ The vllm, sglang and trtllm runtime-test images have no /workspace/container directory. Run by path inside the vLLM image for 06c2ff4, test_pynvvideocodec_spec.py failed 4 checks with FileNotFoundError on container/deps/requirements.*.txt. The template checks already skip when their file is absent, and the requirements checks now do the same. CI did not see this, because CI runs the module only in the dynamo-runtime image, which ships container/deps. Script mode still reports a missing requirements file as an error. The pynvvideocodec-spec pre-commit hook runs that mode in a checkout. Checks: - Inside the vLLM runtime-test image, with the fixed file mounted over the image's copy: 4 failed before, 3 passed and 8 skipped after. - Locally the module passes 11 of 11, and pre-commit passes. - Removing the skip fails the new skip test. Making main() ignore skipped checks fails the new script-mode test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
peilii
left a comment
There was a problem hiding this comment.
The suffix is the right fix for the SONAME collision, and each knock-on (pkg-config symlinks, suffixed deny globs with the third-party-still-denied test, suffixed auditwheel excludes) is necessary and tested. Checked on this head: both new tests pass through the pre-commit hooks, both lockfiles pass cargo metadata --locked, the runtime cp -nL libav*.so* libsw*.so* globs still match the suffixed names, and the image-side codec test excludes the in-tree copy by path rather than name, so neither is affected by the rename. One structural comment inline.
auditwheel renames each library that it grafts into a wheel to <name>-<hash>.so.N (copylib in auditwheel 6.8.2 repair.py). A grafted libavcodec_dynamo.so.63 therefore lands as libavcodec_dynamo-<hash>.so.63. The suffixed deny globs matched only the plain name, so scan_filesystem gave no verdict for the hashed form. Each suffixed family now has the same plain and hash-renamed pair as the families above it. The policy comment no longer carries the measured counts from the first review round. The PR description keeps them. Checks: - The extended test plants both names for libavcodec, libswscale and libpostproc under the .libs directory of a wheel. On the old policy it fails, because the 3 hashed paths are not violations. - Deleting any one of the 6 suffixed globs fails the test. The old test still passed with the plain libpostproc_dynamo glob deleted. - The vLLM, SGLang and TensorRT-LLM runtime-test images for 06c2ff4 give the same scan result with both policies: 0 violations, and the same exceptions and allowed files. - The compliance suite passes 99 tests on macOS. test_scan_codecs.py passes 23 tests in a Linux container with no network. pre-commit passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Dmitry Tokarev <dtokarev@nvidia.com>
Tracked as DYN-4044.
Summary
PyNvVideoCodechad been declared as>=2.2.0in all three requirements files sincethat floor was introduced, when 2.2.0 was the newest release. A floor with no upper
bound pins nothing, so builds quietly resolved 2.2.1, 2.2.2 and now 2.2.3 as they were
published: the runtime-test images for
main@5e21f9c618all ship 2.2.3 while everydeclared floor still read 2.2.0.
container/deps/README.mdalready states the rule —"Never use
>=as it allows untested future versions… Every installed version shouldbe explicitly tested" — and since the wheel's bundled FFmpeg is what the codec gate
inspects, the spec is now
==2.2.3rather than a range.2.2.3 vendors FFmpeg 9.0.1 where 2.2.0–2.2.2 vendored 8.1.2, which is what makes the
second half of this PR necessary. Moving the in-tree build to the same 9.0.1 would give
two independently configured FFmpegs the same
DT_SONAMEs —libavformat.so.63,libavutil.so.61,libavcodec.so.63. The loader resolves a needed name to exactlyone library per process, so whichever loads first serves both. Reproduced with both
trees present: PyNvVideoCodec's own capability collapses from 359 demuxers to 3, 50
bitstream filters to 6, and 183 muxers to 4.
--build-suffix=_dynamorenames ourlibraries and their SONAMEs, so the two can coexist by construction.
Four parts:
Spec
>=2.2.0→==2.2.3inrequirements.{vllm,sglang,trtllm}.txtand in theruntime templates' guard constants. TRT-LLM's
sort -Vfloor test and its separatecase "$v" in 2.*)cap collapse into[ "$v" = "2.2.3" ]; the venv cross-checkbecomes
[ "$vv" = "$v" ], comparing the image's two copies to each other ratherthan each to a bound.
Replace the base image's copy explicitly. The vLLM base ships 2.0.4 (FFmpeg 8.1.1)
and the TRT-LLM base ships 2.1.0 (FFmpeg 7.0.2); both bundle a complete FFmpeg
including a
libavcodec. The package manager uninstalls first — its RECORD is theonly complete list of what the wheel wrote, reaching top-level
samples/andbenchmarks/trees (41 entries in 2.0.4) and a version-stamped FFmpeg source tarballoutside site-packages — and the explicit
rmfollows it for the parts that must notdepend on the installer honouring its own metadata. Each image then asserts what
survived. The SGLang base ships none, so it gets the assertion without a removal.
In-tree FFmpeg 8.1.2 → 9.0.1, built with
--build-suffix=_dynamo. Three thingsfollow from the rename, each of which needed fixing:
.pcfiles are renamed too, sopkg-config libavformatstopsresolving and
ffmpeg-sys-next's probe fails the Rust build outright.Canonical-name symlinks restore it; each still reports
-lavformat_dynamo, soconsumers link the suffixed library.
**/libav*.so*does not match a suffixed name, so the scannergoes blind to every suffixed library. Three pairs of
_dynamodeny globs restore it.Each pair covers the plain name and the auditwheel hash-renamed name, for example
libavcodec_dynamo-<hash>.so.63.allow_pathsre-permits ours by path prefix, so athird-party suffixed library still fails.
fnmatch('libavcodec_dynamo.so.63', 'libavcodec.so.*')isFalse,so leaving the excludes unsuffixed silently re-enables the library grafting they
exist to prevent.
video-rs0.12 requiresffmpeg-next=9.0.0, solib/llmmoves both together withthe lockfiles re-resolved.
Tests.
test_pynvvideocodec_spec.py(renamed from…_floor.py— nothing is afloor any more) pins the spec everywhere it is written; a new
test_ffmpeg_version_consistency.pypinscontext.yaml↔native_packages.yaml↔the codec policy's
deny_componentsfloor, which nothing compared before. Both arewired into pre-commit, because
container/context.yamlandcontainer/templates/are
.dockerignored and so absent from the component images that run the suite.A guard that was checking nothing, fixed here. The in-tree codec absence test ran
/usr/local/bin/ffmpegwith stderr discarded beforeldconfig, and the binary carriesno RPATH — so against a stale cache it could not start, produced empty output, matched no
disallowed codec and passed.
ldconfignow runs first and a positive VP9-encoder checkprecedes the absence tests.
No runtime behaviour changes in Python — that diff is comments and docstrings.
Validation
Everything below was executed. Images are the
main@5e21f9c618runtime-test images,which already carry 2.2.3. The original base-image work used
vllm/vllm-openai:v0.28.0-ubuntu2404,nvcr.io/nvidia/tensorrt-llm/release:1.3.0rc26and
lmsysorg/sglang:v0.5.18-cu130-runtimeon an RTX 6000 Ada box. main has since movedto vLLM v0.30.0, TensorRT-LLM rc28 and SGLang v0.5.19. The next section lists what was
checked again against those.
After merging main
The branch merges main at
3f46e3d3c5. Four files conflicted. In the three requirementsfiles, main added
redis>=6.2.0,<9.0.0next to the PyNvVideoCodec line. Intrtllm_runtime.Dockerfile, main rewrote the pip resolver note for its base bump. Eachresolution keeps both sides.
main's new base images change facts that these templates depend on. Each one was checked
again on the GPU box:
importlib.metadatainrelease:1.3.0rc27and1.3.0rc28tensorrt-llm 1.3.0rc28still requiresPyNvVideoCodec~=2.1.0RUNblock verbatim,FROM release:1.3.0rc28libavformat. pip prints the rc28 complaint that the comment quotesimportlib.metadatainvllm-openai:v0.30.0-ubuntu2404vllm 0.30.0requiresPyNvVideoCodec==2.0.4RUNblocks verbatim,FROM vllm-openai:v0.30.0-ubuntu2404libavformat/libavutil.63/.61, oneffmpeg-9.0.1.tar.xzPyNvVideoCodecVideoBackend.load_byteson the H.264 and H.265 clips, with the base's 2.0.4 as a control(8, 240, 320, 3)uint8, fps 10.0, same frame indicesimportlib.metadatainlmsysorg/sglang:v0.5.19-cu130-runtimecargo metadata --lockedin the root andlib/bindings/python, thencargo test --lockedThe merge also exposed a gap in
test_pynvvideocodec_spec.py. main's new DALI errormessage names PyNvVideoCodec, and the test counted that
echowhen it decided whichinstructions guard the package. It then read DALI's own
2.2.0pin as a secondPyNvVideoCodec version. The test now ignores diagnostic lines for that decision too. A new
regression test covers it. With the old logic restored, the new test and the real
template both fail.
A separate commit corrects stale comments. Two were false before the merge: "The in-tree
FFmpeg is 8.1.2", and that 2.2.0 and 2.2.3 both sit "at or above the floor". The floor is
9.0.1. The others went stale with main's base bumps.
GPU run on the CI images for
06c2ff404eAll three
-runtime-testimages for this head ran on the RTX 6000 Ada box, one containerat a time.
lib*_dynamonames in/usr/local/lib, no unsuffixed copieslibavif, which the scan also matched. TensorRT-LLM holds three copies with distinct names: ours, PyNvVideoCodec's.so.63, and DALI's hash-renamed.so.62/usr/local/lib/libavformat_dynamo.so.63andPyNvVideoCodec/libavformat.so.63are both mapped. NVDEC decodes the H.264 and H.265 clips to(8, 240, 320, 3)uint8 at 10 fpsdynamo/_core.abi3.so(vLLM image)_dynamolibraries and resolves them in/usr/local/lib, so auditwheel did not graft them into the wheeltest_no_software_video_codecs.pycase passes, and so does TensorRT-LLM'stest_no_opencv.py. The 12 failures are explained belowThe unit suites include
test_nvdec_decoder.py(36 of 36) andtest_nvdec_decoder_gpu.py(1 of 1) in each image,
test_video_loader.py(28 of 28) in each image, the SGLang NVDECdecoder (9 of 9), and the VP9 encode test (2 of 2) through the suffixed FFmpeg.
The serve runs that pass cover vLLM agg video, agg video with frontend decoding through the
_dynamolibraries, and NVDEC H.264 and H.265. They also cover SGLang agg video and bothE/PD video variants, and TensorRT-LLM NVDEC video and
video_diffusion(VP9 output).SGLang's
video_agg_fd_qwenskips with "SGLang container lacks media-ffmpeg support", thedeclared gate.
The failing vLLM serve test is
mm_epd_video_qwen3-vl-2b_mixed_frontend_decoding. Itsencode worker never reports healthy, so the test times out at 600 s. It fails the same way
on main at
3f46e3d3c5, the commit this branch merged, so it exists on main without thischange. The test is marked
post_mergeonly, and PR CI does not run it. It passed on mainat
5e21f9c618on September 16. #15432 describes the cause, and #15434 fixed it on main onSeptember 30.
The 12 unit failures come from this PR's own
test_pynvvideocodec_spec.py: 4 checks in eachframework image. Those images have no
/workspace/containerdirectory, and therequirements checks did not skip when their files were absent. CI runs this module only in
the dynamo-runtime image, which ships
container/deps, so CI stays green. Commit3f080e6c09fixes it: those checks now skip when their files are absent, and script modestill fails. Inside the vLLM image the module then shows 3 passed, 8 skipped, 0 failed.
PyNvVideoCodec
importlib.metadata.versionin all three runtime-test images==2.2.3/ shipped 2.2.3libavformat.so.62.12.102,ffmpeg-8.1.2.tar.xzlibavformat.so.63.1.101,ffmpeg-9.0.1.tar.xzcontainer/compliance/enumerate_bundled_decoders.pyon the shippedlibavformat.so.63in all three imagesdynamo.llmfirst — the order that used to fail — in all three images(8, 240, 320, 3)uint8 RGB, C-contiguous, fps 10.0, H.264 and H.265SimpleDecoder.stop(); checked Dynamo, vLLM 0.28multimodal/video.py,tensorrt_llm/media/decoding.py; importedtensorrt_llm.media.decodingagainst 2.2.3from ast import Stris gone by the pin__init__.pyfrom the 2.2.0/2.2.1/2.2.2/2.2.3 wheelsdocker buildof the renderedRUNblocks, extracted verbatimffmpeg-9.0.1.tar.xz, onlylibavformat/libavutilbundledgit archive origin/mainIn-tree FFmpeg 9.0.1 +
--build-suffix=_dynamodocker buildof the ffmpegRUNblock extracted verbatim from the rendered vLLM runtime Dockerfilelibavformat_dynamo.so.63; no unsuffixedlibav*installedpkg-config --modversion/--libsin that image63.1.101 / 63.1.101 / 61.1.101 / 10.1.101 / 7.1.101;-L/usr/local/lib -lavformat_dynamo -lavcodec_dynamo -lavutil_dynamo -lswscale_dynamocargo test -p dynamo-llm --no-default-features --features media-ffmpegin that imagetest_sampled_decode_matches_video_rs; binaryDT_NEEDED=libavutil_dynamo.so.61,libavformat_dynamo.so.63,libavcodec_dynamo.so.63,libswscale_dynamo.so.10ffmpeg_next::RationalAPI intovideo.rserror[E0599], exit 101; reverted tree exits 0video-rs0.12 requiresffmpeg-next=9.0.0video-rs 0.12.0alongsideffmpeg-next = "=8.1.0"dependency ffmpeg-next = "=9.0.0" of package video-rs v0.12.0scan_filesystemon one tree with and without the three_dynamodeny globs, asserting the mutated policy's actual contentslibavcodec_dynamo.so.63is a violationtest_scan_codecs.pyscan_filesystemon plantedlibavcodec_dynamo-1a2b3c4d.so.63,libswscale_dynamo-1a2b3c4d.so.10andlibpostproc_dynamo-1a2b3c4d.so.59under a wheel.libs/, with 4 controlslibvpxis ignoredlibpostproc_dynamo.so*orlibav*_dynamo-*.so*deletedtest_third_party_suffixed_codec_lib_is_denied, and the new test fails on the old policyscan_filesystemon/in the vLLM, SGLang and TensorRT-LLM runtime-test images for06c2ff404e, with each policyldconfigwith stderr discarded, so an unstartable binary passed itlibvpx-vp9matched during the build; encoders/decoders/parsers carry no denied codectest_ffmpeg_version_consistency.pycontainer/render.py, 11 framework/device/target combinationscontainer/compliance/tests/88ab323da0).test_scan_codecs.pypasses 23 of 23 in a Linux container with no networkBuild controls. Positive: vLLM replace-and-assert; the same with a check that 2.0.4's
samples/basic/encode_config.jsonis gone (the orphan the uninstall-first orderingprevents); SGLang; TRT-LLM. Negative, each of which must fail the build and did: base
ships no PyNvVideoCodec · assertion against the untouched 2.0.4 base · removal skipped,
so the presence guard must fire · a second dist-info forged beside the new one · a second
FFmpeg source tarball · a forged
libpostproc· the bundled libraries deleted (thevacuous-pass case) · SGLang with nothing installed · TRT-LLM with both the uninstall and
the
external/ffmpegremoval dropped, which ships 7.0.2 beside 9.0.1. The TRT-LLM"base is newer than the pin" branch was exercised directly over 2.1.0 / 2.2.3 / 2.2.4 /
2.3.0 / 3.0.0, since no published release sits above it.
Video suites, all three images — 558 executed, 15 skipped, 0 failed, 0 errors. Every
skip was read from the JUnit XML; all 15 are framework markers or one declared gate.
test_nvdec_decoder.py— 36 executed, 0 skipped, in each imagetest_nvdec_decoder_gpu.py::test_nvdec_decodes_real_clips— executed and passed in eachtest_no_software_video_codecs.py/test_no_opencv.py— each image's own case passedtest_video_encode_real.py(VP9 output) — 2 executed, 0 skipped(
mm_agg_video_nvdec_*_h264,_h265,mm_agg_video,*_frontend_decoding,mm_epd_video_*), TRT-LLM 2/2 (aggregated_multimodal_video_nvdec,video_diffusion), SGLang 3/3 (video_e_pd_qwen_nvdec,video_agg_qwen,video_e_pd_qwen) plusvideo_agg_fd_qwenskipped on the repo-declaredenable_media_ffmpeg: "false"gateThat covers NVDEC H.264 and H.265 on all three backends, VP9 input, frontend decoding,
disaggregated E/P/D video, and VP9 output.
Review rounds. Thirteen inline comments from
dynamo-review-agent; twelve applied,one declined with evidence.
The human review left four inline comments.
88ab323da0adds the hash-renamed deny globsand removes the measured counts from the policy comment, because this description already
holds them. The shared install guard moves to #15582, as both reviewers agreed.
The one that mattered: the TRT-LLM system-site install was left unbounded at
>=2.2.3after the requirements file gained,<3, so a published 3.x could have landedin system site-packages while the venv stayed on 2.x — and the block's own comment claims
the two specifiers are identical. The root cause was that the spec test scanned lower
bounds only; it now also compares a template's inline install specifier against the
declared spec. The exact pin removes the class of bug outright, and that check stays.
Two corrections to my own earlier claims, both from these rounds: the codec-waiver
SONAME series do not discriminate against each other (any narrowing unwaives the bare
.sosymlinks and fails both, so one series suffices — the real fix there was that thefixture named
.so.60/.so.62, which no supported version ships); andfrom ast import Strwas removed in 2.2.2, not 2.2.1.Declined, with evidence: removing
test_the_spec_is_bounded_aboveas a subset of theexact-spec cases. Those move with
EXPECTED_SPEC; this one does not. Mutating all threerequirements files and every constant self-consistently to a range leaves the other cases
green and fails only that one.
Correction:
common/tests/multimodal/test_embedding_transfer.pycrashed with rc 139 inthe September 16 run, and an earlier version of this description called it an unrelated
crash to raise separately. The crash came from my test harness, not from the code. Those
containers ran with Docker's default 64 MB
/dev/shm. With--shm-size=16g, the filepasses 13 of 13 in all three images for
06c2ff404e. With the default shm, it stillcrashes in the same image. There is nothing to raise.
Where verification stopped. The FFmpeg 9.0.1 and suffix work is verified on x86_64
only, on the RTX 6000 Ada box, and the aarch64 path rests on CI. The aarch64 PyNvVideoCodec
wheel was checked at file level only: the same two libraries, the same SONAMEs, the same
ffmpeg-9.0.1.tar.xz. The minimal rc28 build has no/opt/dynamo/venv, so it skips thevenv cross-check, and only CI runs that branch.
pre-commit run --all-filespasses all 37hooks at
88ab323da0.🤖 Generated with Claude Code