diff options
| author | cashmere <cashmere@autistici.org> | 2026-07-28 19:41:14 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-07-28 19:41:14 +0200 |
| commit | e837e7504379e100ff3b56282577ec67bb88bec9 (patch) | |
| tree | eec7e6f964725a783a9e907e931862591bb46b55 /apps/web/src/services/renderer/__tests__ | |
| parent | da99dec8a2de1f3849aebbf5695c1e812b2dbdf9 (diff) | |
| download | opencut-e837e7504379e100ff3b56282577ec67bb88bec9.tar.gz | |
feat: ripple-extend resize, timeline filmstrip, export hardening
Yesterday's verified web session (gates green: 316 tests, tsc, build):
- ripple-extend pushes right-hand chain on static-element resize
- per-position video filmstrip thumbnails with zoom-adaptive density
- fps-aware export bitrate, 2s keyframes, even-dim export canvas
- freeze frame uses fixed 3s duration, prompt removed
Diffstat (limited to 'apps/web/src/services/renderer/__tests__')
| -rw-r--r-- | apps/web/src/services/renderer/__tests__/export-encoding.test.ts | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/apps/web/src/services/renderer/__tests__/export-encoding.test.ts b/apps/web/src/services/renderer/__tests__/export-encoding.test.ts new file mode 100644 index 00000000..fbf354eb --- /dev/null +++ b/apps/web/src/services/renderer/__tests__/export-encoding.test.ts @@ -0,0 +1,60 @@ +import { describe, expect, test } from "bun:test"; +import { computeVideoBitrate } from "../export-encoding"; + +describe("computeVideoBitrate", () => { + test("scales linearly with frame rate at the same resolution and quality", () => { + const at30 = computeVideoBitrate({ + width: 1920, + height: 1080, + fps: 30, + quality: "high", + }); + const at60 = computeVideoBitrate({ + width: 1920, + height: 1080, + fps: 60, + quality: "high", + }); + + expect(at60).toBe(at30 * 2); + }); + + test("applies the bits-per-pixel ladder per quality tier", () => { + const params = { width: 1920, height: 1080, fps: 30 }; + + expect(computeVideoBitrate({ ...params, quality: "low" })).toBe(3_110_400); + expect(computeVideoBitrate({ ...params, quality: "medium" })).toBe( + 6_220_800, + ); + expect(computeVideoBitrate({ ...params, quality: "high" })).toBe( + 12_441_600, + ); + expect(computeVideoBitrate({ ...params, quality: "very_high" })).toBe( + 24_883_200, + ); + }); + + test("increases monotonically across quality tiers", () => { + const params = { width: 1280, height: 720, fps: 30 }; + const bitrates = (["low", "medium", "high", "very_high"] as const).map( + (quality) => computeVideoBitrate({ ...params, quality }), + ); + + for (let i = 1; i < bitrates.length; i++) { + expect(bitrates[i]).toBeGreaterThan(bitrates[i - 1]); + } + }); + + test("returns a positive integer for fractional frame rates", () => { + const bitrate = computeVideoBitrate({ + width: 1920, + height: 1080, + fps: 29.97, + quality: "high", + }); + + expect(bitrate).toBe(12_429_158); + expect(Number.isInteger(bitrate)).toBe(true); + expect(bitrate).toBeGreaterThan(0); + }); +}); |
