Skip to content

Commit 80708ab

Browse files
committed
fix(core): a looping bed with no length leads the playhead over shorter clips
A looping clip without data-duration plays for its whole window, so it ranks by the window's end, not one pass of its file.
1 parent ff4ae94 commit 80708ab

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

‎packages/core/src/runtime/audioClockSource.test.ts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,30 @@ describe("the audio the playhead follows", () => {
261261
expect(window.__player!.getTime()).toBeGreaterThan((nowMs - playedAt) / 1000 + 0.1);
262262
});
263263

264+
it("follows a looping bed with no length over a longer clip that starts late", async () => {
265+
mount(
266+
`<audio id="shot" data-start="0" data-duration="3" src="/assets/shot.mp4"></audio>` +
267+
`<audio id="bed" data-start="0" loop src="/assets/bed.wav"></audio>`,
268+
);
269+
const shot = document.getElementById("shot") as HTMLAudioElement;
270+
const bed = document.getElementById("bed") as HTMLAudioElement;
271+
Object.defineProperty(bed, "duration", { value: 2, configurable: true });
272+
initSandboxRuntimeModular();
273+
await flush();
274+
window.__player?.play();
275+
await flush();
276+
const playedAt = nowMs;
277+
Object.assign(shot, { paused: false });
278+
Object.assign(bed, { paused: false });
279+
for (let frame = 1; frame <= 100; frame++) {
280+
const t = (nowMs + 1000 / 60 - playedAt) / 1000;
281+
bed.currentTime = t;
282+
shot.currentTime = Math.max(0, t - 0.25);
283+
stepFrames(1);
284+
expect(window.__player!.getTime()).toBeCloseTo(t, 3);
285+
}
286+
});
287+
264288
it("follows the next clip when one earlier in the page failed to load", async () => {
265289
mount(
266290
`<audio id="broken" data-start="0" data-duration="10" src="/assets/missing.mp3"></audio>` +

‎packages/core/src/runtime/init.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4548,7 +4548,9 @@ export function initSandboxRuntimeModular(): void {
45484548
const end = durAttr != null && durAttr > 0 ? start + durAttr : Infinity;
45494549
if (!Number.isFinite(start) || !isInClipWindow(state.currentTime, start, end)) continue;
45504550
if (el === followed) return { el, start };
4551-
const runsUntil = start + (resolveMediaElementDurationSeconds(el) ?? Infinity);
4551+
const runsUntil = el.loop
4552+
? end
4553+
: start + (resolveMediaElementDurationSeconds(el) ?? Infinity);
45524554
if (!longest || runsUntil > longest.runsUntil) longest = { el, start, runsUntil };
45534555
}
45544556
return longest;

0 commit comments

Comments
 (0)