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:
@@ -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 = '';
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user