feat: replace PyPI opencv wheels with ffmpeg-free builds in Dockerfiles (#4336)
## Summary
- After `uv sync`, the Dockerfile downloads a source-built
`opencv-contrib-python-headless` wheel (compiled with `WITH_FFMPEG=OFF`,
`ENABLE_CONTRIB=1`, `ENABLE_HEADLESS=1`) from the GitHub release and
substitutes it for all PyPI opencv-python variants
- The contrib-headless variant is a strict superset of the cv2 API (core
+ contrib modules, no GUI), so a single wheel replaces `opencv-python`,
`opencv-python-headless`, and `opencv-contrib-python`, eliminating 14
bundled ffmpeg CVEs
- Validated end-to-end: PaddleOCR model load + detection + recognition
on a real document image succeeds with the substituted wheel on
wolfi-base arm64
## Dependencies
> **Depends on #4335** — the GHA workflow that builds and publishes the
opencv wheels must be merged and run first so the GitHub release exists
for the Dockerfile to download from. ✅ Merged and release published.
## Test plan
- [x] Merge and run the workflow in #4335 to create the wheel release
- [x] Local smoke test: PaddleOCR OCR on a real document image with
substituted wheel (wolfi-base arm64)
- [ ] Build the main `Dockerfile` and verify opencv imports work without
`.libs`
- [ ] Confirm no ffmpeg-related CVEs remain in a container scan
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Medium risk because it changes a core transitive native dependency in
the Docker image (OpenCV), which could affect OCR/inference behavior or
break builds if the wheel/arch tag mismatch occurs, despite hash
verification.
>
> **Overview**
> **Hardens the Docker image against ffmpeg CVEs** by replacing all PyPI
`opencv-*` packages after `uv sync` with a downloaded, hash-verified
`opencv-contrib-python-headless` wheel built with `WITH_FFMPEG=OFF`.
>
> The Docker build now selects the wheel by architecture
(`x86_64`/`aarch64`), uninstalls any existing OpenCV variants, installs
the pinned wheel version, and bumps the library version/changelog to
`0.22.22`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a58f84268570f1f6d6f638b4f61011cdf2d6e617. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>