3

I am trying to play a YouTube video in my application. Everything works fine. However, when I try to watch a video that contains content from Vevo, it fails.

I had also tried to pass el=vevo in get_video_info:

http://www.youtube.com/get_video_info?video_id=uuZE_IRwLNI&el=vevo&ps=default&eurl=&gl=US&hl=en

stream

 {
    "fallback_host" = "tc.v12.cache7.googlevideo.com";
    itag = 22;
    quality = hd720;
    s = "8E6E5D13EB65FB653B173B94CB0BCC3A20853F5EDE8.5E2E87DF33EEDE165FEA90109D3C7D5DADA06B6BB60";
    type = "video/mp4; codecs=\"avc1.64001F, mp4a.40.2\"";
    url = "http://r7---sn-cvh7zn7r.googlevideo.com/videoplayback?pcm2fr=yes&sver=3&expire=1393773646&itag=22&id=bae644fc84702cd2&upn=SjZd81MudQs&sparams=gcr%2Cid%2Cip%2Cipbits%2Citag%2Cpcm2fr%2Cratebypass%2Csource%2Cupn%2Cexpire&ms=au&gcr=in&mt=1393747698&source=youtube&ratebypass=yes&ipbits=0&fexp=935620%2C919120%2C912523%2C932288%2C914084%2C916626%2C937417%2C937416%2C913434%2C932289%2C936910%2C936913%2C902907&mv=m&key=yt5&ip=103.250.162.79";
}

When I use url its not playing. Is there any solution?

nrubin29
  • 1,522
  • 5
  • 25
  • 53
Sunny Shah
  • 12,990
  • 9
  • 50
  • 86

3 Answers3

7

get_video_info works only for the videos which are allowed to be viewed as embedded videos in other websites. I struggled a lot with get_video_info but could find any solution for vevo. however I was able to make it work by retrieving the actual video page, in actual video page you have to grab player version and hit url (specified in code) to grab the streams links and actual signatures.

youtube might change this in future but today following solutions is working great for me.

Its c# you should know how to convert it into object-C, entry point of following code is ExtractUrls function and remember to pass it html of video page.

e.g. html content of http://www.youtube.com/watch?v=J5iS3tULXMQ&nomobile=1

private static List<string> ExtractUrls(string html)
{
    string Player_Version = Regex.Match(html, @"""\\/\\/s.ytimg.com\\/yts\\/jsbin\\/html5player-(.+?)\.js""").Groups[1].ToString();
    string Player_Code = new WebClient().DownloadString("http://s.ytimg.com/yts/jsbin/" + "html5player-" + Player_Version + ".js");

    html = Uri.UnescapeDataString( Regex.Match(html, @"""url_encoded_fmt_stream_map"":\s+""(.+?)""", RegexOptions.Singleline).Groups[1].ToString());

    var Streams = Regex.Matches(html, @"(^url=|(\\u0026url=|,url=))(.+?)(\\u0026|,|$)");
    var Signatures = Regex.Matches(html, @"(^s=|(\\u0026s=|,s=))(.+?)(\\u0026|,|$)");
    List<string> urls = new List<string>();

    for (int i = 0; i < Streams.Count - 1; i++)
    {
        string URL = Streams[i].Groups[3].ToString();
        if (Signatures.Count > 0)
        {
            string Sign = Sign_Decipher(Signatures[i].Groups[3].ToString(), Player_Code);
            URL += "&signature=" + Sign;
        }
        urls.Add(URL.Trim());
    }

    return urls;
}

