Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,16 @@ export class Track {
private _playHtml5(): void {
if (this.audio.preload !== 'auto') this.audio.preload = 'auto';
this.audio.playbackRate = this.queueRef.playbackRate;
if (isFinite(this.pausedAtTrackTime) && this.pausedAtTrackTime > this.audio.currentTime + 0.5) {
if (this.audio.readyState >= HTMLMediaElement.HAVE_METADATA) {
this.audio.currentTime = this.pausedAtTrackTime;
} else {
const target = this.pausedAtTrackTime;
this.audio.addEventListener('loadedmetadata', () => {
this.audio.currentTime = target;
}, { once: true });
}
}
const promise = this.audio.play();
if (promise) {
promise.catch((err: unknown) => {
Expand Down
18 changes: 18 additions & 0 deletions src/machines/track.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,15 @@ export function createTrackMachine(initialContext: TrackContext) {
// -----------------------------------------------------------------
idle: {
on: {
SEEK: [
{
guard: 'isWebAudioOnly',
actions: ['reportProgress'],
Comment on lines +182 to +183

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Report the Web Audio seek anchor instead of HTML time

In WEBAUDIO_ONLY mode while the track is idle, this branch intentionally skips seekHtml5, but reportProgress calls toInfo(), whose currentTime getter returns audio.currentTime outside the webaudio state rather than the newly assigned pausedAtTrackTime. A seek before decoding therefore emits the old position—typically zero—to progress consumers and media-session state even though playback will eventually use the requested anchor. Report the requested anchor directly or make idle/loading Web Audio-only tracks expose it through currentTime.

Useful? React with 👍 / 👎.

},
{
actions: ['seekHtml5', 'reportProgress'],
Comment on lines +185 to +186

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve the requested start time across activation

When gotoTrack(index, true, startTime) selects a destination with decoded audio or loaded HTML metadata, the queue runs seekCurrentToStartTime before activateAndPlayCurrent; track.activate() then sends ACTIVATE, whose idle/loading actions reset both pausedAtTrackTime and audio.currentTime. This erases the seek performed here before play() reads it, so preloaded Web Audio tracks and metadata-ready HTML tracks start at zero instead of startTime. Activate before seeking, or preserve the requested anchor during this activation.

Useful? React with 👍 / 👎.

},
],
HTML5_ENDED: {
actions: ['notifyTrackEnded'],
},
Expand Down Expand Up @@ -340,6 +349,15 @@ export function createTrackMachine(initialContext: TrackContext) {
// -----------------------------------------------------------------
loading: {
on: {
SEEK: [
{
guard: 'isWebAudioOnly',
actions: ['reportProgress'],
},
{
actions: ['seekHtml5', 'reportProgress'],
Comment on lines +357 to +358

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Invalidate deferred seeks when the track is reset

If this loading-state seek occurs before metadata is available, _seekHtml5() installs a one-shot loadedmetadata listener capturing the requested offset. Navigating away before loading completes resets the track's timing but does not remove that listener, so it can later restore the abandoned offset into audio.currentTime; because _playHtml5() only corrects when the anchor is ahead of the element, a subsequent HTML5 play can then begin at this stale position. Cancel or generation-check deferred seeks when deactivating/resetting the track.

Useful? React with 👍 / 👎.

},
],
BUFFER_LOADING: {
actions: 'setLoadingState',
},
Expand Down
Loading