获取 Java 中 YouTube 播放列表的所有视频
Get all videos of a YouTube Playlist in Java
Context 我正在使用 Android Studio (Java)。我想获取给定播放列表的所有视频(或50个,我将在之后获取所有其他视频)。
问题 我看到有人使用 url 喜欢
https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLiEwZfNgb4fVrRzTonlVEMj6DB2Nmzg2M&key=AIzaSyC2_YRcTE9916fsmA0_KRnef43GbLzz8m0
但我不知道如何在 Java 中实现它。我遵循了一些 tuto,我得到了一种获取完全不同信息的方法,例如:
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" : "Invalid field selection videoId",
"reason" : "invalidParameter"
} ],
"message" : "Invalid field selection videoId"
}
编辑 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());
id/videoId
不存在。
有一个 id
和一个 snippet/resourceId/videoId
。
所以我猜你的 setfields 不对。
我知道这是一个老问题,但重要的是要确定我们使用哪些资源来了解如何获取正确的信息。 YouTube API v3 中有很多资源,但我们通常使用 search
、video
、playlist
和 playlistItems
.
根据文档,以下 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
。但首先重要的是要知道我们将如何定义资源的 PARTS 和 FIELDS。
要定义部分,我们使用此代码:
YouTube.PlaylistItems.List list = youtube.playlistItems().list("snippet");
在上一行中,"snippet"
标识了包含多个字段(或子属性)的 属性,包括 title
、description
、position
,和 resourceId
,所以当我们设置 "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
吗? -嗯,答案是YES/NO。 -为什么这样?来吧 Teo,JSON 结构显示得很清楚。 -是的,我可以看到,但是文档说:
If the snippet.resourceId.kind
property's value is youtube#video
, then this property will be present and its value will contain the ID that YouTube uses to uniquely identify the video in the playlist.
这意味着有时可能无法使用。 -那么,我们如何才能得到videoId
呢? -好吧,我们可以将 id
或 contentDetails
添加到 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)");
希望对大家有所帮助。
Context 我正在使用 Android Studio (Java)。我想获取给定播放列表的所有视频(或50个,我将在之后获取所有其他视频)。
问题 我看到有人使用 url 喜欢
https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLiEwZfNgb4fVrRzTonlVEMj6DB2Nmzg2M&key=AIzaSyC2_YRcTE9916fsmA0_KRnef43GbLzz8m0
但我不知道如何在 Java 中实现它。我遵循了一些 tuto,我得到了一种获取完全不同信息的方法,例如:
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" : "Invalid field selection videoId",
"reason" : "invalidParameter"
} ],
"message" : "Invalid field selection videoId"
}
编辑 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());
id/videoId
不存在。
有一个 id
和一个 snippet/resourceId/videoId
。
所以我猜你的 setfields 不对。
我知道这是一个老问题,但重要的是要确定我们使用哪些资源来了解如何获取正确的信息。 YouTube API v3 中有很多资源,但我们通常使用 search
、video
、playlist
和 playlistItems
.
根据文档,以下 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
。但首先重要的是要知道我们将如何定义资源的 PARTS 和 FIELDS。
要定义部分,我们使用此代码:
YouTube.PlaylistItems.List list = youtube.playlistItems().list("snippet");
在上一行中,"snippet"
标识了包含多个字段(或子属性)的 属性,包括 title
、description
、position
,和 resourceId
,所以当我们设置 "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
吗? -嗯,答案是YES/NO。 -为什么这样?来吧 Teo,JSON 结构显示得很清楚。 -是的,我可以看到,但是文档说:
If the
snippet.resourceId.kind
property's value isyoutube#video
, then this property will be present and its value will contain the ID that YouTube uses to uniquely identify the video in the playlist.
这意味着有时可能无法使用。 -那么,我们如何才能得到videoId
呢? -好吧,我们可以将 id
或 contentDetails
添加到 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)");
希望对大家有所帮助。