* fix(cli): normalize-audio never cuts a clip that is quieter than the target
* fix(cli): carry the boost-hold rule in a name, not a comment
* fix(cli): normalize-audio no longer says a clip is matched when a limit holds it short of the target
* fix(cli): format normalize-audio, drop the extra comment, and say a held clip is held
* fix(studio-server): the render route passes a MOV ProRes profile to the render
* fix(studio-server): drop the added comment line so the comment share does not rise
* fix(studio-server): undo and redo on Windows restore a file something holds open
* fix(studio-server): a restore waits for the preview's reads to close before replacing the file
* fix(studio-server): a restore checks the project folder after the preview's reads close
* 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
* 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
* 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
* 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.
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* 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