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

React Native能否实现实时播放进度条?指定库使用遇困求助

React Native 实时播放进度条实现方案(基于react-native-sound-player + @react-native-community/slider)

核心疑问解答

react-native-sound-player 的 getInfo() 确实可以用来实现实时进度条,但它是异步Promise方法,无法主动推送播放状态更新,所以需要通过定时轮询的方式定期调用它来获取当前播放时间,从而更新滑块状态。

具体实现步骤及代码示例

以下是适配RN 0.68.4、兼容安卓/iOS的完整实现:

1. 安装依赖(确保已正确安装)

npm install react-native-sound-player @react-native-community/slider
# 或 yarn
yarn add react-native-sound-player @react-native-community/slider

注意:RN 0.68.4属于较稳定版本,这两个库的最新兼容版本均可直接使用,无需额外link(自动link已支持)。

2. 组件实现代码

import React, { useState, useEffect, useRef } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import Slider from '@react-native-community/slider';
import SoundPlayer from 'react-native-sound-player';

const AudioPlayer = () => {
  // 播放状态与进度相关状态
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);
  // 定时器引用,用于清除轮询
  const timerRef = useRef(null);

  // 初始化音频(替换为你的音频路径)
  useEffect(() => {
    try {
      SoundPlayer.loadSound('your-audio-file.mp3');
      // 首次加载时获取总时长
      SoundPlayer.getInfo().then(info => {
        setDuration(info.duration);
      });
    } catch (error) {
      console.log('音频加载失败:', error);
    }

    // 组件卸载时清理资源
    return () => {
      if (timerRef.current) clearInterval(timerRef.current);
      SoundPlayer.stop();
    };
  }, []);

  // 播放/暂停逻辑
  const togglePlay = async () => {
    try {
      if (isPlaying) {
        await SoundPlayer.pause();
        clearInterval(timerRef.current);
      } else {
        await SoundPlayer.play();
        // 启动定时轮询,每500ms获取一次播放进度
        timerRef.current = setInterval(async () => {
          const info = await SoundPlayer.getInfo();
          setCurrentTime(info.currentTime);
        }, 500);
      }
      setIsPlaying(!isPlaying);
    } catch (error) {
      console.log('播放/暂停失败:', error);
    }
  };

  // 快退10秒
  const rewind = async () => {
    const newTime = Math.max(0, currentTime - 10);
    await SoundPlayer.seek(newTime);
    setCurrentTime(newTime);
  };

  // 快进10秒
  const forward = async () => {
    const newTime = Math.min(duration, currentTime + 10);
    await SoundPlayer.seek(newTime);
    setCurrentTime(newTime);
  };

  // 滑块拖动结束时跳转播放位置
  const handleSliderComplete = async (value) => {
    await SoundPlayer.seek(value);
    setCurrentTime(value);
  };

  // 格式化时间为 mm:ss
  const formatTime = (seconds) => {
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
  };

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 }}>
      <View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
        <TouchableOpacity onPress={rewind} style={{ padding: 10 }}>
          <Text>快退10s</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={togglePlay} style={{ padding: 10 }}>
          <Text>{isPlaying ? '暂停' : '播放'}</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={forward} style={{ padding: 10 }}>
          <Text>快进10s</Text>
        </TouchableOpacity>
      </View>

      <Slider
        style={{ width: '100%', height: 40 }}
        minimumValue={0}
        maximumValue={duration}
        value={currentTime}
        onSlidingComplete={handleSliderComplete}
        minimumTrackTintColor="#000000"
        maximumTrackTintColor="#cccccc"
      />

      <View style={{ flexDirection: 'row', justifyContent: 'space-between', width: '100%', marginTop: 10 }}>
        <Text>{formatTime(currentTime)}</Text>
        <Text>{formatTime(duration)}</Text>
      </View>
    </View>
  );
};

export default AudioPlayer;

关键注意事项

  • 定时器清理:必须在组件卸载或暂停播放时清除定时器,避免内存泄漏。
  • 音频路径处理:安卓和iOS的音频文件放置路径不同,需确保路径正确(安卓放在android/app/src/main/res/raw,iOS放在项目资源中)。
  • 异常捕获:所有react-native-sound-player的异步方法都要加try/catch,避免因音频加载失败、播放中断等导致崩溃。
  • 滑块交互:仅在onSlidingComplete时调用seek(),避免拖动过程中频繁跳转影响性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 01:25:20