You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raspberry Pi上通过Puppeteer驱动Chromium播放音频出现卡顿问题求助

问题核心原因

该问题由三方面共同导致:

  1. Puppeteer默认启动的Chromium开启了后台标签页资源节流策略,定时器、媒体线程优先级被降低,播放进度判断和音频渲染出现延迟
  2. 树莓派硬件资源有限,默认配置下Chromium媒体播放进程优先级不足,易被系统抢占资源
  3. Howler配置和代码逻辑存在可优化空间,低性能设备上易出现渲染卡顿

具体解决方案

1. 修正Puppeteer启动配置

添加Chromium启动参数关闭资源节流,同时调整缓存策略:

const puppeteer = require ('puppeteer-core');

(async () => {
    const browser = await puppeteer.launch ({
        headless: false,
        executablePath: '/usr/bin/chromium-browser',
        args: [
            '--disable-background-timer-throttling', // 禁用后台定时器节流
            '--disable-backgrounding-occluded-windows', // 禁止窗口遮挡后降优先级
            '--disable-renderer-backgrounding', // 禁止渲染进程后台降权
            '--autoplay-policy=no-user-gesture-required', // 取消自动播放用户手势要求
            '--disable-features=AudioServiceOutOfProcess', // 禁用音频服务独立进程,降低资源开销
            '--disable-audio-output-resampler' // 禁用音频重采样,降低CPU开销
        ]
    });
    const page = await browser.newPage();
    await page.setDefaultNavigationTimeout(0);
    // 本地服务建议开启缓存,避免重复读取IO资源
    await page.setCacheEnabled(true);
    await page.goto('http://localhost:8080');
    
    await page.waitForSelector('#play-button').then(()=> page.click('#play-button'));
    // 监听页面错误日志,方便排查崩溃问题
    page.on('console', msg => console.log('页面日志:', msg.text()));
})();   

运行脚本时提升进程优先级,避免系统资源抢占:

sudo nice -n -10 node puppeteer-script.js

2. 优化Howler配置与播放逻辑

  1. 关闭html5模式,使用性能更好的Web Audio API实现音频渲染,混音和淡入淡出的效率会明显提升
  2. 添加淡入淡出逻辑,避免音频硬切产生的毛刺
  3. 提前预加载后续音频,同时注意释放无用资源避免内存溢出

优化后的核心代码示例:

// 全局fadeTime可根据需要调整
const fadeTime = 3000;

function loadingSound1 (i, playingList) {
    let intervaller;
    // 提前预加载下一首
    if (i+2 < playingList.length) {
        new Howl({src: [playingList[i+2]], preload: true});
    }
    sound1 = new Howl ({
        src: [playingList[i]],
        preload: true,
        html5: false, // 关闭HTML5模式,使用Web Audio
        volume: 0, // 初始音量为0,播放时淡入
        onplay: function() {
            // 播放时淡入到1
            sound1.fade(0, 1, fadeTime);
            const time1 = sound1.duration();
            const timetoswitch1 = time1 - fadeTime;
            intervaller = setInterval(() => {
                if (sound1.seek() >= timetoswitch1) {
                    sound2.play();
                    // 当前音轨淡出
                    sound1.fade(1, 0, fadeTime);
                    clearInterval(intervaller);
                };
            },100); // 降低检查间隔,避免切换时机延迟                     
        },
        onpause: function () {clearInterval(intervaller)},          
        onend: function () {
            console.log('i = ' + i + 'k = ' + k);
            sound1.unload();
            // 手动释放引用,方便垃圾回收
            sound1 = null;
            const listLength = playingList.length;
            i = i + 2;
            if (i < listLength) {
                loadingSound1 (i, playingList);
            }     
        }
    })
}

function loadingSound2 (k, playingList) {
    let intervaller;
    // 提前预加载下一首
    if (k+2 < playingList.length) {
        new Howl({src: [playingList[k+2]], preload: true});
    }
    sound2 = new Howl ({
        src: [playingList[k]],
        preload: true,
        html5: false, // 关闭HTML5模式,使用Web Audio
        volume: 0, // 初始音量为0,播放时淡入
        onplay: function() {
            // 播放时淡入到1
            sound2.fade(0, 1, fadeTime);
            const time2 = sound2.duration();
            const timetoswitch2 = time2 - fadeTime;
            intervaller = setInterval(() => {
                if (sound2.seek() >= timetoswitch2) {
                    sound1.play();
                    // 当前音轨淡出
                    sound2.fade(1, 0, fadeTime);
                    clearInterval(intervaller);
                };
            },100); // 降低检查间隔,避免切换时机延迟                 
        },
        onend: function () {
            const listLength = playingList.length;
            sound2.unload();
            // 手动释放引用,方便垃圾回收
            sound2 = null;
            k = k + 2;
            if (k < listLength) {
                loadingSound2 (k, playingList);
            }
        }
    })
}

3. 树莓派系统层面优化

  • 关闭不必要的桌面进程、后台服务,释放CPU和内存资源,建议使用无桌面版本的树莓派系统运行该服务
  • 升级Chromium到最新适配树莓派的版本,旧版本(88.x)对Web Audio的优化存在缺陷
  • 检查系统日志dmesg是否存在OOM(内存不足)记录,如果内存不够可以适当增加树莓派的swap分区大小

内容的提问来源于stack exchange,提问作者philippino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 19:39:01