有没有办法获取像这样的YouTube直播流的HLS URL https://www.youtube.com/embed/WVZpCdHq3Qg
我已经尝试了典型的get_video_info方法,但它们似乎不适用于直播。
您需要从视频清单中获取 HLS m3u8 播放列表文件。 有一些方法可以手动完成此操作,但为简单起见,我将使用 youtube-dl 工具来获取此信息。 我将以这个直播为例:https://www.youtube.com/watch?v=_Gtc-GtLlTk
首先,获取视频的格式:
➜ ~ youtube-dl --list-formats https://www.youtube.com/watch?v=_Gtc-GtLlTk
[youtube] _Gtc-GtLlTk: Downloading webpage
[youtube] _Gtc-GtLlTk: Downloading video info webpage
[youtube] Downloading multifeed video (_Gtc-GtLlTk, aflWCT1tYL0) - add --no-playlist to just download video _Gtc-GtLlTk
[download] Downloading playlist: Southwest Florida Eagle Cam
[youtube] playlist Southwest Florida Eagle Cam: Collected 2 video ids (downloading 2 of them)
[download] Downloading video 1 of 2
[youtube] _Gtc-GtLlTk: Downloading webpage
[youtube] _Gtc-GtLlTk: Downloading video info webpage
[youtube] _Gtc-GtLlTk: Extracting video information
[youtube] _Gtc-GtLlTk: Downloading formats manifest
[youtube] _Gtc-GtLlTk: Downloading DASH manifest
[info] Available formats for _Gtc-GtLlTk:
format code extension resolution note
140 m4a audio only DASH audio 144k , m4a_dash container, mp4a.40.2@128k (48000Hz)
160 mp4 256x144 DASH video 124k , avc1.42c00b, 30fps, video only
133 mp4 426x240 DASH video 258k , avc1.4d4015, 30fps, video only
134 mp4 640x360 DASH video 646k , avc1.4d401e, 30fps, video only
135 mp4 854x480 DASH video 1171k , avc1.4d401f, 30fps, video only
136 mp4 1280x720 DASH video 2326k , avc1.4d401f, 30fps, video only
137 mp4 1920x1080 DASH video 4347k , avc1.640028, 30fps, video only
151 mp4 72p HLS , h264, aac @ 24k
132 mp4 240p HLS , h264, aac @ 48k
92 mp4 240p HLS , h264, aac @ 48k
93 mp4 360p HLS , h264, aac @128k
94 mp4 480p HLS , h264, aac @128k
95 mp4 720p HLS , h264, aac @256k
96 mp4 1080p HLS , h264, aac @256k (best)
[download] Downloading video 2 of 2
[youtube] aflWCT1tYL0: Downloading webpage
[youtube] aflWCT1tYL0: Downloading video info webpage
[youtube] aflWCT1tYL0: Extracting video information
[youtube] aflWCT1tYL0: Downloading formats manifest
[youtube] aflWCT1tYL0: Downloading DASH manifest
[info] Available formats for aflWCT1tYL0:
format code extension resolution note
140 m4a audio only DASH audio 144k , m4a_dash container, mp4a.40.2@128k (48000Hz)
160 mp4 256x144 DASH video 124k , avc1.42c00b, 30fps, video only
133 mp4 426x240 DASH video 258k , avc1.4d4015, 30fps, video only
134 mp4 640x360 DASH video 646k , avc1.4d401e, 30fps, video only
135 mp4 854x480 DASH video 1171k , avc1.4d401f, 30fps, video only
136 mp4 1280x720 DASH video 2326k , avc1.4d401f, 30fps, video only
151 mp4 72p HLS , h264, aac @ 24k
132 mp4 240p HLS , h264, aac @ 48k
92 mp4 240p HLS , h264, aac @ 48k
93 mp4 360p HLS , h264, aac @128k
94 mp4 480p HLS , h264, aac @128k
95 mp4 720p HLS , h264, aac @256k (best)
[download] Finished downloading playlist: Southwest Florida Eagle Cam
在这种情况下,有两个视频,因为实时流包含两个摄像头。 从这里,我们需要获取特定流的 HLS URL。 使用 -f
传入您想要观看的格式,-g
获取该流的 URL:
➜ ~ youtube-dl -f 95 -g https://www.youtube.com/watch?v=_Gtc-GtLlTk
https://manifest.googlevideo.com/api/manifest/hls_playlist/id/_Gtc-GtLlTk.2/itag/95/source/yt_live_broadcast/requiressl/yes/ratebypass/yes/live/1/cmbypass/yes/gir/yes/dg_shard/X0d0Yy1HdExsVGsuMg.95/hls_chunk_host/r1---sn-ab5l6ne6.googlevideo.com/playlist_type/LIVE/gcr/us/pmbypass/yes/mm/32/mn/sn-ab5l6ne6/ms/lv/mv/m/pl/20/dover/3/sver/3/fexp/9408495,9410706,9416126,9418581,9420452,9422596,9422780,9423059,9423661,9423662,9425349,9425959,9426661,9426720,9427325,9428422,9429306/upn/xmL7zNht848/mt/1456412649/ip/64.125.177.124/ipbits/0/expire/1456434315/sparams/ip,ipbits,expire,id,itag,source,requiressl,ratebypass,live,cmbypass,gir,dg_shard,hls_chunk_host,playlist_type,gcr,pmbypass,mm,mn,ms,mv,pl/signature/7E48A727654105FF82E158154FCBA7569D52521B.1FA117183C664F00B7508DDB81274644F520C27F/key/dg_yt0/playlist/index.m3u8
https://manifest.googlevideo.com/api/manifest/hls_playlist/id/aflWCT1tYL0.2/itag/95/source/yt_live_broadcast/requiressl/yes/ratebypass/yes/live/1/cmbypass/yes/gir/yes/dg_shard/YWZsV0NUMXRZTDAuMg.95/hls_chunk_host/r13---sn-ab5l6n7y.googlevideo.com/pmbypass/yes/playlist_type/LIVE/gcr/us/mm/32/mn/sn-ab5l6n7y/ms/lv/mv/m/pl/20/dover/3/sver/3/upn/vdBkD9lrq8Q/fexp/9408495,9410706,9416126,9418581,9420452,9422596,9422780,9423059,9423661,9423662,9425349,9425959,9426661,9426720,9427325,9428422,9429306/mt/1456412649/ip/64.125.177.124/ipbits/0/expire/1456434316/sparams/ip,ipbits,expire,id,itag,source,requiressl,ratebypass,live,cmbypass,gir,dg_shard,hls_chunk_host,pmbypass,playlist_type,gcr,mm,mn,ms,mv,pl/signature/4E83CD2DB23C2331CE349CE9AFE806C8293A01ED.880FD2E253FAC8FA56FAA304C78BD1D62F9D22B4/key/dg_yt0/playlist/index.m3u8
这些是您的 HLS m3u8 播放列表,每个与直播流关联的摄像机一个。
如果没有 youtube-dl,您的流程可能如下所示:
获取您的视频 ID 并向get_video_info
端点发出 GET 请求:
HTTP GET: https://www.youtube.com/get_video_info?&video_id=_Gtc-GtLlTk&el=info&ps=default&eurl=&gl=US&hl=en
在响应中,hlsvp
值将是指向 m3u8 HLS 播放列表的链接:
https://manifest.googlevideo.com/api/manifest/hls_variant/maudio/1/ipbits/0/key/yt6/ip/64.125.177.124/gcr/us/source/yt_live_broadcast/upn/BYS1YGuQtYI/id/_Gtc-GtLlTk.2/fexp/9416126%2C9416984%2C9417367%2C9420452%2C9422596%2C9423039%2C9423661%2C9423662%2C9423923%2C9425346%2C9427672%2C9428946%2C9429162/sparams/gcr%2Cid%2Cip%2Cipbits%2Citag%2Cmaudio%2Cplaylist_type%2Cpmbypass%2Csource%2Cexpire/sver/3/expire/1456449859/pmbypass/yes/playlist_type/LIVE/itag/0/signature/1E6874232CCAC397B601051699A03DC5A32F66D9.1CABCD9BFC87A2A886A29B86CF877077DD1AEEAA/file/index.m3u8
此 URL 返回玩家实际video_id
https://www.youtube.com/embed/live_stream?channel=UCkA21M22vGK9GtAvq3DvSlA
其中UCkA21M22vGK9GtAvq3DvSlA是您的通道ID。您可以在YouTube帐户的"我的频道"链接中找到它。
或者在这里 https://www.youtube.com/account_advanced
search.list
和参数:
* part: id
* channelId: UCURGpU4lj3dat246rysrWsw
* eventType: live
* type: video
请求:
GET https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCURGpU4lj3dat246rysrWsw&eventType=live&type=video&key={YOUR_API_KEY}
结果:
"items": [
{
"kind": "youtube#searchResult",
"etag": ""DsOZ7qVJA4mxdTxZeNzis6uE6ck/enc3-yCp8APGcoiU_KH-mSKr4Yo"",
"id": {
"kind": "youtube#video",
"videoId": "WVZpCdHq3Qg"
}
},
然后获取videoID
值 WVZpCdHq3Qg 例如,并将值添加到此 url:
https://www.youtube.com/embed/ + videoID
https://www.youtube.com/watch?v= + videoID
For those who:
想在Android的系外行星上观看来自YouTube的实时流媒体视频,然后这样做:https://exoplayer.dev/hls.html
阅读上述文档并在 android studio 中创建 ExoPlayer。
Careful:
要从YouTube直播视频链接获取HLS URL:实际网址示例:https://youtu.be/21X5lGlDOfg.复制 URL 时的一个常见错误:https://www.youtube.com/watch?v=FdQA-pE2luQ。您可以看到第二个是指向视频的链接,该视频可以是实时的,但仍然是视频。它不是HLS。
USAGE:
只需调用convertLinkToHls()
而不是初始化播放器,因为我们在其中调用了initializePlayer()
。
这里我们调用 GET 请求:
void convertLinkToHls(String youtubeLiveLink) {
final String[] hlsLink = {""};
Runnable runnableCode = () -> {
try {
URL url = new URL(youtubeLiveLink);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
if(youtubeLiveLink.contains("m3u8")){
hlsLink[0] = youtubeLiveLink;
}else{
hlsLink[0] = extractHlsUrl(content.toString());
}
con.disconnect();
} catch (Exception e) {
hlsLink[0] = youtubeLiveLink;
e.printStackTrace();
Log.d("TAG", "convertLinkToHls: " +
": Reason is that the link is not a live url," +
"copy the link by open video then right click, copy video url from youtube.");
}
//extractHlsUrl(response);
};
Thread requestThread = new Thread(runnableCode);
requestThread.start();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if (!requestThread.isAlive()) {
// hlsLink[0]
runOnUiThread(() -> {
et_url.setText(hlsLink[0]);
initializePlayer();
});
timer.cancel();
/* Here initialize the player,
* make you do it in runOnUiTHread() */
}
}
}, 1000, 1000);
}
在这里,我们从GET响应中提取链接:
private static String extractHlsUrl(String response) {
String keyName = "hlsManifestUrl";
if (response.contains(keyName)) {
int index = response.indexOf(keyName);
index = index + 17;
int lastIndex = index;
while (lastIndex < response.length()) {
if ((response.charAt(lastIndex) == '8') &&
(response.charAt(lastIndex - 1) == 'u') &&
(response.charAt(lastIndex - 2) == '3') &&
(response.charAt(lastIndex - 3) == 'm')) {
break;
}
lastIndex++;
}
return response.substring(index, lastIndex + 1);
}
return null;
}
在这里,我们为HLS流媒体初始化Exo播放器:
private void initializePlayer() {
player = new SimpleExoPlayer.Builder(this)
.build();
playerView.setPlayer(player);
String tempUrl = et_url.getText().toString();
// Create a data source factory.
DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory();
// Create a HLS media source pointing to a playlist uri.
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(tempUrl));
player.setMediaSource(hlsMediaSource);
player.setPlayWhenReady(playWhenReady);
player.seekTo(currentWindow, playbackPosition);
player.prepare();
player.play();
}
您还可以显示进度条,直到我们提取链接,通常需要 300 毫秒。这段代码适用于Java和Android。因为我使用了获取后台任务的请求和线程的传统方式。
如果链接已经是 m3u8 怎么办?然后,无需任何更改,我们将链接到播放器,因此它适用于 youtube 直播视频和任何其他 m3u8 链接。
这背后的概念是什么?我正在使用实时视频URL调用get请求,并响应~400KB的StringBuffer,我从中提取标签hlsManifestUrl。没有火箭科学。