feat(tools): vmaf-tune Phase E — per-title bitrate ladder (game-changer)#371
Merged
feat(tools): vmaf-tune Phase E — per-title bitrate ladder (game-changer)#371
Conversation
97e5fd3 to
1515c1c
Compare
1515c1c to
bd0958d
Compare
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Scaffolds Phase E of vmaf-tune by adding a per-title bitrate ladder generator (Pareto + diminishing-returns “hull”, knee selection, and manifest emitters) plus a new vmaf-tune ladder CLI subcommand and accompanying documentation/tests.
Changes:
- Added
vmaftune.laddermodule implementing ladder sampling API, hull computation, knee selection, and HLS/DASH/JSON emitters. - Added
vmaf-tune ladderCLI subcommand with parsing helpers and output support. - Added Phase E docs/ADR/research notes and a new ladder-focused test suite.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/vmaf-tune/src/vmaftune/ladder.py | New Phase E core implementation: sampling contract, hull math, rung selection, manifest emitters, convenience wrapper. |
| tools/vmaf-tune/src/vmaftune/cli.py | Registers ladder subcommand and parses ladder-related flags. |
| tools/vmaf-tune/tests/test_ladder.py | Adds synthetic sampler + invariants/tests for hull, knee selection, and manifest formats. |
| tools/vmaf-tune/AGENTS.md | Documents Phase E invariants (two-pass hull, sampler behavior). |
| docs/usage/vmaf-tune.md | Documents Phase E usage/flags and scaffold status. |
| docs/research/0067-vmaf-tune-phase-e-bitrate-ladder.md | Adds Phase E algorithm survey write-up. |
| docs/rebase-notes.md | Adds rebase note entry for Phase E ladder scaffold. |
| docs/adr/README.md | Adds ADR index entry for ADR-0295. |
| docs/adr/0295-vmaf-tune-phase-e-bitrate-ladder.md | Adds Phase E ADR describing decision/scope. |
| CHANGELOG.md | Adds Unreleased entry describing Phase E ladder feature and tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+243
to
+251
| # Avoid duplicates if two targets snap to the same point. | ||
| while idx in seen and idx + 1 < len(hull): | ||
| idx += 1 | ||
| seen.add(idx) | ||
| chosen.append(hull[idx]) | ||
| chosen.sort(key=lambda p: p.bitrate_kbps) | ||
| return [_rendition_of(p) for p in chosen] | ||
|
|
||
|
|
Comment on lines
+326
to
+335
| def _emit_hls(ladder: Sequence[Rendition]) -> str: | ||
| lines: list[str] = ["#EXTM3U", "#EXT-X-VERSION:6"] | ||
| for r in ladder: | ||
| bps = int(round(r.bitrate_kbps * 1000.0)) | ||
| uri = f"rendition_{r.width}x{r.height}_{int(round(r.bitrate_kbps))}k.m3u8" | ||
| lines.append( | ||
| f"#EXT-X-STREAM-INF:BANDWIDTH={bps},RESOLUTION={r.width}x{r.height}," | ||
| f'CODECS="avc1.640028"' | ||
| ) | ||
| lines.append(uri) |
Comment on lines
+343
to
+350
| reps.append( | ||
| f' <Representation id="r{i}" bandwidth="{bps}" ' | ||
| f'width="{r.width}" height="{r.height}" ' | ||
| f'codecs="avc1.640028" mimeType="video/mp4">\n' | ||
| f" <BaseURL>rendition_{r.width}x{r.height}_" | ||
| f"{int(round(r.bitrate_kbps))}k.mp4</BaseURL>\n" | ||
| f" </Representation>" | ||
| ) |
Comment on lines
+196
to
+197
| Positive = counter-clockwise turn (point ``b`` is above the line | ||
| o->a, which is what we want on the upper hull). |
Comment on lines
+618
to
+626
| manifest = build_and_emit( | ||
| src=args.src, | ||
| encoder=args.encoder, | ||
| resolutions=resolutions, | ||
| target_vmafs=target_vmafs, | ||
| quality_tiers=args.quality_tiers, | ||
| format=args.format, | ||
| spacing=args.spacing, | ||
| ) |
Comment on lines
+365
to
+366
| help="source video (used to label the manifest; sampling is currently " | ||
| "Phase B / Phase A driven)", |
Comment on lines
24
to
+32
| [ADR-0276](../adr/0276-vmaf-tune-phase-d-per-shot.md)). Phases B | ||
| (target-VMAF bisect), C (per-title CRF predictor), E (Pareto ABR | ||
| ladder) and F (MCP tools) are not implemented yet — see ADR-0237. | ||
| This doc covers **Phase A** of the six-phase roadmap (a `libx264` grid | ||
| sweep that produces the corpus the later phases consume) and **Phase E** | ||
| (per-title bitrate-ladder generator — scaffold-only until Phase B's | ||
| target-VMAF bisect merges). Phases B (target-VMAF bisect), C (per-title | ||
| CRF predictor), D (per-shot dynamic CRF), and F (MCP tools) are not | ||
| implemented yet — see [ADR-0237](../adr/0237-quality-aware-encode-automation.md) |
Comment on lines
+303
to
+305
| - **vmaf-tune Phase E — per-title bitrate-ladder generator | ||
| (ADR-0277).** Ships | ||
| [`tools/vmaf-tune/src/vmaftune/ladder.py`](tools/vmaf-tune/src/vmaftune/ladder.py) |
Comment on lines
+1
to
+5
| # Research-0054: vmaf-tune Phase E — per-title bitrate-ladder algorithm survey | ||
|
|
||
| - **Date**: 2026-05-03 | ||
| - **Author**: Lusoris (with Claude assistance) | ||
| - **Companion**: [ADR-0295](../adr/0295-vmaf-tune-phase-e-bitrate-ladder.md) |
Scaffolds the Phase E ladder generator (ADR-0277) — the highest-leverage gap surfaced by PR #354's capability audit (Bucket #6). Mirrors the Netflix per-title encoding paper: sample (resolution × target-VMAF), take the Pareto upper-convex hull on (bitrate, vmaf), pick n rungs along the hull, emit an HLS / DASH / JSON manifest. Currently scaffold-only: the production sampler that drives Phase B's target-VMAF bisect (PR #347) lands once that PR merges. Default sampler raises NotImplementedError; tests inject a synthetic stub modelled on the Netflix paper's R-D curves. - New module tools/vmaf-tune/src/vmaftune/ladder.py — build_ladder, convex_hull (Pareto filter + diminishing-returns envelope), select_knees (log-bitrate or VMAF spacing), emit_manifest (HLS / DASH / JSON), and a build_and_emit convenience. - New `vmaf-tune ladder` CLI subcommand with the canonical 5-rung 1080p/720p/480p/360p/240p default rendition set. - 15 new ladder tests (28 total in tools/vmaf-tune/tests/) covering hull correctness on a synthetic Netflix-paper-shaped cloud, knee selection invariants, and HLS / DASH / JSON manifest emit shape. - ADR-0277 (Proposed; flips to Accepted once Phase B integration PR lands and a real-corpus PLCC validation digest reports the delta). - Research-0054 surveys the algorithm space (Netflix per-title paper, Apple HLS authoring spec, JND-spaced, BO sampling). - docs/usage/vmaf-tune.md gains a "Per-title ladder (Phase E)" section with the canonical invocation. - CHANGELOG, rebase-notes (#229), AGENTS.md invariant note. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
181224a to
7076c54
Compare
7076c54 to
93e0d77
Compare
12 tasks
This was referenced May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Scaffolds Phase E of
vmaf-tune— the per-title bitrate-ladder generator. PR #354's capability audit ranked this Bucket #6 the single biggest game-changer for the fork ("reshapes from 'best open-source VMAF measurement' into 'only open-source per-title ladder generator with measured-PLCC proxy'"). Mirrors the Netflix per-title encoding paper: sample (resolution × target-VMAF), take the Pareto upper-convex hull on (bitrate, vmaf), picknrungs along the hull, emit an HLS / DASH / JSON manifest.tools/vmaf-tune/src/vmaftune/ladder.py—build_ladder(pluggable sampler),convex_hull(two-pass: Pareto filter + diminishing-returns envelope),select_knees(log-bitrate or VMAF spacing),emit_manifest(HLS / DASH / JSON), and abuild_and_emitconvenience.vmaf-tune ladderCLI subcommand with the canonical 5-rung 1080p/720p/480p/360p/240p default rendition set.tools/vmaf-tune/tests/) — hull correctness on a synthetic Netflix-paper-shaped cloud, knee invariants, HLS / DASH / JSON manifest shape.Test plan
python -m pytest tools/vmaf-tune/tests/ -v— 28 passed (13 corpus + 15 ladder).python -m ruff check tools/vmaf-tune/— clean.PYTHONPATH=tools/vmaf-tune/src python -m vmaftune.cli ladder --help— argparse renders._default_samplerfor a real bisect-driven sampler; end-to-end smoke against a Netflix Public clip.Six deep-dive deliverables (ADR-0108)
docs/research/0068-vmaf-tune-phase-e-bitrate-ladder.md(algorithm survey: Netflix per-title, Apple HLS authoring spec, JND-spaced, BO sampler).## Alternatives considered(5 alternatives weighed: Pareto+convex / Apple fixed / geometric / JND / BO).tools/vmaf-tune/AGENTS.mdupdated with the two-pass hull invariant and the "default sampler raises by design" rule.python -m pytest tools/vmaf-tune/tests/test_ladder.py -v.docs/rebase-notes.mdentry0229(no upstream-shared paths touched; fork-local Python tool).References
docs/adr/0277-vmaf-tune-phase-e-bitrate-ladder.md.docs/adr/0237-quality-aware-encode-automation.md.🤖 Generated with Claude Code