public static string Sign_Decipher(string s, string Code)
{
    string Function_Name = Regex.Match(Code, @"signature=(\w+)\(\w+\)").Groups[1].ToString();
    var Function_Match = Regex.Match(Code, "function " + Function_Name + @"\((\w+)\)\{(.+?)\}",RegexOptions.Singleline);
    string Var = Function_Match.Groups[1].ToString();
    string Decipher = Function_Match.Groups[2].ToString();
    var Lines = Decipher.Split(';');

    for (int i = 0; i < Lines.Length; i++)
    {
        string Line = Lines[i].Trim();
        if (Regex.IsMatch(Line, Var + "=" + Var + @"\.reverse\(\)"))
        {
            char[] charArray = s.ToCharArray();
            Array.Reverse(charArray);
            s = new string(charArray);
        }
        else if (Regex.IsMatch(Line, Var + "=" + Var + @"\.slice\(\d+\)"))
        {
            s = Slice(s, Convert.ToInt32(Regex.Match(Line, Var + "=" + Var + @"\.slice\((\d+)\)").Groups[1].ToString()));
        }
        else if (Regex.IsMatch(Line, Var + @"=\w+\(" + Var + @",\d+\)"))
        {
            s = Swap(s, Convert.ToInt32(Regex.Match(Line, Var + @"=\w+\(" + Var + @",(\d+)\)").Groups[1].ToString()));
        }
        else if (Regex.IsMatch(Line, Var + @"\[0\]=" + Var + @"\[\d+%" + Var + @"\.length\]"))
        {
            s = Swap(s, Convert.ToInt32(Regex.Match(Line, Var + @"\[0\]=" + Var + @"\[(\d+)%" + Var + @"\.length\]").Groups[1].ToString()));
        }
    }

    return s;
}

private static string Slice(string Input, int Length)
{
    return Input.Substring(Length, Input.Length - 1);
}

private static string Swap(string Input, int Position)
{
    var Str = new StringBuilder(Input);
    var SwapChar = Str[Position];
    Str[Position] = Str[0];
    Str[0] = SwapChar;
    return Str.ToString();
}

credit goes to comments under this code project artical

Mubashar
  • 12,300
  • 11
  • 66
  • 95
  • Great answer, I was able to set up a Xamarin project in 30 minutes. Anyways the code does not work for every YouTube video like Vevo videos, that will not be downloaded. – loretoparisi Sep 19 '14 at 22:50
  • 1
    Thanks. Yeah youtube made some changes last month, my app also stopped working for some videos, if you find some workaround please share, I am stuck in something else :( – Mubashar Sep 21 '14 at 01:34
  • Well the only guess I have is the need to handle signature, but it's very complicated matter: Read here https://github.com/0xced/XCDYouTubeKit/issues/11 – loretoparisi Sep 22 '14 at 20:57
2

Certain videos have a domain-level whitelist or blacklist applied to them. This is done at the discretion of the content owner.

If there is a whitelist or a blacklist, and the domain of the embedding site can't be determined (perhaps because of there not being a real referring domain in the case of your native application), then the default behavior is to block playback.

This blog post has a bit more detail as well: http://apiblog.youtube.com/2011/12/understanding-playback-restrictions.html

That specific video can only be played when it's embedded on a real website with a real referring URL, due to the way domain white/blacklisting works. And, we don't expose those lists via the API. It's a longstanding feature request

Boggarapu
  • 333
  • 2
  • 7
  • 15
1

YouTube video URL should contain a signature (which is included in the 's' field), to use this url, you need to decrypt the signature first and add it to the URL.

The signature decryptor can be found on the web page of the video (i.e. youtube.com/watch?v=VIDEO_ID).

I can't provide more info as it would be against YouTube terms of service :).

MuhammadBassio
  • 1,590
  • 10
  • 13
  • hey i had tried a lot but not able to success how can i decrypt the signature. if you know anythink then please help me – Sunny Shah Mar 03 '14 at 16:47
  • 2
    Sure I know how to decrypt it, but I don't want to share it as I would be violating YouTube terms of service. The only hint I can say is that the decryptor can be found in a JavaScript, a link to this JavaScript can be found when browsing the page source, hope this could help. – MuhammadBassio Mar 03 '14 at 20:56