首页 > 解决方案 > 如何在 React Native 中播放多个音频?

问题描述

我想在我的 React Native 应用程序中播放多个音频文件。目前,一次播放一个音频,我也希望一次播放单个音频。我想要的是,如果一个音频正在播放并且用户突然点击第二个音频按钮,第一个音频按钮将暂停,第二个音频按钮应该播放。当用户再次点击第一个时,暂停的音频将从暂停的位置重新开始。类似于 whatsapp 音频消息。

我正在使用react-native-audio-recorder-player在我的应用程序中录制和播放音频。 检查应用程序设计

我的 FlatList 项目设计:

{ { this.toggleMediaPlayer(item.audiourl, index) } }}>

                                            <TouchableOpacity
                                                style={styles.viewBarWrapper}
                                                onPress={this.onStatusPress}
                                            >
                                                <View style={styles.viewBar}>
                                                    <View style={styles.viewBarPlay} />
                                                </View>
                                            </TouchableOpacity>
                                            <Text style={styles.txtCounter}>
                                                {/* {this.state.playTime} / {this.state.duration} */}
                                            </Text>

                                        </View>

媒体播放器功能:

`toggleMediaPlayer(mediaPath, index) {

    if (this.state.mediaFlag[index] == false) {
        this.onStartPlay(mediaPath, index)

        this.state.mediaFlag[index] = true;
        var cloneObj = Object.assign({}, this.state.mediaFlag);
        this.setState({ mediaFlag: cloneObj });
        console.log(this.state.mediaFlag)

    }
    else {
        this.onPausePlay(mediaPath)
        this.state.mediaFlag[index] = false;
        var cloneObj = Object.assign({}, this.state.mediaFlag);
        this.setState({ mediaFlag: cloneObj });
        console.log(this.state.mediaFlag)
    }
}

`

休息代码

audioRecorderPlayer = new AudioRecorderPlayer();

async onStartPlay(path, index) {
    console.log('onStartPlay');
    this.audioRecorderPlayer.stopPlayer();
    const msg = await this.audioRecorderPlayer.startPlayer(path);
    console.log(msg);
    this.audioRecorderPlayer.addPlayBackListener(async (e) => {
        if (e.current_position === e.duration) {
            console.log('finished');
            // await this.setState({ mediaFlag: !this.state.mediaFlag });

            this.state.mediaFlag[index] = false;
            var cloneObj = Object.assign({}, this.state.mediaFlag);
            this.setState({ mediaFlag: cloneObj });
            console.log(this.state.mediaFlag)

            this.audioRecorderPlayer.stopPlayer();
            this.audioRecorderPlayer.removePlayBackListener();
        }
        else {
            this.setState({
                currentPositionSec: e.current_position,
                currentDurationSec: e.duration,
                playTime: this.audioRecorderPlayer.mmssss(Math.floor(e.current_position)),
                duration: this.audioRecorderPlayer.mmssss(Math.floor(e.duration)),
            })
        }
        return;
    });
};

onPausePlay = async () => {
    await this.audioRecorderPlayer.pausePlayer();
};

async onStopPlay(index) {
    console.log('onStopPlay');
    this.audioRecorderPlayer.stopPlayer();
    this.audioRecorderPlayer.removePlayBackListener();
};

标签: androidreact-native

解决方案


截至v2.4.3,它不是react-native-audio-recorder-player的功能(请参阅https://github.com/dooboolab/react-native-audio-recorder-player/issues/130

但我必须自己做,所以这是我设法做到的:

  • 要点是拥有所有玩家的父组件(或商店 - 如redux或react context),它知道玩家的状态(玩家是否在阅读它的声音?哪个?)

  • 然后,当播放器播放声音时,它会调用父组件,父组件将停止当前正在阅读的任何其他播放器 - 必须按特定顺序完成以避免奇怪的行为

这是我的代码简化:

const ParentComponent = () => {
  const [playerRecording, setPlayerRecording] = useState(false); // Which recording is currently playing?

  const onPlay = async (onStartPlay, playerId) => {
    // No player are reading or it is the same player
    if (!playerRecording || playerRecording === playerId) 
      return onStartPlay();

    // Another player is reading - stop it before starting the new one
    audioRecorderPlayer.removePlayBackListener();
    await audioRecorderPlayer.resumePlayer();
    await audioRecorderPlayer.stopPlayer();
    // Start the new player
    onStartPlay();
  };
}

const PlayerComponent = ({onPlay, setPlayerRecording, playerId}) => {
  const onStartPlay = async () => {
    setPlayerRecording(playerId);
    audioRecorderPlayer.startPlayer(path);
    ...
  }

  return (
    <PlayButton onPress={() => onPlay(onStartPlay, playerId)} />
  )
}

推荐阅读