mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(render): reject unsupported ProRes rate controls (#3702)
This commit is contained in:
@@ -95,6 +95,9 @@ browser already supports the source or you are diagnosing the proxy itself.
|
||||
## Choose quality and frame rate
|
||||
|
||||
The default `standard` quality is the right choice for most finished work.
|
||||
MOV is an alpha-preserving editing intermediate and always uses the fixed
|
||||
ProRes 4444 profile. `--crf` and `--video-bitrate` do not map to that profile
|
||||
and are rejected for MOV; choose MP4 or WebM when you need those controls.
|
||||
|
||||
```bash
|
||||
# Faster review version
|
||||
|
||||
@@ -857,7 +857,7 @@ The flags that come up most:
|
||||
| `--composition, -c` | `index.html` | Render a different composition file. Sub-compositions using `<template>` wrappers must be referenced from `index.html` via `data-composition-src`. |
|
||||
| `--format` | `mp4` | `mp4`, `webm`, `mov`, `gif`, or `png-sequence`. WebM and MOV carry transparency; `png-sequence` writes RGBA frames to a directory. |
|
||||
| `--fps, -f` | root `data-fps`, otherwise 30 | 1–240, or an ffmpeg rational like `30000/1001` for 29.97 |
|
||||
| `--quality, -q` | `standard` | `draft`, `standard`, or `high`. Drives CRF and bitrate. |
|
||||
| `--quality, -q` | `standard` | `draft`, `standard`, or `high`. Drives MP4/WebM encoder settings; MOV always uses the fixed alpha-preserving ProRes 4444 profile. |
|
||||
| `--resolution` | the composition's size | Supersample to a preset via Chrome's `deviceScaleFactor`. Aspect ratio must match and the scale must be a whole multiple. Not with `--hdr`. See [4K rendering](/guides/4k-rendering). |
|
||||
| `--docker` | off | Render inside Docker for [deterministic output](/concepts/determinism) |
|
||||
| `--variables` | — | JSON object merged over the composition's `data-composition-variables` defaults |
|
||||
@@ -869,8 +869,8 @@ Quality and file size:
|
||||
|
||||
| Flag | Default | Description |
|
||||
| ---------------------- | --------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `--crf` | from `--quality`| Override encoder CRF, 0–51. Lower is better quality. Not with `--video-bitrate`. |
|
||||
| `--video-bitrate` | from `--quality`| Target bitrate, e.g. `10M` or `5000k`. Not with `--crf`. |
|
||||
| `--crf` | from `--quality`| Override MP4/WebM encoder CRF, 0–51. Lower is better quality. Not with `--video-bitrate`; rejected for MOV. |
|
||||
| `--video-bitrate` | from `--quality`| Target MP4/WebM bitrate, e.g. `10M` or `5000k`. Not with `--crf`; rejected for MOV. |
|
||||
| `--vp9-cpu-used` | encoder default | libvpx-vp9 speed/quality trade-off for WebM, -8 to 8. Env: `PRODUCER_VP9_CPU_USED`. |
|
||||
| `--gif-loop` | `0` | GIF loop count, `0` for forever. Range 0–65535, `--format gif` only. |
|
||||
| `--video-frame-format` | `auto` | How source video frames are extracted: `auto`, `jpg`, `png`. Use `png` for UI recordings, screen captures, and other colour-sensitive footage. |
|
||||
|
||||
@@ -142,7 +142,8 @@ export default defineCommand({
|
||||
quality: {
|
||||
type: "string",
|
||||
alias: "q",
|
||||
description: "Quality: draft, standard, high",
|
||||
description:
|
||||
"Quality: draft, standard, high. MOV always uses the fixed alpha-preserving ProRes 4444 profile.",
|
||||
default: "standard",
|
||||
},
|
||||
skill: {
|
||||
@@ -195,11 +196,13 @@ export default defineCommand({
|
||||
},
|
||||
crf: {
|
||||
type: "string",
|
||||
description: "Override encoder CRF. Mutually exclusive with --video-bitrate.",
|
||||
description:
|
||||
"Override MP4/WebM encoder CRF. Mutually exclusive with --video-bitrate; unsupported for MOV.",
|
||||
},
|
||||
"video-bitrate": {
|
||||
type: "string",
|
||||
description: "Target video bitrate such as 10M. Mutually exclusive with --crf.",
|
||||
description:
|
||||
"Target MP4/WebM video bitrate such as 10M. Mutually exclusive with --crf; unsupported for MOV.",
|
||||
},
|
||||
"vp9-cpu-used": {
|
||||
type: "string",
|
||||
|
||||
@@ -89,6 +89,34 @@ describe("createRenderPlan", () => {
|
||||
expect(() => createRenderPlan({ dir: projectDir, quality: "maximum" })).toThrow(CliUsageError);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["--crf", { crf: "18" }],
|
||||
["--video-bitrate", { "video-bitrate": "78M" }],
|
||||
])("rejects unsupported %s rate control for ProRes MOV", (flag, encoderArgs) => {
|
||||
expect(() => createRenderPlan({ dir: projectDir, format: "mov", ...encoderArgs })).toThrow(
|
||||
CliUsageError,
|
||||
);
|
||||
expect(vi.mocked(console.error).mock.calls.flat().join("\n")).toContain(flag);
|
||||
expect(vi.mocked(console.error).mock.calls.flat().join("\n")).toContain(
|
||||
"fixed alpha-preserving ProRes 4444",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps MOV quality tiers on the fixed alpha-preserving profile", () => {
|
||||
const plan = createRenderPlan({ dir: projectDir, format: "mov", quality: "high" });
|
||||
|
||||
expect(plan).toMatchObject({ format: "mov", quality: "high" });
|
||||
expect(plan.crf).toBeUndefined();
|
||||
expect(plan.videoBitrate).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps MP4 and WebM rate controls available", () => {
|
||||
expect(createRenderPlan({ dir: projectDir, format: "mp4", crf: "18" }).crf).toBe(18);
|
||||
expect(
|
||||
createRenderPlan({ dir: projectDir, format: "webm", "video-bitrate": "10M" }).videoBitrate,
|
||||
).toBe("10M");
|
||||
});
|
||||
|
||||
it("rejects batch and single-render variables before execution", () => {
|
||||
expect(() =>
|
||||
createRenderPlan({ dir: projectDir, batch: "rows.json", variables: '{"name":"Ada"}' }),
|
||||
|
||||
@@ -408,6 +408,15 @@ export function createRenderPlan(args: RenderCommandArgs, now = new Date()): Ren
|
||||
);
|
||||
failUsage();
|
||||
}
|
||||
if (format === "mov" && (crf !== undefined || videoBitrate !== undefined)) {
|
||||
const flag = crf !== undefined ? "--crf" : "--video-bitrate";
|
||||
errorBox(
|
||||
"Unsupported ProRes rate control",
|
||||
`${flag} does not apply to MOV. MOV uses a fixed alpha-preserving ProRes 4444 profile.`,
|
||||
`Remove ${flag}, or choose MP4/WebM when you need CRF or target-bitrate control.`,
|
||||
);
|
||||
failUsage();
|
||||
}
|
||||
|
||||
const quiet = args.quiet ?? false;
|
||||
const batchJson = args.json ?? false;
|
||||
|
||||
Reference in New Issue
Block a user