我正在构建一个应用程序,旨在利用 Spotify 的网络播放器 SDK 并允许播放。我已成功将用户帐户连接到播放器以及所有其他必需的先决条件,但每当我尝试播放音频(遵循 Spotify 自己的示例代码)时,我都会收到控制台错误,指示:
控制台错误
Uncaught TypeError: this._streamer is null
编辑:我本来会发布错误堆栈的其余部分,但其中包含的 Spotify API URL 将帖子标记为垃圾邮件,因此不幸的是它们已被删除。
目前,编码的 React 组件有点长,但我将删除与我想做的其他事情相关的不相关部分:
应用程序.js
// External imports
import { Fragment, useEffect, useRef, useState } from 'react';
import { useCookies } from 'react-cookie';
export default function CartPlayer(props) {
const track = {
name: "",
album: {
images: [
{ url: "" }
]
},
artists: [
{ name: "" }
]
}
const [player, setPlayer] = useState(null);
const [isPaused, setIsPaused] = useState(false);
const [isPlaybackActive, setIsPlaybackActive] = useState(false);
const [currentTrack, setCurrentTrack] = useState(track);
const [deviceId, setDeviceId] = useState(null);
const [cookies, setCookie, removeCookie] = useCookies();
const spotifyAccessToken = cookies.userSpotifyAuth.access_token;
// Spotify SDK hook
useEffect(() => {
const script = document.createElement("script");
script.src = "https://sdk.scdn.co/spotify-player.js";
script.async = true;
document.body.appendChild(script);
window.onSpotifyWebPlaybackSDKReady = () => {
const player = new window.Spotify.Player({
name: 'Web Playback SDK',
getOAuthToken: cb => { cb(spotifyAccessToken); },
volume: 0.5
});
setPlayer(player);
player.addListener('ready', ({ device_id }) => {
console.log('Ready with Device ID', device_id);
setDeviceId(device_id);
});
player.addListener('not_ready', ({ device_id }) => {
console.log('Device ID has gone offline', device_id);
});
player.addListener('player_state_changed', ( state => {
if (!state) {
return;
}
setCurrentTrack(state.track_window.current_track);
setIsPaused(state.paused);
player.getCurrentState().then( state => {
(!state)? setIsPlaybackActive(false) : setIsPlaybackActive(true)
});
}));
player.on('playback_error', ({message}) => {
console.error('Failed to perform playback', message);
})
player.connect();
};
}, []);
// This function transfers active playback to the Spotify session in the browser
useEffect(() => {
async function transferPlayback() {
await fetch('https://api.spotify.com/v1/me/player', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + cookies.userSpotifyAuth.access_token
},
body: JSON.stringify({
device_ids: [
deviceId
],
play: true
})
});
}
if (deviceId) {
transferPlayback();
}
}, [deviceId])
if (!isPlaybackActive) {
return (
<>
<div className="container">
<div className="main-wrapper">
<b> Instance not active. Transfer your playback using your Spotify app </b>
</div>
</div>
</>)
} else {
return (
<>
<div className="container">
<div className="main-wrapper">
<img src={currentTrack.album.images[0].url} className="now-playing__cover" alt="" />
<div className="now-playing__side">
<div className="now-playing__name">{currentTrack.name}</div>
<div className="now-playing__artist">{currentTrack.artists[0].name}</div>
<button className="btn-spotify" onClick={() => { player.previousTrack() }} >
<<
</button>
<button className="btn-spotify" onClick={() => { player.togglePlay() }} >
{ isPaused ? "PLAY" : "PAUSE" }
</button>
<button className="btn-spotify" onClick={() => { player.nextTrack() }} >
>>
</button>
</div>
</div>
</div>
</>
);
}
该代码与 Spotify 提供的示例非常相似,除了浏览器内“设备”准备就绪并获得 ID 时调用的函数,然后为自身请求活动状态,以便它可以主动播放音频。有谁知道这里会发生什么吗?
我找到了一个解决方法/解决方案。问题似乎出在 React 18 上,从 SDK 调用的
iframe
出现了问题。
我的解决方案是降级到react 17,然后它就像一个魅力。我有一个私人仓库,所以我无法分享,但如果不是 18,请分享你的反应版本。
如果你像我一样并且使用过 Next.js,这是降级的方法 https://github.com/vercel/next.js/discussions/36006
这个问题被问到已经很长时间了,但我最近在 Next.js 14 + React 18 上遇到了这个问题,不得不自己修复它,所以我想我会分享我的解决方案。
我注意到 iframe 也存在问题,可能特别是 React 18 现在如何使用
createRoot
,所以我开始尝试。看来在主组件中使用这样的组件来加载 Spotify SDK 是可行的:
import { type FC, createElement } from 'react';
const SpotifyScript: FC = () => {
const script = createElement('script', {
id: 'spotify-player',
type: 'text/javascript',
async: false,
defer: true,
src: 'https://sdk.scdn.co/spotify-player.js',
onLoad: () => {
console.log('Spotify loaded');
},
onError: console.error
});
return script;
};
export default SpotifyScript;
不确定到底是什么原因,但我已经测试过这个,它至少让我过去了调用
player.getCurrentState()
等错误。您仍然可以使用 window.onSpotifyWebPlaybackSDKReady
回调来创建播放器并将其保存到某种状态。
希望这有帮助!