Commit Graph
1016 Commits
Author SHA1 Message Date
Miguel Angel Simon Sierra 597c14a887 fix(telemetry): send feedback as plain events, not PostHog surveys
CLI and Studio feedback were emitted as `survey sent` with `$survey_*`
properties, so every rating was ingested as a PostHog survey response even
though no survey definition, targeting, or popover backs them.

Emit `cli_render_feedback` and `studio_feedback` with plain `rating` /
`comment` properties instead. Same fields, same call sites, same opt-out.
2026-07-27 16:46:51 +02:00
James 5cad2bc312 chore: release v0.7.76 2026-07-27 05:08:40 +00:00
James 45b458c007 chore: release v0.7.75 2026-07-27 03:38:16 +00:00
James Russo 0cc78c1d42 chore: release v0.7.74 (#2818) 2026-07-26 21:57:54 -04:00
James 527751c871 chore: release v0.7.73 2026-07-26 21:25:03 +00:00
Ular Kimsanov 5bfda4e087 Merge pull request #2797 from heygen-com/feat/studio-professional-color-grading
feat(studio): add professional grading controls
2026-07-26 10:45:43 -07:00
ukimsanov 794930a075 fix(studio): align professional grading contracts 2026-07-26 01:47:06 -07:00
ukimsanov c1fcf7534f fix(studio): clear stale color scopes 2026-07-26 01:29:32 -07:00
ukimsanov 20ef48abcb feat(studio): add professional grading controls 2026-07-26 01:29:32 -07:00
James Russo 72ae39e3d0 chore: release v0.7.72 (#2800) 2026-07-26 02:01:10 -04:00
Miguel Angel Simon Sierra d05ecb1091 fix(studio): scope the per-file keyframe-cache clear to its own keys
R3 review follow-ups on the keyframe cache:

- clearKeyframeCacheForFile collected ids from the index.html alias prefix
  too, so a re-scan of one composition file wiped rows a sibling file had
  just written (several files re-scan concurrently). Only the file's own
  prefixed keys name the ids now; clearKeyframeCacheForElement still takes
  the alias and bare key with them.
- toClipKeyframes fell back to a fixed 1s tween duration, which put a
  duration-less tween's keyframes at a percentage no edit path agreed with.
  It now spans the clip, matching resolveEditableTweenDuration.
- collectAnimatableKeyframeProperties takes `object` so call sites drop
  their `as Record<string, unknown>` casts.

Regression tests cover both fixes.
2026-07-26 02:13:38 +02:00
Miguel Angel Simon Sierra acf6766ed8 refactor(studio): one owner for clip-relative keyframe rows
Each keyframe-cache writer re-derived a clip-relative percentage inline, and the
post-commit writer rounded to 0.1% while the others used 0.001%. Selection keys
embed that number, so a commit-time rewrite could orphan a live key.
toClipPercentage owns the rounding, toClipKeyframes owns the whole row (percentage
plus the tween percentage and animation identity the lanes read), and the parsed
write reuses elementCacheKeys instead of open-coding the three key variants.
2026-07-26 00:51:19 +02:00
Miguel Angel Simon Sierra e34e529720 fix(studio): keep gsapAnimations in sync with the keyframe cache
An ungrouped tween (mixed property groups classify to propertyGroup
undefined) fed keyframeCache but was skipped by every gsapAnimations
writer, so the collapsed row drew diamonds the expanded lanes had no
source animation to render. Drop the property-group gate at all three
writers; lane consumers already filter by group.

Also route the same-percentage merge in updateKeyframeCacheFromParsed
through deduplicateKeyframes so the easeAmbiguous rule has one owner.
2026-07-25 22:48:00 +02:00
Miguel Angel Simon Sierra e4d7bde64f feat(studio): add keyframe timeline state 2026-07-25 21:40:44 +02:00
Miguel Angel Simon Sierra c253dec23b feat(studio): add keyframe ease editor 2026-07-25 14:12:17 +02:00
Miguel Angel Simon Sierra d84e999f72 fix(parsers): preserve authored keyframe intent 2026-07-25 14:12:17 +02:00
ukimsanov bf47416e14 refactor(studio): simplify preview workspace layout 2026-07-24 18:42:49 -07:00
ukimsanov d5c7d3ee16 fix(studio): preserve composed media treatments 2026-07-24 18:42:37 -07:00
ukimsanov 39c2341c4d feat(studio): add media treatment inspector 2026-07-24 18:42:37 -07:00
James d07d1874b6 chore: release v0.7.71 2026-07-24 19:03:16 +00:00
ukimsanov 70213c5a85 feat(core): define media treatment capabilities 2026-07-24 08:56:24 -07:00
Vance Ingalls b9c3e3a4b6 chore: release v0.7.70 2026-07-23 20:59:30 -07:00
James f0034228f5 chore: release v0.7.69 2026-07-23 12:03:36 -07:00
James 71d84ff27f chore: release v0.7.68 2026-07-22 04:41:54 +00:00
James 4b6bb8ffa9 chore: release v0.7.67 2026-07-21 23:51:05 +00:00
Miguel Angel Simon Sierra 84841b8dae chore: release v0.7.66 2026-07-21 14:36:22 +02:00
Miguel Ángel 07965e9fe9 fix(studio): play preview audio at speeds above 1x (#2691)
* fix(studio): play preview audio at speeds above 1x

The player force-muted preview audio whenever playback rate exceeded 1x
and disabled the mute button (and the M shortcut) in that state. Users
changing speed to 2x heard nothing, and clicking unmute did nothing.

Media elements play audio fine at any rate (pitch preserved by default),
so remove the special case: audio now follows only the user's mute
toggle at every speed. Drops the shouldMutePreviewAudio helper and the
audioAutoMuted UI/keyboard gating that existed solely for it.

* test(studio): update seek audio test for unmuted-above-1x behavior

useTimelinePlayer.seek.test.ts still asserted the old force-mute: at 2x
with the user unmuted it expected a set-muted{muted:true} message. With
audio now following only the user's toggle, the preview receives
set-muted{muted:false}. Update the assertion and title to match.
2026-07-21 14:32:13 +02:00
James 835fa899c7 chore: release v0.7.65 2026-07-21 04:45:59 +00:00
ukimsanov 270179d94b fix(studio): harden flat keyframe retiming 2026-07-20 19:26:10 -07:00
ukimsanov f25a136927 fix(studio): retime flat tween keyframe diamonds 2026-07-20 18:56:14 -07:00
James ab8b50afd7 refactor(repo): resolve changed-code audit 2026-07-20 11:59:57 -07:00
James 3454a80eb2 test(repo): execute packed subpaths 2026-07-18 18:27:44 -04:00
James 8d9d9c016e refactor(repo): centralize package subpaths 2026-07-18 15:58:23 -04:00
Miguel Ángel 11cd61d1e3 chore: release v0.7.64 (#2630)
Release HyperFrames v0.7.64.
2026-07-18 15:02:20 -04:00
Miguel Ángel f7911d10b0 fix(studio): keep composition multi-drag positions in sync (#2629) 2026-07-18 20:57:44 +02:00
James 562544f68d refactor(core): own edit protocol contract 2026-07-18 13:24:57 -04:00
James 38c2d06933 refactor(studio): gate SDK operation families 2026-07-18 11:34:22 -04:00
Miguel Ángel feb675a89d chore: release v0.7.63 (#2628) 2026-07-18 04:44:56 -04:00
Miguel Ángel 7f76170956 chore: release v0.7.62 (#2626) 2026-07-17 22:02:49 -04:00
Miguel Ángel e64a22893a fix(studio): preserve alpha proxy playback (#2625)
* fix(studio): preserve alpha proxy playback

* test(cli): pin VP8 alpha proxy pre-resolution

* fix(studio): emit textarea field-sizing CSS

* test(studio): verify textarea CSS generation
2026-07-17 21:56:27 -04:00
Miguel Ángel 2b65b4efce fix(studio): harden composition timeline reliability (#2615)
* fix(studio): preserve composition playback continuity

* feat(studio): drag compositions into the timeline

* fix(studio): collapse expanded composition move aliases

* fix(studio): make timeline cuts atomic

* fix(studio): group inspector gesture history

* test(studio): cover masked text selection

* fix(studio): harden composition timeline reliability

* fix(studio): satisfy CI source gates

* fix(studio): harden composition mutation requests
2026-07-17 14:15:30 -04:00
Vance Ingalls c268f5ba85 chore: release v0.7.61 2026-07-17 01:07:09 -07:00
Vance Ingalls 53b3621437 fix(studio): short-circuit slideshow-island detection with a substring check (review N2)
slideshowIslandRegex scanned the full file content on every editingFile
change even for the common non-slideshow case. Gate it behind a plain
substring check on SLIDESHOW_ISLAND_TYPE first — cheap, and avoids the
full-content RegExp pass for files that plainly have no island.

Added a test for the still-open behavior this preserves: a malformed
island (invalid JSON) still trips the substring check and the regex,
so the tab stays discoverable rather than silently disappearing.
2026-07-17 00:37:39 -07:00
Vance Ingalls a4167ede07 feat(studio): default the flat inspector on
Flip STUDIO_FLAT_INSPECTOR_ENABLED's default from false to true — the
bug-fix pass on the flat inspector is complete (right-aligned values,
Stroke width/style split, promote-badge overlap, Layout/Style section
gating for non-visual elements like audio). VITE_STUDIO_FLAT_INSPECTOR_ENABLED=false
still opts back into the legacy panel.

Updates the two tests that asserted the old false default: the flag's
own default test, and the "classic PropertyPanel input coverage" suite,
which relied on that default to reach the legacy panel and now mocks it
explicitly (mirroring the adjacent "flat" suite's existing pattern).
2026-07-17 00:37:39 -07:00
Vance Ingalls 67696cd8de fix(studio): hide the Slideshow tab and panel for non-slideshow compositions
The Slideshow tab rendered unconditionally, showing the branching editor
for any composition regardless of whether it was actually a slideshow —
a plain video comp offered a tab with nothing meaningful to edit.

Gate it on the composition carrying the slideshow JSON island
(<script type="application/hyperframes-slideshow+json">), the same
definitive marker the CLI's `present` command already requires (it
refuses to run without one). Presence-only, not full manifest
validation, so a malformed island still surfaces the tab rather than
disappearing entirely. Also bounce rightPanelTab off "slideshow" to
"renders" if the active composition stops being a slideshow while that
tab is open (e.g. switching files), since its button would otherwise
vanish with no way back to it.

Extracted the gating + scene-list derivation into useSlideshowTabState
to keep StudioRightPanel.tsx under the 600-LOC gate.
2026-07-17 00:37:39 -07:00
Miguel Ángel 6458807066 feat(cli): let projects opt out of automatic proxying (#2591)
* feat(studio-server): serve H.264 proxies from the preview route

Wires the codec manifest and the transcoder into the preview surface: the route
negotiates a proxy via a query param and serves it through the existing range
and ETag machinery, composition HTML carries a codec map for the runtime, and
hostile assets pre-warm so a first play does not wait on a cold transcode.
Exposes the three subpath exports the CLI surfaces consume upstack.

Drops the TEMP fallow entry added with the transcoder: it has real importers now.

* fix(studio-server): publish media proxy exports

* fix(parsers): scan HTML comments linearly

* feat(cli): let projects opt out of automatic proxying

Adds media.autoProxy to hyperframes.json plus --proxy/--no-proxy flags, and
forwards the resolved value into the studio and preview servers and the vite
adapter. Lands before the runtime slice that turns auto-proxying on, so the
switch exists before there is any behavior to switch off.

* fix(cli): align media config schema
2026-07-16 23:01:14 -04:00
James 68beec0e76 fix(studio): guard storyboard history navigation 2026-07-16 15:49:40 -04:00
James ded443647d fix(studio): address storyboard review feedback 2026-07-16 14:56:11 -04:00
James 73dd38f93e feat(studio): clarify storyboard review handoff 2026-07-16 14:56:11 -04:00
Vance Ingalls 8a793ba2b2 fix(studio): gate Layout and Style panel sections on the element having a rendered box
Both panels showed Layout (X/Y/W/H/Rotation/Z-index) unconditionally —
no gate existed for it at all — and Style was gated only on
canEditStyles (a permission check), never on the element's tag. Neither
gate accounted for `<audio>`, which never paints a visual frame, so a
music track's inspector showed a full set of position/size/fill/shadow
controls with zero visual effect.

Add `layout`/`style` applicability to resolveEditingSections (core),
keyed on tag !== "audio", and gate both panels' Layout section and the
existing Style gate on it. Media/Motion/Grade/Text were already
correctly gated (verified via a research pass across both panels) and
are untouched.
2026-07-16 01:47:46 -07:00