Commit Graph
579 Commits
Author SHA1 Message Date
Miguel Ángel bff39004b0 fix(preview): the proxy copy for the video at the playhead is made ahead of the rest (#6586)
* fix(preview): the proxy copy for the video at the playhead is made ahead of the rest

* test(preview): the resolveProxy assertions carry the priority option

* fix(preview): the proxy copy asked for last goes first, and a repeat ask moves it to the front

* refactor(preview): the proxy wait loop moves its header and progress handling into helpers
2026-10-27 20:08:57 +00:00
Miguel Ángel 53c9759666 chore: release v0.8.209 (#6562) 2026-10-27 14:34:53 +00:00
Miguel Ángel d6e16aa187 fix(studio-server): undo and redo on Windows wait out a briefly held file (#6559)
* fix(studio-server): undo and redo on Windows wait out a briefly held file

* style(core): format the atomic write test
2026-10-27 14:28:43 +00:00
Miguel Ángel 88068af950 fix(studio-server): a history lock whose start cannot be recorded is given back (#6557)
* fix(studio-server): a history lock whose start cannot be recorded is given back

claim() took owner.pid and then wrote the start record; if that write threw, the error left owner.pid held by this process, so later opens waited on and then named their own pid as the busy owner. Creation and recording now release the file together.

* refactor(studio-server): drop the comment the ratchet counts against ownerLock.ts
2026-10-27 13:30:06 +00:00
Miguel Ángel cfef528d3a fix: phone videos with an undecodable first audio track check, preview and render (#6551)
* fix: phone videos with an undecodable first audio track check, preview and render

* fix(engine): a rate-lane clip bakes its ramp from the decodable audio track

* test: phone-clip tests end ffprobe options before the input
2026-10-27 13:09:02 +00:00
Miguel Ángel 404e8254e6 fix(studio-server): an HDR clip previews and snapshots the way the SDR export renders it (#6537)
* fix(studio-server): an HDR clip previews and snapshots the way the SDR export renders it

Footage tagged HLG or PQ played raw in the preview, where the browser tone-maps it its
own way, while the SDR export tone-maps it with zscale and hable: the same clip came
out lighter and with different reds and blues. HDR video now takes the tone-mapped
preview copy (the filter the export uses), and a snapshot still of HDR footage runs
the same tone map. Without an ffmpeg that has zscale and tonemap the clip plays
natively, with a warning that names the missing library.

* fix(studio-server): an HDR clip is never playable for preview, whatever its codec

Only HDR H.264 and ProRes took the tone-mapped copy: an HDR HEVC, VP9 or AV1 clip kept
its codec's test type, so a browser that can decode it was judged able to play it and
the original played with the browser's own mapping. An HDR clip now has no test type, so
the swap always fires. The missing-library warning no longer names the file.

* test(cli): the HDR still test ends ffprobe's options before its input

The repo's ffprobe argv contract requires "--" immediately before the input path; the new
test passed the still's path without it.
2026-10-27 12:49:04 +00:00
Miguel Ángel 6092785348 fix(studio-server): preview loads root-path media, images and CSS from the project, as render does (#6552)
* fix(studio-server): preview loads root-path media, images and CSS from the project, as render does

* fix(studio-server): preview writes root paths project-relative, the form Studio reads back
2026-10-27 12:29:17 +00:00
Miguel Ángel f007882ca7 chore: release v0.8.208 (#6529) 2026-10-27 11:12:48 +00:00
Miguel Ángel 859281a60d fix(studio-server): preview resolves root-path module imports to the project (#6534)
* fix(studio-server): preview resolves root-path module imports to the project

* test(studio-server): preview's own scripts make no module import; lint flags a broken import map
2026-10-27 09:48:42 +00:00
Miguel Ángel 592ca3daf1 fix(studio-server): history lock retries a busy url write and releases on failure (#6525)
* fix(studio-server): history lock retries a busy url write and releases on failure

* style(studio-server): wrap the fs mock

* style(studio-server): format the owner lock test
2026-10-27 07:09:09 +00:00
Miguel Ángel 619b8bc4d7 chore: release v0.8.207 (#6510) 2026-10-27 04:33:06 +00:00
Miguel Ángel 54d0af57eb feat(engine): render sets a keyframe interval and a peak bitrate cap (#6444)
* feat(engine): encoders cap peak bitrate and place keyframes on a set interval

* style(engine): shorten the rate-cap comment

* style(engine): drop the doc lines the comment ratchet flagged

* feat(producer): mp4 renders honour a keyframe interval and a peak bitrate cap on every encoder path

* style(producer): shorten the delivery encoder file headers

* style(producer): drop a comment line from the segment manifest

* style(producer): shorten the integration test header

* test: delivery encoder tests follow the ffprobe argv contract and run in the integration lane

* feat: the render request, server and Lambda plan carry the keyframe interval and peak bitrate cap

* fix(studio): the Studio render route passes the keyframe interval and bitrate cap to the encoder

* chore(studio-server): drop a comment the helper's name already says

* feat(cli): render and lambda render take --keyframe-interval, --max-bitrate and --buffer-size
2026-10-27 00:29:06 +00:00
Miguel Ángel 097cc094b7 fix(studio): a reload refused because the page is missing mid-edit warns instead of erroring (#6491) 2026-10-26 23:53:48 +00:00
Miguel Ángel 85fdc9aa88 chore: release v0.8.206 (#6469) 2026-10-26 15:00:57 -04:00
Miguel Ángel 3e16603d37 fix(render): a PNG's colour tags no longer change its pixels in preview, check, snapshot or render (#6453)
* fix(render): a PNG's colour tags no longer change its pixels in preview, check, snapshot or render

* fix(render): the play and present server also serves a PNG without its colour tags

* fix(render): bundled pages inline a PNG without its colour tags too
2026-10-26 17:48:57 +00:00
Miguel Angel Simon Sierra b4eab1a8c1 chore: release v0.8.205 2026-10-26 12:41:40 -04:00
SophiaHuangCc 2d695a8436 feat(studio): support GIF export with loop count (#5593)
* feat(studio): support GIF export with loop count

* fix(studio): cap GIF exports at 30 fps

* fix(studio): complete GIF export review follow-ups
2026-10-26 14:57:55 +00:00
Miguel Ángel 2d1b5cfbd2 chore: release v0.8.204 (#6423) 2026-10-26 10:16:23 -04:00
Miguel Ángel ff0a56340b chore: release v0.8.203 (#6412) 2026-10-26 07:20:07 -04:00
Miguel Ángel 52b3d32114 fix(studio-server): a failed preview copy reports its causes and what its source is (#6350)
* fix(studio-server): a failed preview copy says why its output could not open

* fix(studio-server): a failed preview copy reports its causes and what its source is

* fix(studio-server): failure reports hide spaced paths and survive a vanished source

* refactor(studio-server): read a probe's result in its own function for the complexity gate

* fix(studio-server): close the source facts function the rebase left open

* fix(studio-server): a failure report reads the source size through one open descriptor
2026-10-26 10:54:09 +00:00
Miguel Ángel 84fd701daa feat(studio): preview copy progress, retry and a remembered quality (#6366)
* feat(studio-server): a copy being made says how far it has got, and can be retried

* feat(core): the preview reports its lighter copies' progress and retries failed ones

* feat(studio): the preview quality and its lighter copies' progress live in the player store

* feat(studio): every host forwards the preview quality, and the choice is kept per computer

* feat(studio): the preview quality knows if a person or the app chose it

* fix(core): the first report of the lighter copies is not held back by the throttle

* test(studio): the preview quality preference test writes under the real key

* fix(core): a quality change reports its copies at once, not after the throttle

* style: format the preview quality files

* feat(core): report how playback is going, and what the preview holds, to the host

* fix(studio): the preview quality levels come from a browser-safe core entry

* style: format the new entry's files

* style: drop two comments the file's ratchet and the citation check refuse

* feat(core): tell which lower levels would give a video a lighter copy

* fix(studio): drop the old level's playback health when the level changes

* feat(studio-server): preview facts carry the probed codec of every video

* refactor(studio): route the preview's reports through a table for the complexity gate

* fix(core): a copy's retry flag is sent on the first ask only, not on every poll

* fix(core): type the health report and restore the player hook's complexity directive

* style: cut four comments the comment ratchet refuses

* fix(studio): keep playerStore.ts within its 600-line cap

* fix(core): a scene mounting does not restart the playback health window

* fix(core): the playback health window restarts only when the display scale changes

* fix(core): a repeated display scale no longer restarts the playback health window

* fix(studio): route the preview's reports by an explicit list of message types
2026-10-26 09:20:07 +00:00
Vance Ingalls f8d51f3146 chore: release v0.8.202 (#6404) 2026-10-26 07:55:04 +00:00
Miguel Ángel 2e23b7e434 fix(studio-server): copies are found by content and made by one process at a time (#6358)
* perf(studio-server): a preview copy is keyed by the file's content, so copied projects reuse it

* fix(studio-server): copies are keyed by content and made by one process at a time

* docs(studio-server): shorten the copy lock comment

* fix(studio-server): find a copy by place and time first, by whole-file content when that misses

* fix(studio-server): hash small sources in one read; wait longer in tests for the hash

* test(studio-server): cache folder listings ignore the copy index files

* style(studio-server): format the copy lookup files

* docs(studio-server): shorten the copy lookup comment

* fix(studio-server): hash a source through one open handle, not a check then a read

* fix(studio-server): hash through one descriptor, keeping the small-file path synchronous

* style(studio-server): format the cache key file
2026-10-26 06:20:03 +00:00
Miguel Ángel 3ff8cd8683 chore: release v0.8.201 (#6377) 2026-10-26 04:50:26 +00:00
Miguel Ángel 38d9aeb5ea feat(core): lighter preview copies of heavy videos below full quality (#6365)
* feat(core): tell which video files deserve a lighter preview copy, and at which size

* feat(studio-server): serve lighter copies of heavy playable files, a keyframe every second

* feat(core): the preview plays lighter copies of heavy videos below full quality

* style: shorten two comments

* style: shorten a comment

* style: shorten a comment

* fix(core): format the preview quality files and split the copy sizing for the complexity gate

* style: format the studio-server preview files

* fix(core): type the copy job's level as a preview quality

* chore(producer): raise the package size budget for the preview runtime growth
2026-10-26 03:53:21 +00:00
Miguel Ángel badb61aa99 fix(studio-server): take over a history lock whose pid now runs another process (#6386)
* fix(studio-server): take over a history lock whose pid now runs another process

* style(studio-server): drop two comments from the history lock
2026-10-26 03:21:37 +00:00
Miguel Ángel e4bdf8c51c perf(studio-server): copy alpha cut-outs several pieces at a time (#6342) 2026-10-26 02:14:49 +00:00
Miguel Ángel 6f4d46ad34 fix(studio-server): a refused preview frame says so at once instead of timing out (#6074)
* fix(studio-server): a refused preview frame says so at once instead of timing out

A frame the server refuses (project gone, bad variables) loaded a JSON body: no runtime and no error, so Studio waited three 15s budgets and reported 'waiting for runtime'. The refusal now reaches the frame as a page that reports it, like a failing preview script.

* chore(studio-server): remove redundant preview refusal comments
2026-10-25 23:05:51 +00:00
Akshar Patel 6a20ec9e9a fix(cli): preserve clip lengths when duplicating media (#6280)
* fix(cli): prevent overlaps when duplicating natural-duration media

* fix(cli): preserve absolute ends when duplicating clips

* fix(cli): keep rippled clip bounds together
2026-10-25 23:01:27 +00:00
Miguel Ángel 2c10eb0a33 chore: release v0.8.200 (#6337) 2026-10-25 20:50:21 +00:00
Miguel Ángel 42b84632a8 chore: release v0.8.199 (#6328) 2026-10-25 18:13:20 +00:00
Miguel Ángel b2124b2a56 perf(studio-server): the browser-playable copy of an alpha video encodes on four threads (#6325)
* perf(studio-server): the browser-playable copy of an alpha video encodes on four threads

libvpx runs on one thread unless told, so the alpha copy of a 4K video took several times its length on a small machine.

* docs(studio-server): drop a comment line the name already carries
2026-10-25 17:35:33 +00:00
Miguel Ángel ada9932d4e fix(cli): a long video copy reports progress, resumes in 15 s pieces and stops only when stalled (#6307)
* fix(cli): a long video copy reports progress, resumes in 15 s pieces and stops only when stalled

* perf(core): a video copy's size box follows the stage within a fifth, not a half

* docs(cli): shorten two comments to the line limit

* fix(cli): the copy heartbeat drops a finished copy; size budgets follow the stall and progress code

* chore: size budgets rise by this change's measured bytes
2026-10-25 13:53:03 +00:00
Miguel Ángel d7f323d319 chore: release v0.8.198 (#6305) 2026-10-25 12:42:50 +00:00
Miguel Ángel f51650d8a7 chore: release v0.8.197 (#6298) 2026-10-25 09:17:12 +00:00
Miguel Ángel 4d154c6a23 test: two flaky queue tests no longer race real time or the first copy's start (#6283) 2026-10-25 07:13:22 +00:00
Miguel Ángel 45167743a6 chore: release v0.8.196 (#6288) 2026-10-25 06:52:05 +00:00
Miguel Ángel 7bc363c87c fix(studio-server): undoing a video rename brings the file back under its old name (#6285)
* fix(studio-server): undoing a video rename brings the file back under its old name

* fix(studio-server): name the bytes a write's deletes set aside
2026-10-25 05:43:55 +00:00
Miguel Ángel 1776b42736 chore: release v0.8.195 (#6273) 2026-10-25 03:18:09 +00:00
James RussoandClaude Opus 5.5 7f19f2335a feat(studio): load GSAP from the CLI's bundled copy by default (#6256)
* feat(studio): load GSAP from the CLI's bundled copy by default

Studio preview now loads the GSAP, CustomEase and MotionPathPlugin scripts
it adds from files the CLI ships and serves same-origin at /api/vendor/npm,
instead of jsDelivr. HYPERFRAMES_GSAP_BASE_URL still wins when set, and a
composition on another GSAP version gets its plugin from jsDelivr.

Renders now honor HYPERFRAMES_GSAP_BASE_URL when they replace a missing
local GSAP script, and the setting accepts plain http only for loopback
hosts.

Closes #6205

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(studio): keep comment share flat for the GSAP local root

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(cli): find the installed gsap with node resolution when run from source

The Windows CI lane installs with the hoisted linker, so gsap is not under
packages/core/node_modules there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(producer): load a nested composition's missing GSAP from the mirror

A sub-composition's missing local gsap/dist script was hoisted into the
render unchanged, so HYPERFRAMES_GSAP_BASE_URL (and the jsDelivr fallback)
only reached the entry document. Run the same rewrite on every
sub-composition before it is compiled, resolving its path the way the
inliner will hoist it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 03:08:42 +00:00
James RussoandClaude Opus 5.5 685cd75a92 fix(studio): load GSAP core when only a GSAP plugin is on the page (#6260)
* fix(studio): load GSAP core when only a GSAP plugin is on the page

The Studio preview checked for GSAP core by matching "gsap" anywhere in a
script src, so the MotionPathPlugin it had just injected (served from
gsap@x/dist/) counted as core. A composition with a motion path and
Studio-edited motion but no GSAP script of its own then got the plugin and
no core, and its animations did not run.

Detect core by file name (gsap.js, gsap.min.js, or a vendored
gsap-<version>.min.js) on any host or path, and inject Studio motion's core
before the MotionPathPlugin so the plugin can register onto it. Apply the
same core-only check to the sub-composition preview fallback and the
missing_gsap_script lint rule.

Refs #6205

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(studio): keep GSAP core detection within the comment budget

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(studio): load GSAP core ahead of head plugins and only on a real core script

Studio motion and sub-composition previews now insert GSAP core before the
first GSAP plugin script in the head, so an authored MotionPathPlugin or
CustomEase registers on core instead of running first. Core detection keys on
a core script (src, inlined marker, license banner or library body), not on
usage like gsap.registerPlugin() or gsap.defaults(). The missing_gsap_script
lint rule drops the same usage-based and plugin-banner shortcuts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 02:37:08 +00:00
Miguel Ángel 2e397dba59 chore: release v0.8.194 (#6269) 2026-10-24 22:17:19 -04:00
Miguel Ángel 85fb19f1e8 fix(studio-server): undo and restore keep the media they delete or replace (#6215)
* fix(studio-server): undo and restore keep the media they delete or replace

* fix(studio-server): set-aside media is freed only after a whole undo or restore lands

* fix(studio-server): set-aside media does not count toward the history budget

* fix(studio-server): set-aside media keeps its own ledger apart from copied blobs

* fix(studio-server): a set-aside copy waits for every path that counts on it

* fix(studio-server): an unreadable history folder fails the read instead of looking empty

* fix(studio-server): history opens past a temp file a crash left behind

* fix(studio-server): trim a comment so the comment share holds
2026-10-25 01:48:06 +00:00
Abdullah M. Nazif 1c14fbb542 fix(studio): allow a local GSAP dependency mirror (#6247) 2026-10-24 22:13:28 +00:00
Miguel Ángel 89081b9197 chore: release v0.8.193 (#6229) 2026-10-24 12:39:08 -04:00
Miguel Ángel 0eae4946d3 fix(studio-server): a history restore refuses to remove every tracked file (#6175)
* fix(studio-server): a history restore refuses to remove every tracked file

* test(studio-server): compare the held clip by bytes so the adopting check stays fast

* fix(studio-server): history's own hidden records do not count as files a restore keeps

* refactor(studio-server): name the restore guard's check instead of commenting it

* chore(studio-server): re-baseline the packed size budget for the restore guard
2026-10-24 12:51:30 +00:00
Miguel Ángel c16b783f5e chore: release v0.8.192 (#6206) 2026-10-24 08:51:29 +00:00
Miguel Ángel 5ebbc8ef6d fix(studio-server): project history no longer copies video, audio or huge files (#6171)
* fix(studio-server): project history no longer copies video, audio or huge files

* fix(studio-server): clean drops old video and audio copies in every history

* fix(studio-server): TypeScript source is not media, so its history is kept

* fix(studio-server): split the media reclaim and point the slow-copy route test at a non-media file

* fix(studio-server): no unused expression when collecting a history's hashes
2026-10-24 04:12:48 +00:00
Abdullah M. Nazif 0aa728b1aa fix(studio-server): decode authored audio attributes for loudness (#5289) 2026-10-24 04:11:25 +00:00
Miguel Ángel cf7266d815 chore: release v0.8.191 (#6170) 2026-10-24 01:40:50 +00:00