Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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

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 :).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top