有没有办法使用Expo AV添加背景音乐而不添加“播放音乐”按钮?

问题描述 投票:0回答:1

我想添加自动播放的背景音乐,可能只有“暂停/停止音频”

我尝试在多个来源中搜索,但我找到的所有教程都包含“播放声音”音乐,这是不需要的。

react-native expo background-music expo-av
1个回答
0
投票

他们并没有在 expo-av 页面上提供的示例中真正显示它,但 Audio.Sound.createAsync 函数允许进行大量自定义。您可以设置音量,决定是否应该循环播放,决定是否应该在加载时播放,甚至可以订阅播放状态更新并设置获取这些更新的时间间隔。我太过分了,充实了一个钩子来返回歌曲播放时的状态、位置和持续时间;如果您需要订阅其他信息,该挂钩将允许您订阅播放更新事件:

import { useState, useEffect, useCallback, useMemo } from 'react';
import { Audio, usePermissions } from 'expo-av';


const msToSeconds = (num) => Math.round(num / 1000);
// these should work but I found that only isPlaying works
const STATUSES = ['isBuffering', 'isPlaying', 'didJustFinished', 'isLooping'];
const getStatus = (playbackEvent) => {
  if (playbackEvent.durationMillis === playbackEvent.positionMillis)
    return 'finished';
  const status = STATUSES.find((status) => playbackEvent[status] === true);
  if (status) return status === 'didJustFinished' ? 'finished' : status;
};

export default function useAudio({
  uri,
  shouldPlay = false,
  onPlaybackStatusUpdate,
  updateIntervals = 500,
  startPosition = 0,
  shouldLoop = false,
}) {
  const [sound, setS] = useState(null);
  const [position, setPosition] = useState(0);
  const [status, setStatus] = useState('isLoading');
  const [duration, setDuration] = useState(0);
  
  const handlePlaybackStatusChange = useCallback(
    (playbackEvent) => {
      setStatus(getStatus(playbackEvent));
      setPosition(msToSeconds(playbackEvent.positionMillis||0));
      // because this function is recreated everytime onPlaybuckStatusChange
      // is recreated, onPlaybackStatusUpdate may need to be wrap in an
      // useCallback for better performance
      onPlaybackStatusUpdate?.(playbackEvent);
    },
    [onPlaybackStatusUpdate]
  );
  // cleanup function 
  useEffect(() => {
    return async () => {
      if (sound) {
        // await sound.pauseAsync();
        await sound.unloadAsync();
      }
    };
  }, [sound]);
  // load song on uri changes
  useEffect(() => {
    const loadSound = async () => {
      try {
        const {sound,status} = await Audio.Sound.createAsync(
          uri,
          {
            shouldPlay,
            progressUpdateIntervalMillis: updateIntervals,
            positionMillis: startPosition,
            isLooping: shouldLoop,
            volume:1
          },
          handlePlaybackStatusChange
        );
        setS(sound);
        setDuration(msToSeconds(status.durationMillis));
      } catch (err) {
        console.log(err);
        setStatus('error')
      }
    };
    loadSound();
  }, [
    uri,
    handlePlaybackStatusChange,
    shouldLoop,
    shouldPlay,
    startPosition,
    updateIntervals,
  ]);
  return { position, status, duration,sound };
}

使用钩子(演示):

const playOnLoad = true;
const updateIntervals = 1000;
const startPosition = 1000 * 60 * 4.4;

export default function App() {
  const { width } = useWindowDimensions();
  const barWidth = width * 0.8;
  const { position, duration, status } = useAudio({
    uri: require('./song.mp3'),
    shouldPlay: playOnLoad,
    updateIntervals,
    startPosition:0,
    shouldLoop: true,
  });
  return (
    <SafeAreaView style={styles.container}>
      <View style={[styles.player, { width: barWidth }]}>
        <Text>Sound status:{status}</Text>
        <Progress.Bar progress={position/duration || 0} width={barWidth} color="green" />
        <View style={styles.timeContainer}>
          <Text style={styles.currentTime}>{formatSeconds(position)}</Text>
          <Text style={styles.duration}>{formatSeconds(duration)}</Text>
        </View>
      </View>
    </SafeAreaView>
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.