From c562fe05b004e0466d459bd47696a0b2ff7c3d21 Mon Sep 17 00:00:00 2001 From: saopig1 <4x7sw862st@gmail.com> Date: Thu, 7 May 2026 21:04:27 +0800 Subject: [PATCH] fix(player): start frame loop only after ffmpeg spawns in jdymusic path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #54's playViaPowerShellDownload called startFrameLoop() right after spawning the PowerShell downloader, before ffmpeg existed. The loop's "no ffmpeg + empty buffer → emit trackEnd" branch fired on the very first tick (~25ms), skipping every jdymusic song. Visible as: each PowerShell download sessionId logged "Track ended, advancing queue" before the download completed, so the queue burned through every track in a few seconds. Move startFrameLoop() into spawnFfmpegFromFile() where ffmpeg is known to be alive and producing PCM. state = "playing" still flips in playViaPowerShellDownload so external observers see the right status during download. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/audio/player.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/audio/player.ts b/src/audio/player.ts index 5b1e6e0..4485a11 100644 --- a/src/audio/player.ts +++ b/src/audio/player.ts @@ -279,8 +279,12 @@ export class AudioPlayer extends EventEmitter { this.emit("error", err); }); + // Mark playing but DO NOT start the frame loop here — the loop's + // "no ffmpeg + empty buffer → trackEnd" branch would fire on the very + // first tick, before the PowerShell download even completes. The + // frame loop is started inside spawnFfmpegFromFile() once ffmpeg is + // alive and producing PCM. this.state = "playing"; - this.startFrameLoop(); } private spawnFfmpegFromFile(tempFile: string, seekSeconds: number, sessionId: number): void { @@ -329,6 +333,9 @@ export class AudioPlayer extends EventEmitter { this.emit("error", err); } }); + + // Now that ffmpeg is producing PCM, run the frame loop. + this.startFrameLoop(); } stop(): void {