cp: Port FFmpeg video codec support updates to main (2217) into r1.3.0#2222
Conversation
* Remove libopenh&libx264 and Add vp9 (#1930) * fix: remove libopenh264 and replace with libx264 Signed-off-by: Dong Hyuk Chang <9426164+thomasdhc@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: install libx264 Signed-off-by: Dong Hyuk Chang <9426164+thomasdhc@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: drop libx264 support Signed-off-by: Dong Hyuk Chang <9426164+thomasdhc@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Enhance video transcoding support by adding `libvpx-vp9` as a CPU fallback encoder alongside `h264_nvenc`. Update installation instructions and verification steps to reflect the new encoder options. Modify `ClipTranscodingStage` to validate encoder selection and handle encoding options for both encoders. Update relevant documentation and examples to guide users on using the new encoder. Signed-off-by: Ao Tang <aot@nvidia.com> * Minor update Signed-off-by: Ao Tang <aot@nvidia.com> * refine docs Signed-off-by: Ao Tang <aot@nvidia.com> * refine docs Signed-off-by: Ao Tang <aot@nvidia.com> * add back openlibh264 and inform user to install themself if needed Signed-off-by: Ao Tang <aot@nvidia.com> * docs format Signed-off-by: Ao Tang <aot@nvidia.com> --------- Signed-off-by: Dong Hyuk Chang <9426164+thomasdhc@users.noreply.github.com> Signed-off-by: Ao Tang <aot@nvidia.com> Co-authored-by: Dong Hyuk Chang <9426164+thomasdhc@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> (cherry picked from commit 79cacb4) * Update FFmpeg codec support without PyAV source-build path (#1959) Port the non-PyAV parts of #1959 onto latest main: - Keep the strict FFmpeg allowlist installer and update its default tag to n8.1.2. - Add the opt-in h264/hevc/av1 software decoder and libopenh264 installer. - Improve video metadata error handling when ffprobe cannot open NVDEC-only codecs in CPU-only stages. - Update video docs, tutorial preflight checks, and decoder tests for the optional software codec path. - Make video benchmark entries install the opt-in h264 support at runtime and use libopenh264 explicitly. The Docker image still follows latest main's #2203 behavior: it does not bake in system FFmpeg, does not force a PyAV source build, and leaves Dockerfile, pyproject.toml, and uv.lock unchanged. (cherry picked from commit 8055f35) * fix(video): avoid PyAV motion decode log callback deadlock * comments addressed Signed-off-by: Ao Tang <aot@nvidia.com> * install video codecs for benchmark image build Signed-off-by: Ao Tang <aot@nvidia.com> --------- Signed-off-by: Dong Hyuk Chang <9426164+thomasdhc@users.noreply.github.com> Signed-off-by: Ao Tang <aot@nvidia.com> Co-authored-by: Dong Hyuk Chang <9426164+thomasdhc@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: NeMo Bot <nemo-bot@nvidia.com>
|
/ok to test ef14b2f |
Greptile SummaryThis PR ports FFmpeg video codec support updates (#2217) to the
Confidence Score: 3/5Safe to merge with a targeted fix to install_h264_support.sh before release; all Python-side logic is sound but the shell script bug causes misleading license messaging for default users. The Python changes are well-structured and thoroughly tested. The one issue worth fixing before shipping is in install_h264_support.sh: the NOTE block about license obligations prints on every invocation regardless of whether --with-libopenh264 was passed, because the echo statements landed outside the if guard. Users running the default (LGPL-only) path receive an alarming license warning that does not apply to them. The av.logging.restore_default_callback() change correctly addresses a Ray/GIL deadlock but permanently alters process-wide PyAV logging, which is worth documenting. docker/common/install_h264_support.sh (echo indentation places the license NOTE outside its if block) Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Video Input] --> B[VideoReaderStage\npopulate_metadata via ffprobe]
B -->|success| C[ClipTranscodingStage\nsetup]
B -->|SoftwareCodecMissingError\nNVDEC-only ffprobe + no GPU| D[log error\nskip video]
B -->|other error| E[log warning\nskip video]
C -->|encoder=h264_nvenc| F{use_hwaccel?}
C -->|encoder=libvpx-vp9\nCPU fallback| G[emit perf warning\n_add_libvpx_vp9_options\nCRF or VBR mode]
C -->|encoder=libopenh264| H[_verify_libopenh264_available\nffmpeg -encoders probe]
H -->|libopenh264 found| I[encode with libopenh264]
H -->|not found| J[RuntimeError\npoint to install_h264_support.sh]
F -->|yes| K[-hwaccel cuda\n-hwaccel_output_format cuda]
F -->|no| L[encode with h264_nvenc\nno hwaccel flags]
K --> M[_add_nvenc_options\nVBR+CQ mode]
L --> M
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Video Input] --> B[VideoReaderStage\npopulate_metadata via ffprobe]
B -->|success| C[ClipTranscodingStage\nsetup]
B -->|SoftwareCodecMissingError\nNVDEC-only ffprobe + no GPU| D[log error\nskip video]
B -->|other error| E[log warning\nskip video]
C -->|encoder=h264_nvenc| F{use_hwaccel?}
C -->|encoder=libvpx-vp9\nCPU fallback| G[emit perf warning\n_add_libvpx_vp9_options\nCRF or VBR mode]
C -->|encoder=libopenh264| H[_verify_libopenh264_available\nffmpeg -encoders probe]
H -->|libopenh264 found| I[encode with libopenh264]
H -->|not found| J[RuntimeError\npoint to install_h264_support.sh]
F -->|yes| K[-hwaccel cuda\n-hwaccel_output_format cuda]
F -->|no| L[encode with h264_nvenc\nno hwaccel flags]
K --> M[_add_nvenc_options\nVBR+CQ mode]
L --> M
Reviews (1): Last reviewed commit: "Port FFmpeg video codec support updates ..." | Re-trigger Greptile |
| if [ "$WITH_LIBOPENH264" -eq 1 ]; then | ||
| echo " Encoder added: libopenh264 (Cisco OpenH264 binary)" | ||
| fi | ||
| echo " NOTE: This expands the container's codec footprint beyond Curator's" | ||
| echo " default strict FFmpeg allowlist. License obligations of the resulting binaries" | ||
| echo " are the user's responsibility." | ||
| echo |
There was a problem hiding this comment.
NOTE message always prints regardless of
--with-libopenh264
The three echo lines for the NOTE (lines 93–95) are outside the if [ "$WITH_LIBOPENH264" -eq 1 ] block — the fi closes it on line 91. The indentation is misleading: the message about "License obligations of the resulting binaries are the user's responsibility" fires unconditionally, even when running without --with-libopenh264. This directly contradicts usage(), which clearly states the default (LGPL-only decoders) path has no special license obligations beyond LGPL itself. Users who run the script in its default mode will receive an alarming license warning that doesn't apply to them.
| # PyAV's Python log callback can deadlock in Ray workers when FFmpeg decoder | ||
| # threads log during codec-context teardown. |
There was a problem hiding this comment.
restore_default_callback() is a process-wide global state change
av.logging.restore_default_callback() replaces PyAV's Python-level logging hook with FFmpeg's native C-level handler for the entire process, not just for this av.open() call. If any other code in the same Ray worker later relies on PyAV's Python log callback (e.g. for structured logging or log redirection), those messages will be silently dropped after the first call to decode_for_motion. The fix for the Ray/GIL deadlock is correct in motivation, but consider calling it once at worker startup (e.g. in a @ray.remote initializer) rather than on every decode_for_motion invocation, or document the side effect explicitly so future callers are not surprised.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
beep boop [🤖]: Hi @suiyoubi 👋,