Giter VIP home page Giter VIP logo

youtube-dl-android's Introduction

youtube-dl-android

Implementation of youtube-dl in Android/Java

It can download any video/audio on youtube except videos with age filter. (will be fixed soon) If it doesn't work for any link, please raise an Issue with the link.

Features

  • Download in any format supported
  • Downloads using the built-in downloader DownloadManager
  • History of queried URLs
  • Download anywhere you want

Credits

youtube dl
Storage Chooser

youtube-dl-android's People

Contributors

tastelessjolt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

youtube-dl-android's Issues

fix can't download bug

i cant push my code to your project
so i paste code to here
Extractor.java
`package me.harshithgoka.youtubedl;

import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

import com.google.code.regexp.Matcher;
import com.google.code.regexp.Pattern;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import me.harshithgoka.youtubedl.Utils.Arg;
import me.harshithgoka.youtubedl.Utils.Fun;

import static me.harshithgoka.youtubedl.Utils.Arg.VAL;

public class Extractor {

public String _VALID_URL = "(?x)^\n" +
        " (\n" +
        "     (?:https?://|//)                                    # http(s):// or protocol-independent URL\n" +
        "     (?:(?:(?:(?:\\w+\\.)?[yY][oO][uU][tT][uU][bB][eE](?:-nocookie)?\\.com/|\n" +
        "        (?:www\\.)?deturl\\.com/www\\.youtube\\.com/|\n" +
        "        (?:www\\.)?pwnyoutube\\.com/|\n" +
        "        (?:www\\.)?hooktube\\.com/|\n" +
        "        (?:www\\.)?yourepeat\\.com/|\n" +
        "        tube\\.majestyc\\.net/|\n" +
        "        youtube\\.googleapis\\.com/)                        # the various hostnames, with wildcard subdomains\n" +
        "     (?:.*?\\#/)?                                          # handle anchor (#/) redirect urls\n" +
        "     (?:                                                  # the various things that can precede the ID:\n" +
        "         (?:(?:v|embed|e)/(?!videoseries))                # v/ or embed/ or e/\n" +
        "         |(?:                                             # or the v= param in all its forms\n" +
        "             (?:(?:watch|movie)(?:_popup)?(?:\\.php)?/?)?  # preceding watch(_popup|.php) or nothing (like /?v=xxxx)\n" +
        "             (?:\\?|\\#!?)                                  # the params delimiter ? or # or #!\n" +
        "             (?:.*?[&;])??                                # any other preceding param (like /?s=tuff&v=xxxx or ?s=tuff&v=V36LpHqtcDY)\n" +
        "             v=\n" +
        "         )\n" +
        "     ))\n" +
        "     |(?:\n" +
        "        youtu\\.be|                                        # just youtu.be/xxxx\n" +
        "        vid\\.plus|                                        # or vid.plus/xxxx\n" +
        "        zwearz\\.com/watch|                                # or zwearz.com/watch/xxxx\n" +
        "     )/\n" +
        "     |(?:www\\.)?cleanvideosearch\\.com/media/action/yt/watch\\?videoId=\n" +
        "     )\n" +
        " )?                                                       # all until now is optional -> you can pass the naked ID\n" +
        " ([0-9A-Za-z_-]{11})                                      # here is it! the YouTube video ID\n" +
        " (?!.*?\\blist=\n" +
        "    (?:\n" +
        "        %(playlist_id)s|                                  # combined list/video URLs are handled by the playlist IE\n" +
        "        WL                                                # WL are handled by the watch later IE\n" +
        "    )\n" +
        " )\n" +
        "                                                 # if we found the ID, everything can follow\n" +
        " $";


private HashMap<Pair<String, String>, JSInterpreter> player_cache;
private HttpGetter httpGetter;


Extractor() {
    player_cache = new HashMap<>();
    httpGetter = new HttpGetter();
}



public JSInterpreter parseSigJs(String response) {
    // (r'(["\'])signature\1\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
    //        r'\.sig\|\|(?P<sig>[a-zA-Z0-9$]+)\('),

    JSInterpreter jsInterpreter = new JSInterpreter(response);
    return jsInterpreter;
}

String signatureCacheId (String sig) {
    StringBuilder stringBuilder = new StringBuilder();
    for (String s : sig.split("\\.")) {
        stringBuilder.append(s.length());
        stringBuilder.append(".");
    }
    stringBuilder.deleteCharAt(stringBuilder.length() - 1);
    return stringBuilder.toString();
}

public String extractSignatureFunction(String video_id, String player_url, String s) {
    Pair playerID = new Pair<String, String >(player_url, signatureCacheId(s));

    if (!player_cache.containsKey(playerID)) {
        Pattern playerUrl = Pattern.compile(".*?-(?<id>[a-zA-Z0-9_-]+)(?:/watch_as3|/html5player(?:-new)?|(?:/[a-z]{2}_[A-Z]{2})?/base)?\\.(?<ext>[a-z]+)$");

        Matcher matcher = playerUrl.matcher(player_url);
        if (!matcher.find())
            return null;

        String player_id = matcher.group(1);
        String player_type = matcher.group(2);

        try {
            String response = httpGetter.run(player_url);
            JSInterpreter jsInterpreter = parseSigJs(response);
            if (jsInterpreter == null)
                return null;

            Pattern funcNamePattern = Pattern.compile("([\"\\'])signature\\1\\s*,\\s*(?<sig>[a-zA-Z0-9$]+)\\(");
            Matcher m = funcNamePattern.matcher(response);

            String func_name;
            if (m.find())
                func_name = m.group(2);
            else {
                funcNamePattern = Pattern.compile("\\.sig\\|\\|(?<sig>[a-zA-Z0-9$]+)\\(");
                m = funcNamePattern.matcher(response);
                if (m.find())
                    func_name = m.group(2);
                else {
                    funcNamePattern = Pattern.compile("yt\\.akamaized\\.net/\\)\\s*\\|\\|\\s*.*?\\s*c\\s*&&\\s*d\\.set\\([^,]+\\s*,\\s*([a-zA-Z0-9$]+)\\(");
                    m = funcNamePattern.matcher(response) ;
                    if (m.find()){
                        func_name = m.group(1) ;
                    } else {
                        funcNamePattern = Pattern.compile("\\bc\\s*&&\\s*d\\.set\\([^,]+\\s*,\\s*([a-zA-Z0-9$]+)\\(") ;
                        m = funcNamePattern.matcher(response) ;
                        if (m.find()){
                            func_name = m.group(1) ;
                        } else {
                            return null ;
                        }
                    }
                }
            }



            if (!TextUtils.isEmpty(func_name)){
                Fun fun = jsInterpreter.extractFunction(func_name);
                jsInterpreter.setSigFun(fun);

                player_cache.put(playerID, jsInterpreter);
            } else {
                return null ;
            }

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    JSInterpreter jsi = player_cache.get(playerID);
    Arg arg = new Arg(s);
    try {
        Arg ret = jsi.callFunction(jsi.getSigFun(), new Arg[]{arg});
        return ret.getString(VAL);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

public String getSignatureCacheId (String s) {
    // in Python
    // return '.'.join(compat_str(len(part)) for part in example_sig.split('.'))
    StringBuilder stringBuilder = new StringBuilder();
    for (String part : s.split("\\.")) {
        stringBuilder.append(part.length() + ".");
    }
    stringBuilder.deleteCharAt(stringBuilder.length() - 1);
    return stringBuilder.toString();
}

public String decryptSignature(String s, String video_id, String player_url) {
    String TAG = "decryptSig";

    if (player_url == null)
        return null;

    if (player_url.startsWith("//"))
        player_url = "https:" + player_url;

    if (!player_url.matches("https?://"))
        player_url = "https://www.youtube.com/" + player_url;

    Pair<String, String> player_id = new Pair<> (player_url, getSignatureCacheId(s));


    String sig = extractSignatureFunction(video_id, player_url, s);

    Log.d(TAG + "enc", s);
    Log.d(TAG + "dec", sig);
    Log.d(TAG, video_id);
    Log.d(TAG, player_url);

    return sig;
}

public String getID (String url) {
    Pattern pattern = Pattern.compile(_VALID_URL);
    Matcher m = pattern.matcher(url);
    if (!m.find()) {
        Log.d("ERR", "Not a valid URL, couldn't get ID");
        Log.d("ERR", url);
    }
    return m.group(2);
}

public VideoInfo getFormats(String you_url) {
    String response;
    String video_id = "";
    String thumbnail_url = "";
    String length = "";
    String view_count = "";
    String author = "";
    JSONObject ret = new JSONObject();

    try {
        ret.put("status", false);
        response = httpGetter.run(you_url);
        Pattern ytconf = Pattern.compile("ytplayer.config[ =]*");
        Pattern ytcond_end = Pattern.compile(";[ ]*ytplayer\\.load");
        String json = ytcond_end.split(ytconf.split(response)[1])[0];
        JSONObject ytconfig = new JSONObject(json);
        ret.put("data", ytconfig);
        ret.put("status", true);

        JSONObject args = ytconfig.getJSONObject("args");
        String fmts = args.getString("url_encoded_fmt_stream_map") + "," + ytconfig.getJSONObject("args").getString("adaptive_fmts");
        String title = args.optString("title", "videoplayback");
        video_id = args.getString("video_id");
        length = args.getString("length_seconds");
        view_count = args.getString("view_count");
        author = args.getString("author");

        String[] fmts_enc = fmts.split(",");
        List<Format> formats = new ArrayList<>();

        for (String fmt : fmts_enc) {
            Format f = new Format(title);

            Map<String, String> query_pairs = new LinkedHashMap<String, String>();
            String[] pairs = fmt.split("&");
            for (String pair : pairs) {
                int idx = pair.indexOf("=");
                if (idx != -1 && idx < pair.length()){
                    query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
                }

            }

            String url = query_pairs.get("url");
            if (TextUtils.isEmpty(url)){
                continue ;
            }
            Set<String> params = query_pairs.keySet();
            if (params.contains("sig"))
                url += "&signature=" + query_pairs.get("sig");
            else if (params.contains("s")) {
                Pattern pattern = Pattern.compile("\"assets\":.+?\"js\":\\s*(\"[^\"]+\")");
                Matcher m = pattern.matcher(response);
                m.find();
                String player_url = m.group(1);
                player_url = new JSONObject("{ \"str\" :" + player_url + "}").getString("str");

                Pattern playerType = Pattern.compile("(html5player-([^/]+?)(?:/html5player(?:-new)?)?\\.js)|((?:www|player)-([^/]+)(?:/[a-z]{2}_[A-Z]{2})?/base\\.js)");
                m = playerType.matcher(player_url);
                if (!m.find()) {
                    Log.d("ERR", "Couldn't find Player URL");
                    Log.d("ERR", response);
                }

                String player_version = m.group();
                String player_desc = "html5 player " + player_version;
                String encrypted_signature = query_pairs.get("s");
                String videoID = getID(you_url);

                String decryptsig = decryptSignature(encrypted_signature, videoID, player_url);
                url += "&signature=" + decryptsig;

            }

            if (!url.contains("ratebypass")) {
                url += "&ratebypass=yes";
            }

            f.url = url;

            for (String param : params) {
                if (param.equals("itag")) {
                    f.setItag(Integer.parseInt(query_pairs.get(param)));
                }

                if (param.equals("type")) {
                    f.type = query_pairs.get(param);
                }

                if (param.equals("quality")) {
                    f.quality = query_pairs.get(param);
                }
            }

            formats.add(f);
        }

        VideoInfo videoInfo = new VideoInfo(video_id, title, length, view_count, author, thumbnail_url, formats);
        return videoInfo;

    } catch (IllegalStateException e) {
        try {
            ret.put("message", e.toString());
        } catch (JSONException e1) {
            e1.printStackTrace();
        }
        Log.d("Err", e.toString());
    } catch (IOException e) {
        try {
            ret.put("message", e.toString());
        } catch (JSONException e1) {
            e1.printStackTrace();
        }
        Log.d("Err", e.toString());
    } catch (JSONException e) {
        try {
            ret.put("message", e.toString());
        } catch (JSONException e1) {
            e1.printStackTrace();
        }

// e.printStackTrace();
}

    return null;
}

}
`

