feat(studio,cli): music beat detection with timeline guides + headless beats CLI#1424
Open
vanceingalls wants to merge 3 commits into
Open
feat(studio,cli): music beat detection with timeline guides + headless beats CLI#1424vanceingalls wants to merge 3 commits into
vanceingalls wants to merge 3 commits into
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
| // blob:/data: URLs have no stable identity across sessions — not persistable. | ||
| if (/^(blob:|data:)/i.test(src)) return null; | ||
| // Studio preview URLs: /api/projects/<id>/preview[/comp]/<relpath> | ||
| const previewMatch = src.match(/\/preview\/(?:comp\/)?(.+?)(?:[?#].*)?$/); |
4711e7b to
f355498
Compare
Collaborator
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
…s beats CLI Beat detection for music tracks: the Studio draws beat guides on the active track, beats are user-editable and persist to a project file, and a new `hyperframes beats` CLI generates that file headlessly before the Studio opens. Detection lives in @hyperframes/core/beats (shared by Studio + CLI): an energy onset detector cross-validated with bpm-detective, regularized to an octave- aligned grid, silence-gated, with per-beat loudness. Music-only — an <audio data-timeline-role="music"> is analyzed; voiceover is excluded. Studio: green beat lines + draggable dots on the selected track; add at playhead, drag to move, double-click to delete (audio scrubs); edits persist to beats/<audio>.json and are undoable (interleaved with file history). CLI: `hyperframes beats [dir]` runs the same detection in headless Chrome (prebuilt browser bundle in dist) and writes the beat file. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Miguel Ángel <miguel07alm@protonmail.com>
f355498 to
bea30d4
Compare
- Center-anchored magnify: zooming via the toolbar/slider keeps the time at the viewport center fixed instead of anchoring at the left. Pinch still anchors at the cursor. - Move-snap to beats: dragging a clip snaps whichever edge (start or end) is nearest a beat, matching the existing resize-edge snapping. - Beat lines on track backgrounds: faint full-height beat lines now paint behind the clips on every track lane (brightness scales with loudness); the green dots stay on the active track's top bar. - Waveform follows zoom: bars fill the full clip width and resample the windowed peaks, so the waveform stretches with zoom instead of stopping partway across a widened clip. - Beat dots centered in the top bar: align the dot band to the clip top (CLIP_Y) so the dots sit centered in the dark bar instead of being bisected by the clip's top border. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Miguel Ángel <miguel07alm@protonmail.com>
Moving a non-music clip re-derived the timeline elements into fresh objects whose sourceDuration the DOM scan hadn't loaded yet. The async probe skips srcs already in its cache, so the value was silently dropped — trimFractions then returned no window and the trimmed music waveform reset to the full source pinned at the track start. Re-apply the cached probe duration synchronously on every derivation (applyCachedSourceDurations) and extract the async probe loop into probeMissingSourceDurations to keep useTimelinePlayer within the file size limit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Miguel Ángel <miguel07alm@protonmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Adds music beat detection to HyperFrames. The Studio draws beat guides on the timeline; beats are user-editable and persist to a per-audio project file; and a new
hyperframes beatsCLI generates that file headlessly so guides are ready before the Studio is ever opened.Beat detection is music-only: an
<audio data-timeline-role="music">(or an id likemusic/bgm/soundtrack) is analyzed; voiceover and other audio are excluded by the sharedisMusicTrackrule.What's included
Detection —
@hyperframes/core/beats(shared by Studio + CLI)bpm-detectiveis loaded lazily (it toucheswindowat module top-level) so the module is safe to import in Node/SSR/tests.Studio
beats/<audio>.jsonin audio-file coordinates, so they survive trimming/moving the music clip and are matched back to the same audio if it's removed and re-added.minDurationand source/composition limits).CLI —
hyperframes beats [dir]distat CLI build time (build:beat-analyzer), so it works for published users without shipping source; a dev fallback bundles from core source.browser ensurewhen Chrome is missing.Beat file format
{ "version": 1, "audio": "music.wav", "beats": [{ "time": 1.23, "strength": 0.8 }] }Notes
examples/is gitignored, so the demo composition/audio used during development isn't part of this PR.Testing
core(1466),studio(798),clitypecheck/lint all green; pre-commit hooks (lint, format, fallow complexity gate, filesize, typecheck) pass.hyperframes beatson a demo composition analyzes the music track only (voiceover excluded) and writes a file the Studio reloads with edits intact.🤖 Generated with Claude Code
Timeline UX refinements (follow-up)
Center-anchored magnify — zooming the timeline via the toolbar/slider keeps the time at the viewport center fixed instead of anchoring at the left edge; pinch-to-zoom still anchors at the cursor.
Move-snap to beats — dragging a clip snaps whichever edge (start or end) is nearest a beat, matching the existing resize-edge snapping.
Beat lines on track backgrounds — faint full-height beat lines now paint behind the clips on every track lane (brightness scales with loudness); the green dots stay on the active track's top bar.
Waveform follows zoom — waveform bars fill the full clip width and resample the windowed peaks, so the waveform stretches with zoom instead of stopping partway across a widened clip.
Dots centered in the top bar — the dot band aligns to the clip top so the dots sit vertically centered in the dark top bar instead of being bisected by the clip's selection border.
Trim survives moving other clips — re-applies the cached probe
sourceDurationon every element re-derivation, so moving a non-music clip no longer drops the music clip's source length (which made the trimmed waveform reset to the full source pinned at the track start).