Skip to content

Commit 2c9786c

Browse files
thomasdhcclaude
andauthored
fix(deps): clear wheel-bundled ffmpeg CVEs from the all image (part 1/2) (#2192)
* fix(deps): clear wheel-bundled ffmpeg CVEs from the all image (part 1/2) 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(video): adapt motion-vector backend to PyAV 17 API Signed-off-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: Dong Hyuk Chang <9426164+thomasdhc@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent aeb06bc commit 2c9786c

4 files changed

Lines changed: 63 additions & 207 deletions

File tree

nemo_curator/stages/video/filtering/motion_vector_backend.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def decode_for_motion( # noqa: C901
185185
stream = input_container.streams.video[0]
186186
ctx = stream.codec_context
187187
# Set this flag to return motion vectors
188-
ctx.flags2 |= av.codec.context.Flags2.EXPORT_MVS
188+
ctx.flags2 |= av.codec.context.Flags2.export_mvs
189189
ctx.thread_type = av.codec.context.ThreadType.AUTO
190190
ctx.thread_count = thread_count
191191
mv_data = []

pyproject.toml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,8 @@ text_cuda12 = [
217217

218218
# Video Curation Dependencies
219219
video_cpu = [
220-
"av==13.1.0",
221-
"opencv-python",
220+
"av==17.1.0", # ffmpeg 8.1.1 (CVE: was 7.0.2)
221+
"opencv-python-headless", # dedupe with vllm's headless
222222
"torchvision",
223223
"einops",
224224
"easydict",
@@ -230,11 +230,16 @@ video_cuda12 = [
230230
"nemo_curator[vllm]",
231231
"cvcuda_cu12",
232232
"pycuda",
233-
"PyNvVideoCodec==2.0.2; (platform_machine == 'x86_64' and platform_system != 'Darwin')",
234233
"torch<=2.10.0",
235234
"torchaudio",
236235
]
237236

237+
# NVDEC HW decode; opt-in, kept off `all` (wheel vendors CVE ffmpeg). CPU-decode fallback exists.
238+
video_media = [
239+
"nemo_curator[video_cuda12]",
240+
"PyNvVideoCodec==2.0.2; (platform_machine == 'x86_64' and platform_system != 'Darwin')",
241+
]
242+
238243
# Math Curation Dependencies
239244
math_cpu = [
240245
"nemo_curator[text_cpu]", # Math examples use text processing utilities
@@ -250,10 +255,9 @@ math_cuda12 = [
250255

251256
# Multimodal / Interleaved Dependencies
252257
interleaved_cpu = [
253-
"albumentations",
254258
"matplotlib",
255259
"open_clip_torch",
256-
"opencv-python",
260+
"opencv-python-headless", # dedupe with vllm's headless
257261
"Pillow",
258262
"pypdfium2",
259263
"s3fs>=2024.12.0",

tests/stages/video/filtering/test_motion_vector_backend.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def test_video_resolution_too_small_error(self):
177177
"""Test that VideoResolutionTooSmallError is raised for small resolution."""
178178
mock_video = io.BytesIO(b"mock_video_data")
179179

180-
with patch("av.open") as mock_open, patch("av.codec.context.Flags2.EXPORT_MVS", create=True):
180+
with patch("av.open") as mock_open:
181181
# Mock frame with small resolution
182182
mock_frame = Mock()
183183
mock_frame.height = 100 # Less than 256
@@ -211,7 +211,7 @@ def test_successful_decode(self):
211211
"""Test successful decode operation."""
212212
mock_video = io.BytesIO(b"mock_video_data")
213213

214-
with patch("av.open") as mock_open, patch("av.codec.context.Flags2.EXPORT_MVS", create=True):
214+
with patch("av.open") as mock_open:
215215
# Mock motion vector side data
216216
mock_side_data = Mock()
217217
mock_side_data.type = Mock()
@@ -260,18 +260,17 @@ def test_successful_decode(self):
260260

261261
mock_open.return_value = mock_container
262262

263-
with patch("av.sidedata.sidedata.Type.MOTION_VECTORS", create=True):
264-
result = decode_for_motion(mock_video)
263+
result = decode_for_motion(mock_video)
265264

266-
assert isinstance(result, DecodedData)
267-
assert len(result.frames) == 1
268-
assert result.frame_size == torch.Size([480, 640, 3])
265+
assert isinstance(result, DecodedData)
266+
assert len(result.frames) == 1
267+
assert result.frame_size == torch.Size([480, 640, 3])
269268

270269
def test_no_motion_vectors(self):
271270
"""Test decode with no motion vectors."""
272271
mock_video = io.BytesIO(b"mock_video_data")
273272

274-
with patch("av.open") as mock_open, patch("av.codec.context.Flags2.EXPORT_MVS", create=True):
273+
with patch("av.open") as mock_open:
275274
# Mock frame with no motion vector side data
276275
mock_frame = Mock()
277276
mock_frame.height = 480
@@ -307,7 +306,7 @@ def test_custom_parameters(self):
307306
"""Test decode with custom parameters."""
308307
mock_video = io.BytesIO(b"mock_video_data")
309308

310-
with patch("av.open") as mock_open, patch("av.codec.context.Flags2.EXPORT_MVS", create=True):
309+
with patch("av.open") as mock_open:
311310
# Mock motion vector side data
312311
mock_side_data = Mock()
313312
mock_side_data.type = Mock()
@@ -356,11 +355,10 @@ def test_custom_parameters(self):
356355

357356
mock_open.return_value = mock_container
358357

359-
with patch("av.sidedata.sidedata.Type.MOTION_VECTORS", create=True):
360-
result = decode_for_motion(mock_video, thread_count=8, target_fps=5.0, target_duration_ratio=0.3)
358+
result = decode_for_motion(mock_video, thread_count=8, target_fps=5.0, target_duration_ratio=0.3)
361359

362-
assert isinstance(result, DecodedData)
363-
assert result.frame_size == torch.Size([480, 640, 3])
360+
assert isinstance(result, DecodedData)
361+
assert result.frame_size == torch.Size([480, 640, 3])
364362

365363

366364
class TestCheckIfSmallMotion:

0 commit comments

Comments
 (0)