How do you build the URL?

Hello,

I'm digging around your code and trying to fully comprehend how it all works.

I'm particularly interested how do you build this URL:
https://r2---sn-apuoxu-30ol.googlevideo.com/videoplayback?itag=140&source=youtube&signature=D57B903AA9628708FE65C3A7B6DEBBC11C1615DC.240F806BFD2258385BBFA1D77BC2C8D60C1FCB82&clen=19589536&fvip=3&txp=5535432&initcwndbps=2080000&expire=1548800675&ei=Q35QXOfpDNHF7gONqICoCQ&key=yt6&keepalive=yes&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Ckeepalive%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Crequiressl%2Csource%2Cexpire&mm=31%2C29&ip=158.129.27.115&mn=sn-apuoxu-30ol%2Csn-4g5e6nez&ms=au%2Crdu&requiressl=yes&mt=1548778987&pl=18&mv=m&id=o-AFWCexAD0GwvgItXIVrkQzn2L6iuFPdftllpgyRR51ZP&dur=1210.386&mime=audio%2Fmp4&ipbits=0&gir=yes&c=WEB&lmt=1547401178781647&ratebypass=yes
Because I'm mostly interested in the downloading aspect I can't seem to generate it.

Can't Dismiss The Clipboard

So, I'm trying out to figure out the core methods and how to use them.

