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

react-native-sound首次播放无声音及多次播放缺失问题求助

问题排查与修复方案

核心问题分析

  • 音频初始化时机错误:把new Sound()放在组件顶层,每次组件渲染都会重新创建实例,且未等待加载完成就调用play,这是首次无声音的主要原因。
  • 递归中的音频停止逻辑错误:在递归调用movePawnByStep后立即调用stop,会中断当前正在播放的音频,导致部分播放缺失。
  • 未重置音频播放位置:重复播放时没有将音频重置到开头,可能导致音频处于结束状态无法再次播放。
  • 播放回调处理不当:回调中直接再次调用play,未判断音频当前状态,容易引发播放冲突。

修复后的代码

import Sound from 'react-native-sound';
import { useEffect, useRef } from 'react';

// 假设FINISHED和setTestState是已定义的变量/函数
const FINISHED = 'finished';

export default function App(){
    const stepAudio = useRef(null);
    const isAudioLoaded = useRef(false);

    // 仅初始化一次音频
    useEffect(() => {
        stepAudio.current = new Sound('step.mp3', Sound.MAIN_BUNDLE, (error) => {
            if (error) {
                console.log('Error Step Audio', error);
                return;
            }
            // 标记音频加载完成
            isAudioLoaded.current = true;
            // 设置单次播放,完成后自动重置位置
            stepAudio.current.setNumberOfLoops(0);
        });

        // 组件卸载时释放音频资源
        return () => {
            if (stepAudio.current) {
                stepAudio.current.release();
            }
        };
    }, []);

    async function playStepAudio() {
        if (!isAudioLoaded.current || !stepAudio.current) return;
        
        // 重置音频到起始位置,确保每次播放从头开始
        stepAudio.current.setCurrentTime(0);
        
        return new Promise((resolve) => {
            stepAudio.current.play((success) => {
                if (!success) {
                    console.log('Audio playback failed');
                }
                resolve(success);
            });
        });
    }

    async function movePawnByStep(prevPosition, newPostion, piece, areaIndicator, finished = null) {
        // 等待音频播放完成后再执行后续逻辑
        await playStepAudio();
        
        piece.position = areaIndicator + ++prevPosition;
        piece.updateTime = Date.now();

        if (prevPosition < newPostion) {
            setTimeout(() => {
                movePawnByStep(prevPosition, newPostion, piece, areaIndicator, finished);
                setTestState(prev => !prev);
            }, 100);
        } else {
            if (finished !== null) {
                piece.position = FINISHED;
                piece.updateTime = Date.now();
            }
            setTestState(prev => !prev);
        }
    }
}

关键改动说明

  • 用useEffect初始化音频:确保音频只被创建一次,等待加载完成后才允许播放,彻底解决首次调用时音频未就绪的问题。
  • 新增playStepAudio工具函数:统一处理音频重置和播放逻辑,返回Promise让播放流程可控,每次播放前强制重置到起始位置。
  • 移除错误的stop调用:递归过程中不需要手动终止音频,让音频自然播放完成;若需控制播放时长,可在play回调中处理。
  • 组件卸载时释放资源:避免内存泄漏,符合react-native-sound的最佳实践。
  • 简化递归逻辑:去掉setTimeout中不必要的await和clearTimeout,避免异步嵌套导致的音频冲突。

额外注意事项

  • 确认step.mp3文件路径正确,放在对应平台的资源目录(iOS的Resources或Android的raw目录)。
  • 若需要音频与移动动画严格同步,可调整setTimeout延迟时间,或改用requestAnimationFrame替代。
  • 测试时检查设备静音状态及react-native-sound的权限配置(如Android的音频权限)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:01:05