From ac8405e3003387e5c1cff176c066b4a1403a627d Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Sun, 2 Aug 2026 08:53:49 +0800 Subject: [PATCH] fix: use pcall to uncapped AUDIO_VOLUME for HQ speakers while keeping 3.0 fallback for vanilla speakers --- CloudServer/server.js | 11 +++++------ station_broadcast.lua | 33 ++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/CloudServer/server.js b/CloudServer/server.js index 29cd241..c90feed 100644 --- a/CloudServer/server.js +++ b/CloudServer/server.js @@ -1289,7 +1289,7 @@ function buildSequenceWavFile(seq) { const inputs = files.map(f => `-i "${f}"`).join(' '); const filterResamples = files.map((_, i) => `[${i}:a]aformat=sample_rates=48000:channel_layouts=mono,aresample=48000[a${i}]`).join(';'); - const filterConcat = files.map((_, i) => `[a${i}]`).join('') + `concat=n=${files.length}:v=0:a=1,volume=5.0[a]`; + const filterConcat = files.map((_, i) => `[a${i}]`).join('') + `concat=n=${files.length}:v=0:a=1[a]`; const filterComplex = `${filterResamples};${filterConcat}`; try { @@ -1330,7 +1330,7 @@ function runFfmpegRtmpPush(streamName, seq) { const tmpAacPath = path.join(tmpDir, `prebuild-${Date.now()}-${Math.random().toString(16).slice(2)}.aac`); const inputs = files.map(f => `-i "${f}"`).join(' '); const filterResamples = files.map((_, i) => `[${i}:a]aformat=sample_rates=48000:channel_layouts=mono,aresample=48000[a${i}]`).join(';'); - const filterConcat = files.map((_, i) => `[a${i}]`).join('') + `concat=n=${files.length}:v=0:a=1,volume=5.0[a]`; + const filterConcat = files.map((_, i) => `[a${i}]`).join('') + `concat=n=${files.length}:v=0:a=1[a]`; const filterComplex = `${filterResamples};${filterConcat}`; const buildArgs = [ @@ -1425,7 +1425,7 @@ function runFfmpegRtmpPush(streamName, seq) { } const filterResamples = files.map((_, i) => `[${i}:a]aformat=sample_rates=48000:channel_layouts=mono,aresample=48000[a${i}]`).join(';'); - const filterConcat = files.map((_, i) => `[a${i}]`).join('') + `concat=n=${files.length}:v=0:a=1,volume=5.0[a]`; + const filterConcat = files.map((_, i) => `[a${i}]`).join('') + `concat=n=${files.length}:v=0:a=1[a]`; const filterComplex = `${filterResamples};${filterConcat}`; const args = [ @@ -2086,8 +2086,7 @@ function convertToDfpwm(filePath) { // -f s8: signed 8-bit pcm // -ac 1: mono // -ar 48000: 48kHz - // -filter:a volume=5.0: boost volume significantly - execSync(`ffmpeg -y -v quiet -i "${filePath}" -filter:a volume=5.0 -f s8 -acodec pcm_s8 -ac 1 -ar 48000 "${rawPath}"`); + execSync(`ffmpeg -y -v quiet -i "${filePath}" -f s8 -acodec pcm_s8 -ac 1 -ar 48000 "${rawPath}"`); if (fs.existsSync(rawPath)) { const buffer = fs.readFileSync(rawPath); @@ -2715,7 +2714,7 @@ function buildTempBroadcastFromWav(prefixWavPath, contentWavPath) { const filterComplex = [ '[0:a]aformat=sample_rates=48000:channel_layouts=mono,aresample=48000[a0]', '[1:a]aformat=sample_rates=48000:channel_layouts=mono,aresample=48000[a1]', - '[a0][a1]concat=n=2:v=0:a=1,volume=5.0[a]' + '[a0][a1]concat=n=2:v=0:a=1[a]' ].join(';'); execSync(`ffmpeg -hide_banner -loglevel error -y -i "${prefixWavPath}" -i "${contentWavPath}" -filter_complex "${filterComplex}" -map "[a]" -ac 1 -ar 48000 -c:a pcm_s16le "${outWavPath}"`); diff --git a/station_broadcast.lua b/station_broadcast.lua index 4d3559d..61e608a 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -1127,10 +1127,15 @@ local function queueSamplesSynchronized(samples, volume, playSeq) if shouldStop(playSeq) then return false end for name, sp in pairs(pending) do local ok = false - pcall(function() - local safeVolume = math.min(volume or 3, 3.0) - ok = sp.playAudio(samples, safeVolume) + local success, err = pcall(function() + ok = sp.playAudio(samples, volume) end) + if not success then + -- Fallback for vanilla speakers which throw an error if volume > 3.0 + pcall(function() + ok = sp.playAudio(samples, 3.0) + end) + end if ok then pending[name] = nil end @@ -1161,12 +1166,18 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain) if shouldStop(playSeq) then return false end for name, sp in pairs(pending) do local ok = false - pcall(function() + local success, err = pcall(function() if type(sp.playAudio) == "function" then - local safeVolume = math.min(volume or 3, 3.0) - ok = sp.playAudio(samples, safeVolume) + ok = sp.playAudio(samples, volume) end end) + if not success then + pcall(function() + if type(sp.playAudio) == "function" then + ok = sp.playAudio(samples, 3.0) + end + end) + end if ok then usedNativePath = true pending[name] = nil @@ -1189,10 +1200,14 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain) while true do if shouldStop(playSeq) then return false end local ok = false - pcall(function() - local safeVolume = math.min(volume or 3, 3.0) - ok = controller.playAudioAll(samples, safeVolume) + local success, err = pcall(function() + ok = controller.playAudioAll(samples, volume) end) + if not success then + pcall(function() + ok = controller.playAudioAll(samples, 3.0) + end) + end if ok then break end local ev = { os.pullEvent() } if ev[1] == "audio_interrupt" and tonumber(ev[2]) and tonumber(ev[2]) >= playSeq then