What I did is tried hardcoding the link like this:

    public void startPoint(View button) {
        //String url = urlEdit.getText().toString();
        String url = "https://www.youtube.com/watch?v=CQceqbA7kFI";
        startDownload(url);
    }

I added a different button that points to this method, but when I try to use it I get the error:
IllegalStateException: No successful match so far
Error connecting to the Internet

Complete doesn't work

Every time I open the app, it just opens Google. When I share a video from YT in Firefox it does the same thing

Sent from my TETRA using FastHub-Libre

Support for API 15 and higher

Hello. I following this project and this is magnificent approach for discarding server side. And this is my commit for supporting API 19 and higher.
LINK HERE

Can you help me for supporting API 15 and higher? I think you just need to use GSON instead of org.json.JSONObject. Actually i can't any way to remove element of jsonobject because this api doesn't support actually. This app is not support for API 15 because of only one command line. You can see here.

LINK HERE

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.io.File.getAbsolutePath()' on a null object reference

When clicking on any of the ways to download the video I get this error:

12-28 17:36:43.620 22533-22533/me.harshithgoka.youtubedl E/AndroidRuntime: FATAL EXCEPTION: main
Process: me.harshithgoka.youtubedl, PID: 22533
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.io.File.getAbsolutePath()' on a null object reference
at me.harshithgoka.youtubedl.Activities.MainActivity.download(MainActivity.java:525)
at me.harshithgoka.youtubedl.Adapters.FormatAdapter$MyViewHolder.onClick(FormatAdapter.kt:51)
at android.view.View.performClick(View.java:5184)
at android.view.View$PerformClick.run(View.java:20893)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5938)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)

increase versionCode/versionName

The latest release (v0.12) still shows versionCode 1 and versionName 1.0 โ€“ which makes it hard to update (as Android considers it to be the same version as all before). Would you consider increasing it with each release? It must just be higher. So it would eg. be fine to use versionCode:12 and versionName:0.12 or simply increase versionCode by 1 with each new release, and put the real version number into versionName.

Doesn't work

I can paste a link, then a loading animation comes up briefly, but nothing more.
When I want to open the settings, I get a notification with "Coming soon", so I can't customize anything there either.

app crashes in google play

i shared an app using this library in google play but when install app in play it crashes and cant intiatialize how can i fix it anyone can help me

All links seem to have stopped working

All links that I tried recently stopped working.
It could be related to some change in youtube, because youtube-dl also stopped working until they updated it.

Details on code workings ?

It would be nice if you put comments on codes so we can understand how it is working and further we can help to add other sites ( which as you told your not going to add them soon to your project)
But many including me is waiting for the support of additional sites such as Hotstar Sony and other streaming sites.
Youtube-dl ofc have these but for compatibility, this would be great.
Waiting for your reply.

when i use api?

Configuration for Prefered Quality and Auto download
I wanna the method

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.