Skip to content

fix(lint): back-to-back audio clips no longer count as overlapping after float rounding - #5837

Merged
miguel-heygen merged 1 commit into
mainfrom
scrubfix/audiotouch
Oct 18, 2026
Merged

miguel-heygen merged 1 commit into
mainfrom
scrubfix/audiotouch

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

What

lint and check no longer warn duplicate_audio_track for audio clips placed end to end on one track when the first clip's start plus duration only lands past the next start because of float rounding. For example, a clip at data-start="21.03" data-duration="0.1" followed by one at data-start="21.13" used to be reported as layered audio ("a.mp3 at 21.03-21.1s, a.mp3 at 21.13-26.1s"), because 21.03 + 0.1 is 21.130000000000003.

Why

The rule compared raw float ends: a.start < b.end && b.start < a.end. Any end that rounds a step past the next start counts as overlap. In the reported pattern (music cut at 21.03 s and laid back to back), 712 of the 3,000 two-decimal durations from 0.01 to 30 s produce such an end. The warning then sends authors and agents to "fix" a timeline that plays correctly, and trains them to ignore the real overlap warning.

Reproduced on 0.8.170: a project with 0-21.03, 21.03-21.13 and 21.13-26.13 on track 9 gets the warning.

Related work

None found (searched open PRs and issues for duplicate_audio_track and audio overlap).

How

  • Core already owns "one instant" comparisons for clip times: instantTolerance, sameInstant and the span helpers in clipFacts.ts, used by the runtime and the timeline commands. Lint cannot import core (core depends on lint), so those helpers move unchanged to a new @hyperframes/parsers/time-spans subpath. Both packages already depend on parsers, and the runtime already imports parsers subpaths.
  • clipFacts.ts re-exports them, so every existing import keeps working.
  • The rule uses spansOverlap, so ends within one instant of the next start do not overlap, and a real overlap still warns.
  • The subpath is registered in package-subpaths.json and synced to package.json with bun run sync:package-subpaths; tsup builds it.

Test plan

  • Unit tests added/updated: project.test.ts "stays quiet for back-to-back clips whose start plus duration only rounds past the next start" fails on main (the warning is reported) and passes here, 3 runs in a row (61 passed). The existing "warns when audible videos overlap on one track" still passes.
  • Manual testing performed: the CLI from this branch runs lint on the reproducing project with no duplicate_audio_track (3 warnings, down from 4). Moving the third clip to start at 21.10 (0.03 s of real overlap) still warns.
  • Also run: core src/runtime and clipFacts (2121 passed), the runtime CI suite (test:hyperframe-runtime-ci), CLI src/timeline (113 passed), tsc for parsers, lint, core and cli, check:package-cycles and check:package-subpaths.
  • Documentation updated (if applicable): not applicable.
  • Comments follow CONTRIBUTING.md "Comments": the moved helpers keep their comments; the test says why its numbers matter.

…ter float rounding

duplicate_audio_track compared raw float ends, so 21.03 + 0.1 (21.130000000000003)
overlapped a clip starting at 21.13. The one-instant span helpers move from core's
clipFacts to parsers, which lint and core both depend on; core re-exports them and
the rule uses spansOverlap.
@github-actions

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 174 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (1)

  • textedit-none-px-r0-nested-z100: tracking 0, pressJump -, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0, pressJump -, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0, pressJump -, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@somanshreddy somanshreddy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean at 47c1a19b: no blocker.

  • The helpers move into @hyperframes/parsers/time-spans unchanged, and clipFacts.ts re-exports them, so existing imports keep working. The subpath is registered in package-subpaths.json, in both package.json export maps and in the tsup entry.
  • I brute-forced the rule outside the repo with the same spansOverlap. That covered about 2.5M back-to-back pairs at 2- and 3-decimal starts and durations, each parsed the way the attributes are, with starts up to 3600 s and durations up to 60 s:
    • The old a.start < b.end && b.start < a.end check gives 314,892 false duplicate_audio_track warnings.
    • The new check gives 0.
    • A real overlap of one unit (0.01 s or 0.001 s) still warns in every case: 0 misses.
  • Zero-length clips behave as before. One inside another still overlaps; one at the other's start still doesn't.

— Somu

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 18, 2026
Merged via the queue into main with commit d112329 Oct 18, 2026
79 checks passed
@miguel-heygen
miguel-heygen deleted the scrubfix/audiotouch branch October 18, 2026 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants