7

I'm working on a music APP that displays lyrics and info about songs and also plays songs from a youtube URL.

In my activity, there are some TextViews (for the lyrics/info) and one VideoView (for the youtube link).

I've created a class called YoutubeVideo, that does the following:

  1. Downloads the content of this page: http://gdata.youtube.com/feeds/api/videos?q=SONG_NAME&v=2&max-results=1, parses it's content and gets the youtube's id (e.g EvuL5jyCHOw). This is a RSS feeds page that searches for videos and display 1 result (And all I need to do is to change the query).
  2. Downloads the content of this page: http://gdata.youtube.com/feeds/api/videos?q=YOUTUBES_ID&format=1&alt=json, parses it's content and gets the rtsp (e.g rtsp://v7.cache3...3gp). This is an XML file that holds some information about the video (name, length, thumbnail and of course - rtsp link :).
  3. Than all I need to do is to set the rtsp as VideoURI: VideoView.setVideoURI(Uri.parse(rtsp)) and the video is being played.

If you wonder, I use this class like that: new YoutubeVideo(VideoView).setVideo(artist + " " + title);

It works, but I got one problem: It's a 3gp file... Which has really bad quality. How can I get better quality urls? (mp4/flv/ect?)

eviabs
  • 621
  • 1
  • 8
  • 24
  • did u find out solution for your issue. could u throw an eye over [this query](http://stackoverflow.com/questions/14156411/loading-youtube-video-through-i-frame-in-android-webview) – edwin Jan 07 '13 at 12:06
  • I was thinking about another approach: The html code of the flash object contains all of the HQ videos urls. That's why programs like IDM and some greasemonkey scripts let you download the HQ videos. You can look at this: http://userscripts.org/scripts/review/25105. It's a javascript code that extracts the HQ urls. You can read this and understand how to extract the HQ links yourself and also let the user chose the format! By this, You can use a videoview instead of webview. I didn't do that yet, so I don't have the java code for that :/ – eviabs Jan 12 '13 at 00:54

2 Answers2

9

I managed to write a function that gets a youtube video html code (the html source code) and returns an array with all of the available video links. Then I select a hight quality link, and display it instead of the poor 3gp.

It's not perfect, and there may be some bugs and improvments to make:

    protected String[] extractLinks(String result) {
    //The title of the downloaded file
    String title = "bla bla bla";
    // An array of strings that will hold the links (in case of error, it will hold 1 string)
    String[] temper = new String[1];

    try{
        // Extract the "url_encoded_fmt_stream_map" attr from the flash object
        Pattern p = Pattern.compile("url_encoded_fmt_stream_map(.*?);");          
        Matcher m = p.matcher(result);
        List<String> matches = new ArrayList<String>();
        while(m.find()){
            matches.add(m.group().replace("url_encoded_fmt_stream_map=", "").replace(";", ""));                   
        }
        String[] streamMap = null;
        List<String> links = new ArrayList<String>();

        if(matches.get(0) != null &&  matches.get(0) != ""){
            // Split the "url_encoded_fmt_stream_map" into an array of strings that hold the link values
            streamMap = matches.get(0).split("%2C");
            for (int i = 0; i < streamMap.length; i++){
                String url = "";
                String sig = "";

                //Using regex, we will get the video url.
                Pattern p2 = Pattern.compile("url%3D(.*?)%26");       
                Matcher m2 = p2.matcher(streamMap[i]);
                List<String> matches2 = new ArrayList<String>();
                while(m2.find()){
                    // We don't need the "url=...&" part.
                    matches2.add(m2.group().substring(6, m2.group().length() - 3));
                }                     
                url = matches2.get(0);   

                //Using regex again, we will get the video signature.               
                p2 = Pattern.compile("sig%3D(.*?)%26");       
                m2 = p2.matcher(streamMap[i]);
                matches2 = new ArrayList<String>();
                while(m2.find()){
                // We don't need the "sig=...&" part.               
                    matches2.add(m2.group().substring(6, m2.group().length() - 3));
                }                     
                sig = matches2.get(0);   

                //Now lets add a link to our list. Link = url + sig + title.
                links.add(URLDecoder.decode(URLDecoder.decode(url + "&signature=", "UTF-8") + sig + "%26title%3D" + URLDecoder.decode(title, "UTF-8"), "UTF-8"));
            }
        }
        else{
        links.add("No download Links");
        }
        //Now lets make temper point to a array that holds the list items (aka links).
        temper = links.toArray(new String[links.size()]);
    }
    catch(Exception ex){
    temper[0] = ex.getMessage();
    }
    // That's it! temper has direct download links from youtube!
    return temper;
}
eviabs
  • 621
  • 1
  • 8
  • 24
  • 1
    What in the world is result? – Chris Sprague Feb 27 '15 at 23:29
  • Sorry for the unclear code, it was just for a quick demonstration. Anyway, the result parameter is a string that holds the js code for the flash object. It Looks like this: "" You can extract this tag from the page source. – eviabs Mar 01 '15 at 11:52
  • No worries about clarity...I can usually figure it out but neither the direct youtube link or rtsp filepath worked. Does your method get the highquality filepath or the low quality 3gp? If high quality, could you update your code here so that the full example is visible? Thanks much. – Chris Sprague Mar 01 '15 at 15:05
  • This method gets a youtube source page and using regex, it extracts all of the available qualities for the video. Here is an example of a link that youtube uses today: http://jpst.it/x1HZ In the past 2 years, the flash object (and the download links as well) has been changed. It now has some new parameters, which make this code outdated. This code can still be used, but needs to be changed according to the new parameters. Also, as far as I know rtsp provides only 3gp format, which is very bad. ATM I don't have time to change the code and I no longer hold the complete project. Sorry :/ – eviabs Mar 01 '15 at 23:06
1

I strongly recommend you to use Official YouTube Api.

Please download the example zip file at link and see FullscreenDemoActivity.java file. That implemented most of you wanted. just click and show embedded YouTube video in high quality, full screen toggle, and automatically-show-fullscreen-when-rotation.

Youngjae
  • 24,352
  • 18
  • 113
  • 198