Repository navigation
Conversation
The track machine's idle and loading states had no SEEK handler, so when seekCurrentToStartTime fired during gotoTrack, the SEEK event was silently dropped — pausedAtTrackTime was set correctly but audio.currentTime stayed at 0, causing playback to start from the beginning instead of the target. - Add SEEK → seekHtml5 handler to idle and loading states so the HTML5 element actually seeks during the GOTO phase before PLAY fires. - Defense-in-depth: _playHtml5() now checks if audio.currentTime diverges from pausedAtTrackTime by >0.5s and seeks before calling play(), handling both metadata-ready and not-yet-loaded cases. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deploying gapless with
|
| Latest commit: |
49be3df
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://d4244077.gapless-e1l.pages.dev |
| Branch Preview URL: | https://fix-seek-in-idle-loading.gapless-e1l.pages.dev |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 335bc39b5b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (isFinite(this.pausedAtTrackTime) && Math.abs(this.audio.currentTime - this.pausedAtTrackTime) > 0.5) { | ||
| if (this.audio.readyState >= HTMLMediaElement.HAVE_METADATA) { | ||
| this.audio.currentTime = this.pausedAtTrackTime; |
There was a problem hiding this comment.
Avoid restoring a stale anchor when resuming HTML5 playback
When HTML5 playback is paused normally, pausedAtTrackTime is not updated—the HTML5 PAUSE transition only pauses the element—so it commonly remains 0 or the position of an earlier seek. Resuming after the element has advanced by more than 0.5 seconds now assigns that stale value to audio.currentTime, causing HTML5-only playback, or hybrid playback while decoding is still pending, to jump backward instead of resuming from the paused position.
Useful? React with 👍 / 👎.
Matches the html5 and webaudio states so UI consumers get notified of the new seek position immediately. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pausedAtTrackTime is not updated on HTML5 pause, so the previous Math.abs check would seek backward on normal resume (e.g. pausedAt=0 after 30s of playback). Changed to only trigger when pausedAtTrackTime is ahead of audio.currentTime — the actual GOTO scenario where the SEEK event was dropped. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6dc74d3303
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| idle: { | ||
| on: { | ||
| SEEK: { | ||
| actions: ['seekHtml5', 'reportProgress'], |
There was a problem hiding this comment.
Keep idle seeks off the HTML5 path in WebAudio-only mode
When playbackMethod is WEBAUDIO_ONLY and a seek arrives before decoding completes—for example, gotoTrack(..., startTime) while the track is idle—this new handler invokes _seekHtml5(). Without loaded metadata, that method sets preload = 'auto' and calls audio.load(), initiating an unnecessary HTML5 media request and potentially reporting an HTML5 onerror even if the Web Audio fetch succeeds, despite this mode promising Web Audio exclusively. Gate this action by playback method or use an anchor-only seek for WebAudio-only tracks.
Useful? React with 👍 / 👎.
In WEBAUDIO_ONLY mode, calling seekHtml5 triggers audio.load() which initiates an unnecessary HTML5 request and can fire spurious onerror. pausedAtTrackTime is already set by seek(), and startSourceNode reads it on PLAY, so the HTML5 element doesn't need to be touched. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 49be3df008
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| { | ||
| actions: ['seekHtml5', 'reportProgress'], |
There was a problem hiding this comment.
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 👍 / 👎.
| { | ||
| actions: ['seekHtml5', 'reportProgress'], |
There was a problem hiding this comment.
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 👍 / 👎.
| guard: 'isWebAudioOnly', | ||
| actions: ['reportProgress'], |
There was a problem hiding this comment.
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 👍 / 👎.
|
Closing in favor of a broader refactor: moving pausedAtTrackTime into machine context as seekTarget to eliminate the dual-authority problem. |
Summary
idleandloadingstates had noSEEKhandler, so whenseekCurrentToStartTimefires duringgotoTrack, the SEEK event was silently dropped —pausedAtTrackTimewas set correctly butaudio.currentTimestayed at 0.SEEK → seekHtml5handler toidleandloadingstates so the HTML5 element actually seeks during the GOTO phase before PLAY fires._playHtml5()— ifaudio.currentTimediverges frompausedAtTrackTimeby >0.5s, seek the element before callingplay().Test plan
gotoTrack(n, { startTime: 142.6 })starts playback at 142.6s, not 0🤖 Generated with Claude Code