YouTube API v3获取播放列表中最新视频

4
一些基本背景:我协助运营一个在YouTube上的游戏频道,并正在使用PHP构建一个实用程序,将频道内容与伴随网站集成。我们的播放列表主要是按发布日期排序的“玩一玩”系列,按时间顺序通过各种游戏进行进度记录,我希望网站能够显示所选系列的“最新剧集”。
我知道可以通过链接以下调用来找到最后的视频:
$youtubeService->playlistItems->listPlaylistItems(
    "snippet",
    array(
        "playlistId"  =>  $playlistId
        "pageToken"   =>  $nextPageToken
    )
)

只需在 $nextPageToken 未设置时,简单地获取响应集中的最后一项即可。
然而,这让我感到非常低效--部分原因是我相信它会消耗我的 API 请求配额,但更多的原因是它会减慢整个站点的响应时间。这两种情况都不理想。
看起来应该有一种更容易的方法来获取播放列表中的“最新”视频,可以通过改变响应的顺序或使用一些便捷的函数来实现,但我找不到任何相关的文档。
我已经尝试使用搜索函数覆盖播放列表项,但是(根据文档),搜索仅接受频道 ID 作为参数,而不是播放列表 ID,这让我认为它是错误的方向。

是的,它绝对会消耗每日配额。 - aequalsb
3个回答

1
这里的简短回答是,在当前API版本下似乎不可能实现。没有明显的方法可以选择反向视频,但我进行了一些小改动,使整个过程更加高效。

这是原始代码:

$items = $youtube->playlistItems->listPlaylistItems(
    "snippet",
    array(
        "playlistId"    =>  $playlistId,
        "maxResults"    => 50
    )
);

while ($items->nextPageToken) {
    $items = $youtube->playlistItems->listPlaylistItems(
        "snippet",
        array(
            "playlistId"    =>  $playlistId,
            "maxResults"    =>  50,
            "pageToken" =>  $items->nextPageToken
        )
    );
}

if ($items) {
    return end($items->getItems());
}

这是修复方法:

首先,我添加了一个对象来帮助缓存:

class PlaylistCache {
    protected $expirationDate;
    protected $playlistId;
    protected $latestEpisode;

    __construct($playlistId, $latestEpisode) {
        $this-playlistId = $playlistId;
        $this->latestEpisode = $latestEpisode;

        $this->expirationDate = time() + 86400;
        // get current time + 24 hours
    }

    public function getLatestEpisode() {
        return $this->latestEpisode;
    }

    public function getPlaylistId() {
        return $this->playlistId;
    }

    public function isExpired() {
        return $this->expirationDate < time();
    }
}

在轮询API之前,我会查看是否有可用的缓存版本,只有在缓存版本过期时才会使用API。

$playlistCache = json_decode(get_option('playlist_cache_' . $playlistId));

if ($playlistCache->isExpired()) {

    $items = $youtube->playlistItems->listPlaylistItems(
        "id",
        array(
            "playlistId"    =>  $playlistId,
            "maxResults"    => 50
        )
    );

    while ($items->nextPageToken) {
        $items = $youtube->playlistItems->listPlaylistItems(
            "id",
            array(
                "playlistId"    =>  $playlistId,
                "maxResults"    =>  50,
                "pageToken" =>  $items->nextPageToken
            )
        );
    }

    if ($items) {
        $videoId = end($items->getItems()[0]->getId());
        $video = $youtube->videos->listVideos("snippet", array('id' => $videoId))
        $video = $video->getItems()[0];

        $playlistCache = new PlaylistCache($playlistId, $video);

        update_option('playlist_cache_' . $playlistId, json_encode($playlistCache)));
    }
}

return $playlistCache->getLatestEpisode();

这里的另一个重要变化是,我对listPlaylistItems()的调用请求id而不是snippet
根据文档snippet每个API配额的成本为2单位,而对id的请求为0。因此,我不需要在每个页面的每个项目上获取snippet。我只需要抓取结果中最后一个视频的snippet,这可以通过更精细的调用完成。
$youtube->videos->listVideos()

通过添加PlaylistCache类,我只有在缓存版本的播放列表返回true时,在$playlistCache->isExpired()调用上才会访问API,因此我每24小时只需要一次轮询整个播放列表,而不是为每个用户的每个页面加载1次。

尽管仍然不完美,但据我所知,这是目前可用的最佳选项。


感谢您提供正确的实现方案! - Android Enthusiast

0
首先,您需要通过HTTP请求获取用户的{{link1:channelId}}:

示例请求:

https://www.googleapis.com/youtube/v3/channels?part=snippet&forUsername={0}&key={1} 
  • 其中{0}是用户名,key是您的API密钥

然后,通过调用'PlaylistItems:list'获取视频列表,它返回与API请求参数匹配的播放列表项集合。您可以检索指定播放列表中的所有播放列表项,或通过其唯一ID检索一个或多个播放列表项。

示例请求:

https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId={0}&key={1}

从那里,您可以创建一个数组以获取播放列表中的最后一个视频。包括 max-results 参数,max-results 指定了结果集中包含的最大结果数。


这种方法的缺点是(根据文档),“max-results”参数最多只能支持50个结果。目前,这已经足够了,但我们有几个系列将超过此限制,仍需要多次调用来翻页浏览结果。 - Mike

-1
通常情况下,播放列表中最新的视频会被添加到前面而不是末尾。

正如我在问题中所述,我正在整合的播放列表是按发布日期排序的,因此这实际上是不准确的。我正在拉取我创建的播放列表,并且我知道视频的顺序。我希望从YT获得的响应与它们在频道上出现的相反顺序。 - Mike
嗯,Mike,我不知道还有什么可告诉你的了。你按照那种方式下达指令,所以API就会返回相应的结果。 - johnh10
这似乎是谷歌的短视行为。以这种方式排序的播放列表中获取“最新”的视频肯定不可能是一个罕见的需求。似乎应该存在某个“升序”/“降序”切换按钮。感谢反馈,但听起来回答我的问题令人失望,是一个令人沮丧的“否”。 - Mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接