fix(audio): guard underrun/stream-complete against false end-of-playback
pause() clears underrun_ so setStreamComplete can't fire TrackEnded while paused; resetToStart() resets streamComplete. Prior fix: underrun_ park + streamComplete discriminator prevent the Opus-startup false-end. Tests: 18 PlaybackScheduler cases including pause-during-underrun and underrun->resume->genuine-end-once.
This commit is contained in:
@@ -237,6 +237,12 @@ export class AudioPlayer {
|
||||
}
|
||||
}
|
||||
this.streamingCompleted = true;
|
||||
// Hand the genuine-end signal to the scheduler AFTER the tail buffers are added and
|
||||
// scheduled: now an empty scheduled queue is a real end-of-track, not a startup gap, so
|
||||
// the scheduler may fire onPlaybackEnded when its queue drains. If the queue was already
|
||||
// empty at this point (the tail produced no buffers, or they were already played),
|
||||
// setStreamComplete finalises immediately.
|
||||
this.scheduler.setStreamComplete(true);
|
||||
return { success: true, bufferCount: this.scheduler.getBufferCount() };
|
||||
} catch (error) {
|
||||
return { success: false, error: (error as Error).message };
|
||||
@@ -321,9 +327,13 @@ export class AudioPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if streaming is complete
|
||||
// Check if streaming is complete. The StreamDecoder self-detects completion by byte
|
||||
// count (WAV/MP3/FLAC); propagate that to the scheduler so a drained queue past this
|
||||
// point is treated as a genuine end. Buffers from this chunk were already added above,
|
||||
// so any final end fires through handleSourceEnded when they drain.
|
||||
if (this.streamDecoder.isComplete) {
|
||||
this.streamingCompleted = true;
|
||||
this.scheduler.setStreamComplete(true);
|
||||
}
|
||||
|
||||
const canStart = this.streamDecoder.headerParsed &&
|
||||
|
||||
Reference in New Issue
Block a user