我想添加自动播放的背景音乐,可能只有“暂停/停止音频”
我尝试在多个来源中搜索,但我找到的所有教程都包含“播放声音”音乐,这是不需要的。
他们并没有在 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>
);
}