在Java中获取YouTube播放列表中的所有视频

3

背景 我正在使用Android Studio(Java)开发。我想获取给定播放列表中的所有视频(或前50个,之后再获取其他视频)。

问题 我看到有人使用像下面这样的URL: https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLiEwZfNgb4fVrRzTonlVEMj6DB2Nmzg2M&key=YOUR_API_KEY 但我不知道如何在Java中实现这个功能。我按照一些教程操作,得到了完全不同的获取信息的方法,例如:

YouTube.Search.List query;
query = youtube.search().list("id,snippet");
      query.setKey(MY_API_KEY);
      query.setMaxResults((long)20);
      query.setType("video");
      query.setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url)");

我真的不明白除了搜索之外该如何得到其他东西。大部分文档只有英文...

编辑 好吧,我继续尝试,我认为我已经得到了一个接近解决方案,但出现了错误。

private YouTube youtube;
private YouTube.PlaylistItems.List playlistItemRequest;
private String PLAYLIST_ID = "PLiEwZfNgb4fVrRzTonlVEMj6DB2Nmzg2M";
public static final String KEY = "AIzaSyC2_YRcTE9916fsmA0_KRnef43GbLzz8m0";

// Constructor
public YoutubeConnector(Context context)
{
    youtube = new YouTube.Builder(new NetHttpTransport(),
            new JacksonFactory(), new HttpRequestInitializer()
    {
        @Override
        public void initialize(HttpRequest hr) throws IOException {}
    }).setApplicationName(context.getString(R.string.app_name)).build();
}

public List<VideoItem> result()
{
    List<PlaylistItem> playlistItemList = new ArrayList<PlaylistItem>();
    try
    {
    /* HERE MUST BE MY PROBLEM ! */
        playlistItemRequest = youtube.playlistItems().list("snippet");
        playlistItemRequest.setPlaylistId(PLAYLIST_ID);
        playlistItemRequest.setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url),nextPageToken,pageInfo");
        playlistItemRequest.setKey(KEY);
        String nextToken = "";
        do {
            playlistItemRequest.setPageToken(nextToken);
            PlaylistItemListResponse playlistItemResult = playlistItemRequest.execute();

            playlistItemList.addAll(playlistItemResult.getItems());

            nextToken = playlistItemResult.getNextPageToken();
        } while (nextToken != null);
    }catch(IOException e)
    {
        Log.d("YC", "Could not initialize: "+e);
    }
//[...]
}

这是我得到的错误: { "code" : 400, "errors" : [ { "domain" : "global", "location" : "fields", "locationType" : "parameter", "message" : "视频ID字段选择无效", "reason" : "invalidParameter" } ], "message" : "视频ID字段选择无效" } 编辑2 感谢Martijn Woudstra。 正确的行是:
playlistItemRequest = youtube.playlistItems().list("snippet,contentDetails");
//[...]
playlistItemRequest.setFields("items(snippet/title,snippet/description,snippet/thumbnails/default/url,contentDetails/videoId),nextPageToken,pageInfo");
//[...]
videoItem.setId(item.getContentDetails().getVideoId());

我回答了你的问题,希望你会找到它有用。 - Teocci
2个回答

3
我知道这是一个老问题,但重要的是要确定我们使用哪些资源来了解如何获取正确的信息。在YouTube API v3中有许多资源,但我们通常使用搜索、视频、播放列表和播放列表项。
根据文档,以下JSON结构显示了“playlistItems”资源的格式:
{
  "kind": "youtube#playlistItem",
  "etag": etag,
  "id": string,
  "snippet": {
    "publishedAt": datetime,
    "channelId": string,
    "title": string,
    "description": string,
    "thumbnails": {
      (key): {
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      }
    },
    "channelTitle": string,
    "playlistId": string,
    "position": unsigned integer,
    "resourceId": {
      "kind": string,
      "videoId": string,
    }
  },
  "contentDetails": {
    "videoId": string,
    "startAt": string,
    "endAt": string,
    "note": string,
    "videoPublishedAt": datetime
  },
  "status": {
    "privacyStatus": string
  }
}

从这个结构中,我们可以推测有三种方法可以获取videoId。但首先要知道如何定义资源的PARTSFIELDS是很重要的。
为了定义PARTS,我们使用以下代码:
YouTube.PlaylistItems.List list = youtube.playlistItems().list("snippet");

在前一行中,"snippet" 表示一个包含多个字段(或子属性)的属性,包括 titledescriptionpositionresourceId,所以当我们设置 "snippet" 时,API 的响应将包含所有这些子属性。
现在,如果我们定义 FIELDS,也可以限制前面的属性。例如,在这段代码中:
list.setFields("items(id/videoId,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

如果我们调用list.execute(),它会显示一个错误,因为我们没有在PARTS属性中定义id。此外,根据JSON结构,id是一个字符串,不包含videoId作为子属性。啊!但是我们可以从resourceId中提取videoId吗? -嗯,答案是是/否。 -为什么?来吧,Teo,JSON结构清楚地表明了这一点。 -是的,我能看到,但是文档说:

如果snippet.resourceId.kind属性的值是youtube#video,那么该属性将存在,并且其值将包含YouTube用于在播放列表中唯一标识视频的ID。

这意味着有时可能不可用。 -那么,我们如何获取videoId?-嗯,我们可以将idcontentDetails添加到PARTS资源中。如果我们添加id,则定义字段如下:
YouTube.PlaylistItems.List list = youtube.playlistItems().list("id,snippet");
list.setFields("items(id,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

如果我们添加contentDetails,则定义字段如下:
YouTube.PlaylistItems.List list = youtube.playlistItems()
    .list("snippet,contentDetails");
list.setFields("items(contentDetails/videoId,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

我希望这能帮助大家。


2

id/videoId 不存在。 存在一个 id 和一个 snippet/resourceId/videoId。 所以我猜测你的 setfields 不正确。


我不知道为什么网站和代码中的层次结构不一样,但是我是item/ContentDetails/VideoId。你的评论对我很有帮助,谢谢。 - Marco

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