如何解决使用 react-native-track-player 播放来自 Napster API 的流式歌曲
我按照教程使用 react-native-track-player 设法构建了一个简单的音乐播放器,这是我在 React Native 中学习曲线的一部分。现在,我不只是从我的歌曲数组中提供的 url 轨道播放/流式传输歌曲,我想从 API 流式传输歌曲(虽然它可以是任何 API - 但我已经注册了 Napster API),我觉得这不受限制只是几首歌。但是,我无法整合如何实现或调用 Napster API 来获取歌曲。 请任何帮助/指南,我将不胜感激。
下面是我的代码:
我有 data.js,我的歌曲数组:
const songs = [
{
title: "death bed",artist: "Powfu",artwork: require("../assets/album-arts/death-bed.jpg"),url: "https://github.com/ShivamJoker/sample-songs/raw/master/death%20bed.mp3",id: "1",},{
title: "bad liar",artist: "Imagine Dragons",artwork: require("../assets/album-arts/bad-liar.jpg"),url: "https://github.com/ShivamJoker/sample-songs/raw/master/Bad%20Liar.mp3",id: "2",{
title: "faded",artist: "Alan Walker",artwork: require("../assets/album-arts/faded.jpg"),url: "https://github.com/ShivamJoker/sample-songs/raw/master/Faded.mp3",id: "3",];
export default songs;
这是我的 playerScreen.js :
import React,{useRef,useEffect,useState} from 'react';
import {
View,SafeAreaView,Text,Image,FlatList,Dimensions,Animated,StyleSheet,} from 'react-native';
import TrackPlayer,{
Capability,useTrackPlayerEvents,usePlaybackState,TrackPlayerEvents,STATE_PLAYING,Event,} from 'react-native-track-player';
import songs from './data';
import Controller from './Controller';
import SliderComp from './SliderComp';
const {width,height} = Dimensions.get('window');
// const events = [
// TrackPlayerEvents.PLAYBACK_STATE,// TrackPlayerEvents.PLAYBACK_ERROR
// ];
export default function PlayerScreen() {
const scrollX = useRef(new Animated.Value(0)).current;
const slider = useRef(null);
const isPlayerReady = useRef(false);
const index = useRef(0);
const [songIndex,setSongIndex] = useState(0);
const isItFromUser = useRef(true);
// for tranlating the album art
const position = useRef(Animated.divide(scrollX,width)).current;
const playbackState = usePlaybackState();
useEffect(() => {
// position.addListener(({ value }) => {
// console.log(value);
// });
scrollX.addListener(({value}) => {
const val = Math.round(value / width);
setSongIndex(val);
});
TrackPlayer.setupPlayer().then(async () => {
// The player is ready to be used
console.log('Player ready');
// add the array of songs in the playlist
await TrackPlayer.reset();
await TrackPlayer.add(songs);
TrackPlayer.play();
isPlayerReady.current = true;
await TrackPlayer.updateOptions({
stopWithApp: false,alwaysPauSEOnInterruption: true,capabilities: [
Capability.Play,Capability.Pause,Capability.SkipToNext,Capability.SkipToPrevIoUs,],});
//add listener on track change
TrackPlayer.addEventListener(Event.PlaybackTrackChanged,async (e) => {
console.log('song ended',e);
const trackId = (await TrackPlayer.getCurrentTrack()) - 1; //get the current id
console.log('track id',trackId,'index',index.current);
if (trackId !== index.current) {
setSongIndex(trackId);
isItFromUser.current = false;
if (trackId > index.current) {
goNext();
} else {
goPrv();
}
setTimeout(() => {
isItFromUser.current = true;
},200);
}
// isPlayerReady.current = true;
});
//monitor intterupt when other apps start playing music
TrackPlayer.addEventListener(Event.RemoteDuck,(e) => {
// console.log(e);
if (e.paused) {
// if pause true we need to pause the music
TrackPlayer.pause();
} else {
TrackPlayer.play();
}
});
});
return () => {
scrollX.removeAllListeners();
TrackPlayer.destroy();
// exitPlayer();
};
},[]);
// change the song when index changes
useEffect(() => {
if (isPlayerReady.current && isItFromUser.current) {
TrackPlayer.skip(songs[songIndex].id)
.then((_) => {
console.log('changed track');
})
.catch((e) => console.log('error in changing track ',e));
}
index.current = songIndex;
},[songIndex]);
const exitPlayer = async () => {
try {
await TrackPlayer.stop();
} catch (error) {
console.error('exitPlayer',error);
}
};
const goNext = async () => {
slider.current.scrollToOffset({
offset: (index.current + 1) * width,});
await TrackPlayer.play();
};
const goPrv = async () => {
slider.current.scrollToOffset({
offset: (index.current - 1) * width,});
await TrackPlayer.play();
};
const renderItem = ({index,item}) => {
return (
<Animated.View
style={{
alignItems: 'center',width: width,transform: [
{
translateX: Animated.multiply(
Animated.add(position,-index),-100,),}}>
<Animated.Image
source={item.artwork}
style={{width: 320,height: 320,borderRadius: 5}}
/>
</Animated.View>
);
};
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={{height: 320}}>
<Animated.FlatList
ref={slider}
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
data={songs}
renderItem={renderItem}
keyExtractor={(item) => item.id}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {x: scrollX}}}],{useNativeDriver: true},)}
/>
</SafeAreaView>
<View>
<Text style={styles.title}>{songs[songIndex].title}</Text>
<Text style={styles.artist}>{songs[songIndex].artist}</Text>
</View>
<SliderComp />
<Controller onNext={goNext} onPrv={goPrv} />
</SafeAreaView>
);
}
解决方法
我会通过道具将 songs
传递到您当前的 PlayerScreen
中。您可以使用单独的组件从 Napster API 加载曲目,然后使用这些道具渲染 PlayerScreen
。
唯一我不确定的部分是作为 url
传递给玩家的路径。 Napster 数据包含一个属性 previewURL
,它是一个 mp3
,但它不是整首歌曲。我相信 href
是可流式传输的 URL。不过,它需要身份验证才能加载完整曲目。
我在这里使用的 API 路径适用于最流行的曲目。
export default function TopTracks() {
const [songs,setSongs] = useState([]);
useEffect(() => {
const loadData = async () => {
try {
const url = `http://api.napster.com/v2.2/tracks/top?apikey=${API_KEY}&limit=5`;
const res = await axios.get(url);
setSongs(
res.data.tracks.map((track) => ({
duration: track.playbackSeconds,title: track.name,artist: track.artistName,album: track.albumName,id: track.id,url: track.href // or track.previewURL?
}))
);
} catch (error) {
console.error(error);
}
};
loadData();
},[]);
return <PlayerScreen songs={songs} />;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。