【问题标题】:Detect end of a track's playback with Spotify Web API / Playback SDK使用 Spotify Web API / Playback SDK 检测曲目播放的结束
【发布时间】:2018-04-12 21:07:20
【问题描述】:

使用 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(我还没有找到确切的位置和原因)。堆栈说 dequeueUpdates / tryUpdate / _processUpdate / _appendUpdate。然而,我是一个初学者,我必须先学习如何应对 Firefox Debugger.. :)

【问题讨论】:

    标签: spotify


    【解决方案1】:

    我的最后一个答案被打破了,所以我现在将添加现在可以使用的新解决方案。

    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 是否在以前的曲目列表中。但是现在位置检查出现了问题,因为当前曲目似乎在曲目完全结束之前出现在先前的曲目列表中。但这在我的应用程序中不是问题,因为命令总是存在小的延迟。

    【讨论】:

    • 请注意,有时这会被触发多次,我们有时会计数 4 次,然后是 2 次。
    【解决方案2】:

    编辑:由于某种原因,这不再起作用。检查我现在可以使用的其他答案。 https://stackoverflow.com/a/51114848/8081009

    这是我的解决方案。它大部分时间都有效。实际上,在我能想象的任何情况下,我都没有把它弄坏。所以保持最后一个状态并检查它是否进入暂停状态。希望 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;
        }
      );
    

    【讨论】:

    【解决方案3】:

    您应该使用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;
        }
    });
    

    【讨论】:

    • 但如果同一首曲目在之后第二次播放,这将失败。此外,就我而言,只有在当前曲目结束时才应确定下一曲目。因此,在您的示例中还没有“下一个”轨道。我没有播放列表。我曾希望当播放结束/暂停时current_track 会变成null,但事实并非如此。我将编辑我的问题以显示我目前在哪里挣扎。谢谢!
    猜你喜欢
    • 2018-07-19
    • 2014-09-20
    • 2018-07-10
    • 2018-05-18
    • 1970-01-01
    • 2013-04-01
    • 2021-04-09
    • 2016-08-01
    • 2017-06-16
    相关资源
    最近更新 更多