fix(music): add wav chunk diagnostics and larger chunks

Increase live WAV chunk size to one second and log chunk acceptance, queue depth, and retry state on stations so the HQ speaker path can be diagnosed from runtime logs.
This commit is contained in:
2026-07-31 22:46:47 +08:00
parent f7755953b4
commit 87e45de15b
2 changed files with 29 additions and 2 deletions
+2 -2
View File
@@ -324,7 +324,7 @@ async function sendLiveWavChunksToStation(stationName, fallbackWs, task) {
const sampleRate = 48000;
const channels = 1;
const bitsPerSample = 16;
const chunkDurationSec = 0.25;
const chunkDurationSec = 1.0;
const chunkBytes = Math.max(4096, Math.floor(sampleRate * channels * (bitsPerSample / 8) * chunkDurationSec));
targetWs.send(JSON.stringify({
@@ -344,7 +344,7 @@ async function sendLiveWavChunksToStation(stationName, fallbackWs, task) {
const ffmpegArgs = ['-hide_banner', '-loglevel', 'error'];
if (loop) ffmpegArgs.push('-stream_loop', '-1');
ffmpegArgs.push('-re', '-i', sourcePath, '-f', 's16le', '-acodec', 'pcm_s16le', '-ac', String(channels), '-ar', String(sampleRate), 'pipe:1');
log('INFO', `Live WAV chunk stream start for ${stationName}: ${path.basename(sourcePath)}${loop ? ' (loop)' : ''}`);
log('INFO', `Live WAV chunk stream start for ${stationName}: ${path.basename(sourcePath)}${loop ? ' (loop)' : ''} chunk=${chunkDurationSec}s`);
return await new Promise((resolve, reject) => {
let stderr = '';
+27
View File
@@ -799,15 +799,29 @@ end
local function pushWavChunkToSpeakers(payload, playSeq)
local controller = Peripherals.speakers and Peripherals.speakers[1] or nil
if controller and type(controller.speakWavAll) == "function" then
local retryCount = 0
while true do
if shouldStop(playSeq) then return false end
local ok = false
local queueSize = -1
local isPlaying = false
pcall(function()
ok = controller.speakWavAll(payload, CONFIG.AUDIO_VOLUME)
if type(controller.speakQueueSize) == "function" then
queueSize = tonumber(controller.speakQueueSize()) or -1
end
if type(controller.speakIsPlaying) == "function" then
isPlaying = controller.speakIsPlaying() and true or false
end
end)
if ok then
Utils.log("INFO", string.format("WAV chunk accepted: bytes=%d queue=%d playing=%s", #payload, queueSize, tostring(isPlaying)))
return true
end
retryCount = retryCount + 1
if retryCount == 1 or retryCount % 20 == 0 then
Utils.log("WARN", string.format("WAV chunk waiting: bytes=%d queue=%d playing=%s retries=%d", #payload, queueSize, tostring(isPlaying), retryCount))
end
if not waitForInterruptibleDelay(playSeq, 0.05) then
return false
end
@@ -820,6 +834,7 @@ local function pushWavChunkToSpeakers(payload, playSeq)
if name then pending[name] = sp end
end
local retryCount = 0
while next(pending) do
if shouldStop(playSeq) then return false end
for name, sp in pairs(pending) do
@@ -831,6 +846,18 @@ local function pushWavChunkToSpeakers(payload, playSeq)
end)
if ok then pending[name] = nil end
end
if next(pending) then
retryCount = retryCount + 1
if retryCount == 1 or retryCount % 20 == 0 then
local pendingCount = 0
for _ in pairs(pending) do
pendingCount = pendingCount + 1
end
Utils.log("WARN", string.format("WAV chunk waiting on %d speakers: bytes=%d retries=%d", pendingCount, #payload, retryCount))
end
else
Utils.log("INFO", string.format("WAV chunk accepted by fallback speakers: bytes=%d", #payload))
end
if next(pending) and not waitForInterruptibleDelay(playSeq, 0.05) then
return false
end