How can I get the actual video URL of a YouTube live stream?
Asked Answered
W

4

49

Is there a way to get the HLS URL for YouTube live streams like this one https://www.youtube.com/embed/WVZpCdHq3Qg

I've tried the typical get_video_info methods but they don't seem to work with live streams.

Wolverhampton answered 24/2, 2016 at 17:13 Comment(0)
J
78

You need to get the HLS m3u8 playlist files from the video's manifest. There are ways to do this by hand, but for simplicity I'll be using the youtube-dl tool to get this information. I'll be using this live stream as an example: https://www.youtube.com/watch?v=_Gtc-GtLlTk

First, get the formats of the video:

➜  ~ 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

In this case, there are two videos because the live stream contains two cameras. From here, we need to get the HLS URL for a specific stream. Use -f to pass in the format you would like to watch, and -g to get that stream's 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

These are your HLS m3u8 playlists, one for each camera associated with the live stream.

Without youtube-dl, your flow might look like this:

Take your video id and make a GET request to the get_video_info endpoint:

HTTP GET: https://www.youtube.com/get_video_info?&video_id=_Gtc-GtLlTk&el=info&ps=default&eurl=&gl=US&hl=en

In the response, the hlsvp value will be the link to the m3u8 HLS playlist:

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
Judie answered 25/2, 2016 at 15:6 Comment(8)
@mpgn I understand how you feel, but realistically it's impossible to go after everyone breaking YouTube's TOS. I've been there. Especially on mobile, look at the number of people who use tools like XCDYouTubeKit. Even YouTube won't go after you if your break their TOS if you build something useful. In the context of this question, for personal use I have no qualms providing this answer.Judie
@Judie thank you for the information, but how do I go about getting those values without that tool? I'm trying to do this programmatically from Java. I am using this code but it doesn't seem to work github.com/freecode/YouTube-Downloader/blob/master/src/…Wolverhampton
@mntgoat You can look at the youtube-dl source code and try to translate that into Java. I've edited my answer to provide an overview of the web requests required to get the m3u8 URL.Judie
@mpgn if i can get to the bits they are mineCw
Hey! I run that stream! dickpritchettrealestate.com/eagle-feed.html.Langrage
thanks SIR, struggling from 2 days. Now I have a working script written in java that download video from any site.Vizierate
stackoverflow is too much power trip, too little resource. thanks JAL for answering a legitimate question! I'm shocked I found decent information here for a change; it's always Topic Police, or strange code over-the-top code done in the most convoluted manner. The Topic Police have leaked onto IRC, too, which is even worse, since it's pretty much real-time communication (oh no there's physical latency let's argue semantics)Axenic
By using youtube-dl, the result url start with manifest.googlevideo.com/api/manifest**hls_playlist**/ and from hlsvp start with manifest.googlevideo.com/api/manifest**hls_variant**/ . Both url is working. If I am using hlsvp, shall I worry about the quality issue?Foolproof
T
12

This URL return to player actual video_id

https://www.youtube.com/embed/live_stream?channel=UCkA21M22vGK9GtAvq3DvSlA

Where UCkA21M22vGK9GtAvq3DvSlA is your channel id. You can find it inside YouTube account on "My Channel" link.

or here https://www.youtube.com/account_advanced

Trina answered 24/9, 2017 at 21:10 Comment(0)
T
4

Yes this is possible Since the question is update, this solution can only gives you the embed url not the HLS url, check @JAL answer. with the ressource search.list and the parameters:

* part: id
* channelId: UCURGpU4lj3dat246rysrWsw
* eventType: live
* type: video

Request :

GET https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCURGpU4lj3dat246rysrWsw&eventType=live&type=video&key={YOUR_API_KEY}

Result:

 "items": [
  {
   "kind": "youtube#searchResult",
   "etag": "\"DsOZ7qVJA4mxdTxZeNzis6uE6ck/enc3-yCp8APGcoiU_KH-mSKr4Yo\"",
   "id": {
    "kind": "youtube#video",
    "videoId": "WVZpCdHq3Qg"
   }
  },

Then get the videoID value WVZpCdHq3Qg for example and add the value to this url:

https://www.youtube.com/embed/ + videoID
https://www.youtube.com/watch?v= + videoID
Tamas answered 24/2, 2016 at 22:31 Comment(7)
Thanks for the reply but I'm sure I understand. I want the get the actual video url, not the embed url. With videos that are not live streams I can get the actual mp4 url.Wolverhampton
That is the webpage for watching the video, I want the video address, the actual video, not the page.Wolverhampton
download videos when you are not the owner is prohibited by YouTube You shall not copy, reproduce, distribute, transmit, broadcast, display, sell, license, or otherwise exploit any Content for any other purposes without the prior written consent of YouTube or the respective licensors of the Content.Tamas
but i feel like @Judie answer the questionTamas
@Tamas "or the respective licensors of the Content." is the key part in that paste. You can get consent from either YouTube or the person doing the stream. Both are doable.Tannie
@Tamas he might not reproduce, distribute, transmit, broadcast, display, sell, license or otherwise exploit any Content for any other purposes. He might just download it for his private collection and watch from time to time when he has no internet connection.Suborder
does "download copy" is equivalent to "reproduce" ?Tamas
F
2

For those who: want to see a live streaming video from youtube in your exoplanet in android then do this: https://exoplayer.dev/hls.html

Read the above documentation and create the ExoPlayer in android studio.

Careful: To get HLS Url from youtube live videos link: Example of live URL: https://youtu.be/21X5lGlDOfg . A common mistake in copying URL: https://www.youtube.com/watch?v=FdQA-pE2luQ. You can see that the second one is a link to a video that can be live but still a video. It's not HLS.

USAGE: Just call convertLinkToHls() instead of initializing player, because we called initializePlayer() inside it.

Here we call the GET request:

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);
    }

Here we extract the link from the GET response:


    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;
    }

Here we initialize Exo player for HLS streaming:

    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();
    }

You can also show the progress bar until we extract the link, it usually takes 300 milliseconds. This code works in java and android. As I have used the traditional way of getting requests and threads for background tasks.

What If the link is already an m3u8? Then without any changes, we will link to the player, hence it works for youtube live videos and any other m3u8 links.

What is the concept behind this? I am calling a get request using the live video URL and in response to ~400KB of StringBuffer, I extract the tag hlsManifestUrl from it. There is no rocketScience.

Fabulist answered 7/6, 2021 at 6:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.