From b140aafa2dc4ff4bae6746177978a3f0635a82b3 Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Sat, 1 Aug 2026 11:11:22 +0800 Subject: [PATCH] fix(audio): prebuffer live wav stream startup Buffer a couple of live wav chunks before beginning playback so startup jitter is reduced when the stream first begins feeding speakers. --- station_broadcast.lua | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/station_broadcast.lua b/station_broadcast.lua index e514619..13a78ef 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -2,7 +2,7 @@ -- ============================================================================ -- 1. Configuration & Constants -- ============================================================================ -local APP_VERSION_TEXT = "v1.0.13" +local APP_VERSION_TEXT = "v1.0.14" local CONFIG = { CLOUD_URL = "ws://stabadmin.fse-media.group", @@ -14,6 +14,7 @@ local CONFIG = { DISK_AUDIO_STATION = "disk/Audio/Station/", STATION_IDENTITY_FILE = "station_identity.cfg", AUDIO_VOLUME = 3, + AUDIO_STREAM_PREROLL_CHUNKS = 2, DEBUG = true } @@ -739,6 +740,14 @@ function Audio.createStream() end return table.remove(chunks, 1) end + + stream.count = function() + return #chunks + end + + stream.isFinished = function() + return finished + end return stream end @@ -1393,8 +1402,10 @@ function Audio.playWavStreamItem(item) local playSeq = State.interruptSeq local source = item.audioData + local streamObj = nil if type(source) == "table" and source.read then + streamObj = source source = source.read end @@ -1407,6 +1418,22 @@ function Audio.playWavStreamItem(item) end end + local prebufferChunks = math.max(0, tonumber(CONFIG.AUDIO_STREAM_PREROLL_CHUNKS) or 0) + if streamObj and prebufferChunks > 0 then + Utils.log("INFO", "Prebuffering live WAV stream: target chunks=" .. tostring(prebufferChunks)) + while streamObj.count() < prebufferChunks and not streamObj.isFinished() do + if shouldStop(playSeq) then + Audio.stop("current") + return + end + if not waitForInterruptibleDelay(playSeq, 0.02) then + Audio.stop("current") + return + end + end + Utils.log("INFO", "Live WAV prebuffer ready: chunks=" .. tostring(streamObj.count())) + end + while true do if shouldStop(playSeq) then Audio.stop("current")