使用 Spotify Web API / Playback SDK 检测曲目的播放结束
Detect end of a track's playback with Spotify Web API / Playback SDK
使用 Spotify Web API 和 Web Playback SDK,有人知道检测曲目播放何时结束(即歌曲结束)的好方法吗?
我知道 Web Playback SDK 中有一个名为 player_state_changed
的事件,但事件中提供的数据似乎对我帮助不大。
在我的网络应用程序中,下一首要播放的歌曲是自发确定的。如果我只能在当前曲目结束时确定它,那就太好了。因此,没有播放列表。相反,该应用会连续播放单首曲目,并应在当前歌曲结束时确定下一首歌曲。
与此同时,我在这里尝试使用此代码:
var bCallingNextSong = false;
player.addListener('player_state_changed', state => {
if (state != null &&
state.position == 0 &&
state.duration == 0 &&
state.paused == true) {
if (!bCallingNextSong) {
playNextSong();
}
}
});
function playNextSong() {
$.ajax({
url:"playback.php", //the page containing php script
type: "post", //request type,
dataType: 'json',
data: {action: "next", device: deviceId},
success: function(result) {
bCallingNextSong = false;
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
bCallingNextSong = false;
}
});
}
并在 playback.php
中:
switch ($action) {
case "next":
//some blackbox magic here to determine next song, do logging etc.
//but for now just play the same song over and over
$api->play($deviceId, ['uris' => "spotify:track:0eGsygTp906u18L0Oimnem"],]);
echo json_encode(array("answer"=>"played next"));
break;
// more code
}
然而,这经常(但不总是)抛出 InvalidStateError(我还没有找到确切的位置和原因)。 Stack 表示 dequeueUpdates / tryUpdate / _processUpdate / _appendUpdate。然而,我是初学者,我必须先学习如何处理 Firefox Debugger.. :)
您应该使用 player_state_changed
事件并查看正在播放的曲目是否已更改。您可以在 playerStateObject.track_window.current_track
.
中找到当前曲目
一个可能的实现可能是这样的:
let currentTrack = '';
player.on('player_state_changed', state => {
if( state.track_window.current_track.id != currentTrack ) {
// The track changed!
currentTrack = state.track_window.current_track.id;
}
});
编辑:由于某种原因,这不再有效。检查我现在可以使用的其他答案。
这是我的解决方案。它大部分时间都有效。事实上,在我能想象到的任何情况下,我都没有把它弄坏。所以保持最后一个状态并检查它是否进入暂停状态。希望 Spotify 将简化我们在跟踪结束事件方面的工作。如果他们这样做会很棒。这仍然比每 1 秒左右轮询他们的 /me/player/currently-playing 端点要好。
this.player.addListener(
'player_state_changed',
state =>
{
console.log(state);
if(this.state && !this.state.paused && state.paused && state.position === 0) {
console.log('Track ended');
this.setTrackEnd(true);
}
this.state = state;
}
);
我的上一个答案被破坏了,所以我现在将添加目前有效的新解决方案。
this.player.addListener('player_state_changed', (state) => {
console.log(state);
if (
this.state
&& state.track_window.previous_tracks.find(x => x.id === state.track_window.current_track.id)
&& !this.state.paused
&& state.paused
) {
console.log('Track ended');
this.setTrackEnd(true);
}
this.state = state;
});
那么与上一个解决方案有何不同?我检查 current_track 是否在之前的曲目列表中。但是现在位置检查有问题,因为似乎当前曲目在曲目完全结束之前出现在上一个曲目列表中。但这在我的应用程序中不是问题,因为命令总是有小的延迟。
我遇到了同样的问题,我就是这样解决的。
歌曲播放完毕后,它会添加到 state.track_window.previous_tracks
列表
state.track_window.previous_tracks
只有在有下一首曲目并开始播放时才会填充
但是每次调用 api 播放新曲目时,它都会清除 state.track_window.previous_tracks
& state.track_window.next_tracks
列表。
如果有下一首曲目,我想停下来选择我自己的下一首曲目,然后调用 api
var alreadyPlayed = state.track_window.previous_tracks
if(alreadyPlayed.length > 0) {
player.pause()
}
如果没有下一首曲目,播放器将在歌曲结束时暂停
if(state.paused && state.position === 0) {
//song ended
ChooseNextSong()
}
state
回调被触发了很多次,但我想调用 ChooseNextSong()
只有一次,所以每次触发时我都会增加 startCheck
if(state.paused && state.position === 0) {
//song ended
startCheck++
if(startCheck === 1) {
ChooseNextSong()
}
}
检查歌曲是否开始
if(state.position === 0 && alreadyPlayed.length === 0 && !state.paused)
{
//song started
startCheck = 0
}
使用 Spotify Web API 和 Web Playback SDK,有人知道检测曲目播放何时结束(即歌曲结束)的好方法吗?
我知道 Web Playback SDK 中有一个名为 player_state_changed
的事件,但事件中提供的数据似乎对我帮助不大。
在我的网络应用程序中,下一首要播放的歌曲是自发确定的。如果我只能在当前曲目结束时确定它,那就太好了。因此,没有播放列表。相反,该应用会连续播放单首曲目,并应在当前歌曲结束时确定下一首歌曲。
与此同时,我在这里尝试使用此代码:
var bCallingNextSong = false;
player.addListener('player_state_changed', state => {
if (state != null &&
state.position == 0 &&
state.duration == 0 &&
state.paused == true) {
if (!bCallingNextSong) {
playNextSong();
}
}
});
function playNextSong() {
$.ajax({
url:"playback.php", //the page containing php script
type: "post", //request type,
dataType: 'json',
data: {action: "next", device: deviceId},
success: function(result) {
bCallingNextSong = false;
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
bCallingNextSong = false;
}
});
}
并在 playback.php
中:
switch ($action) {
case "next":
//some blackbox magic here to determine next song, do logging etc.
//but for now just play the same song over and over
$api->play($deviceId, ['uris' => "spotify:track:0eGsygTp906u18L0Oimnem"],]);
echo json_encode(array("answer"=>"played next"));
break;
// more code
}
然而,这经常(但不总是)抛出 InvalidStateError(我还没有找到确切的位置和原因)。 Stack 表示 dequeueUpdates / tryUpdate / _processUpdate / _appendUpdate。然而,我是初学者,我必须先学习如何处理 Firefox Debugger.. :)
您应该使用 player_state_changed
事件并查看正在播放的曲目是否已更改。您可以在 playerStateObject.track_window.current_track
.
一个可能的实现可能是这样的:
let currentTrack = '';
player.on('player_state_changed', state => {
if( state.track_window.current_track.id != currentTrack ) {
// The track changed!
currentTrack = state.track_window.current_track.id;
}
});
编辑:由于某种原因,这不再有效。检查我现在可以使用的其他答案。
这是我的解决方案。它大部分时间都有效。事实上,在我能想象到的任何情况下,我都没有把它弄坏。所以保持最后一个状态并检查它是否进入暂停状态。希望 Spotify 将简化我们在跟踪结束事件方面的工作。如果他们这样做会很棒。这仍然比每 1 秒左右轮询他们的 /me/player/currently-playing 端点要好。
this.player.addListener(
'player_state_changed',
state =>
{
console.log(state);
if(this.state && !this.state.paused && state.paused && state.position === 0) {
console.log('Track ended');
this.setTrackEnd(true);
}
this.state = state;
}
);
我的上一个答案被破坏了,所以我现在将添加目前有效的新解决方案。
this.player.addListener('player_state_changed', (state) => {
console.log(state);
if (
this.state
&& state.track_window.previous_tracks.find(x => x.id === state.track_window.current_track.id)
&& !this.state.paused
&& state.paused
) {
console.log('Track ended');
this.setTrackEnd(true);
}
this.state = state;
});
那么与上一个解决方案有何不同?我检查 current_track 是否在之前的曲目列表中。但是现在位置检查有问题,因为似乎当前曲目在曲目完全结束之前出现在上一个曲目列表中。但这在我的应用程序中不是问题,因为命令总是有小的延迟。
我遇到了同样的问题,我就是这样解决的。
歌曲播放完毕后,它会添加到 state.track_window.previous_tracks
列表
state.track_window.previous_tracks
只有在有下一首曲目并开始播放时才会填充
但是每次调用 api 播放新曲目时,它都会清除 state.track_window.previous_tracks
& state.track_window.next_tracks
列表。
如果有下一首曲目,我想停下来选择我自己的下一首曲目,然后调用 api
var alreadyPlayed = state.track_window.previous_tracks
if(alreadyPlayed.length > 0) {
player.pause()
}
如果没有下一首曲目,播放器将在歌曲结束时暂停
if(state.paused && state.position === 0) {
//song ended
ChooseNextSong()
}
state
回调被触发了很多次,但我想调用 ChooseNextSong()
只有一次,所以每次触发时我都会增加 startCheck
if(state.paused && state.position === 0) {
//song ended
startCheck++
if(startCheck === 1) {
ChooseNextSong()
}
}
检查歌曲是否开始
if(state.position === 0 && alreadyPlayed.length === 0 && !state.paused)
{
//song started
startCheck = 0
}