Giter VIP home page Giter VIP logo

java-youtube-downloader's Introduction

java-youtube-downloader

Simple java parser for retrieving youtube video metadata.

Library is not stable, because Youtube often changes web structure of its pages. I don't use this library regularly to find the errors. Thats why errors are fixed as soon as someone finds it and opens an issue. Feel free to report an error or sumbit a PR.

WARNING: Youtube API does not support a video download. In fact, it is prohibited - Terms of Service - II. Prohibitions.
WARNING: Downloading videos may violate copyrights!

This project is only for educational purposes. I urge not to use this project to violate any laws.

Usage

Configuration

// init downloader with default config
YoutubeDownloader downloader = new YoutubeDownloader();
// or with custom config
Config config = new Config.Builder()
    .executorService(executorService) // for async requests, default Executors.newCachedThreadPool()
    .maxRetries(1) // retry on failure, default 0
    .header("Accept-language", "en-US,en;") // extra request header
    .proxy("192.168.0.1", 2005)
    .proxyCredentialsManager(proxyCredentials) // default ProxyCredentialsImpl
    .proxy("192.168.0.1", 2005, "login", "pass")
    .build();
YoutubeDownloader downloader = new YoutubeDownloader(config);

// or configure after init
Config config = downloader.getConfig();
config.setMaxRetries(0);

Request

// each request accepts optional params that will override global configuration
Request request = new Request(...)
        .maxRetries(...) 
        .proxy(...) 
        .header(...)
        .callback(...) // add callback for async processing
        .async(); // make request async

Response

Response<T> response = downloader.get...(request)

// get response status one of [downloading, completed, canceled, error]
ResponseStatus status = response.status();

// get reponse data 
// NOTE: will block current thread until completion if request is async        
T data = response.data(); 
// or get with timeout, may throw TimeoutException
T data = response.data(1, TimeUnit.SECONDS);

// cancel if request is async
boolean canceled = response.cancel();        

// get response error if request finished exceptionally
// NOTE: will block current thread until completion if request is async        
Throwable error = response.error();

// check if request finished successfully
// NOTE: will block current thread until completion if request is async        
boolean ok = response.ok();

VideoInfo

String videoId = "abc12345"; // for url https://www.youtube.com/watch?v=abc12345

// sync parsing
RequestVideoInfo request = new RequestVideoInfo(videoId);
Response<VideoInfo> response = downloader.getVideoInfo(request);
VideoInfo video = response.data();

// async parsing
RequestVideoInfo request = new RequestVideoInfo(videoId)
        .callback(new YoutubeCallback<VideoInfo>() {
            @Override
            public void onFinished(VideoInfo videoInfo) {
                System.out.println("Finished parsing");
            }
    
            @Override
            public void onError(Throwable throwable) {
                System.out.println("Error: " + throwable.getMessage());
            }
        })
        .async();
Response<VideoInfo> response = downloader.getVideoInfo(request);
VideoInfo video = response.data(); // will block thread

// video details
VideoDetails details = video.details();
System.out.println(details.title());
System.out.println(details.viewCount());
details.thumbnails().forEach(image -> System.out.println("Thumbnail: " + image));

// HLS url only for live videos and streams
if (video.details().isLive()) {
    System.out.println("Live Stream HLS URL: " + video.details().liveUrl());
}
        
// get videos formats only with audio
List<VideoWithAudioFormat> videoWithAudioFormats = video.videoWithAudioFormats();
videoWithAudioFormats.forEach(it -> {
    System.out.println(it.audioQuality() + ", " + it.videoQuality() + " : " + it.url());
});

// get all videos formats (may contain better quality but without audio) 
List<VideoFormat> videoFormats = video.videoFormats();
videoFormats.forEach(it -> {
    System.out.println(it.videoQuality() + " : " + it.url());
});

// get audio formats
List<AudioFormat> audioFormats = video.audioFormats();
audioFormats.forEach(it -> {
    System.out.println(it.audioQuality() + " : " + it.url());
});

// get best format
video.bestVideoWithAudioFormat();
video.bestVideoFormat();
video.bestAudioFormat();

// filtering formats
List<Format> formats = video.findFormats(new Filter<Format>() {
    @Override
    public boolean test(Format format) {
        return format.extension() == Extension.WEBM;
    }
});

// itags can be found here - https://gist.github.com/sidneys/7095afe4da4ae58694d128b1034e01e2
Format formatByItag = video.findFormatByItag(18); // return null if not found
if (formatByItag != null) {
    System.out.println(formatByItag.url());
}

Downloading video

File outputDir = new File("my_videos");
Format format = videoFormats.get(0);

// sync downloading
RequestVideoFileDownload request = new RequestVideoFileDownload(format)
    // optional params    
    .saveTo(outputDir) // by default "videos" directory
    .renameTo("video") // by default file name will be same as video title on youtube
    .overwriteIfExists(true); // if false and file with such name already exits sufix will be added video(1).mp4
Response<File> response = downloader.downloadVideoFile(request);
File data = response.data();

// async downloading with callback
RequestVideoFileDownload request = new RequestVideoFileDownload(format)
    .callback(new YoutubeProgressCallback<File>() {
        @Override
        public void onDownloading(int progress) {
            System.out.printf("Downloaded %d%%\n", progress);
        }
    
        @Override
        public void onFinished(File videoInfo) {
            System.out.println("Finished file: " + videoInfo);
        }
    
        @Override
        public void onError(Throwable throwable) {
            System.out.println("Error: " + throwable.getLocalizedMessage());
        }
    })
    .async();
Response<File> response = downloader.downloadVideoFile(request);
File data = response.data(); // will block current thread

// async downloading without callback
RequestVideoFileDownload request = new RequestVideoFileDownload(format).async();
Response<File> response = downloader.downloadVideoFile(request);
File data = response.data(20, TimeUnit.SECONDS); // will block current thread and may throw TimeoutExeption

// download in-memory to OutputStream
OutputStream os = new ByteArrayOutputStream();
RequestVideoStreamDownload request = new RequestVideoStreamDownload(format, os);
Response<Void> response = downloader.downloadVideoStream(request);

Subtitles

// you can get subtitles from video captions if you have already parsed video info
List<SubtitlesInfo> subtitlesInfo = video.subtitles(); // NOTE: includes auto-generated
// if you don't need video info, but just subtitles make this request instead
Response<List<SubtitlesInfo>> response = downloader.getSubtitlesInfo(new RequestSubtitlesInfo(videoId)); // NOTE: does not include auto-generated
List<SubtitlesInfo> subtitlesInfo = response.data();

for (SubtitlesInfo info : subtitles) {
    RequestSubtitlesDownload request = new RequestSubtitlesDownload(info)
            // optional
            .formatTo(Extension.JSON3)
            .translateTo("uk");
    // sync download
    Response<String> response = downloader.downloadSubtitle(request);
    String subtitlesString = response.data();

    // async download
    RequestSubtitlesDownload request = new RequestSubtitlesDownload(info)
            .callback(...) // optional
            .async();
    Response<String> response = downloader.downloadSubtitle(request);
    String subtitlesString = response.data(); // will block current thread

    // to download using external download manager
    String downloadUrl = request.getDownloadUrl();
}

Playlists

String playlistId = "abc12345"; // for url https://www.youtube.com/playlist?list=abc12345
RequestPlaylistInfo request = new RequestPlaylistInfo(playlistId);
Response<PlaylistInfo> response = downloader.getPlaylistInfo(request);
PlaylistInfo playlistInfo = response.data();

// playlist details
PlaylistDetails details = playlistInfo.details();
System.out.println(details.title());
System.out.println(details.videoCount());

// get video details
PlaylistVideoDetails videoDetails = playlistInfo.videos().get(0);
System.out.println(videoDetails.videoId());
System.out.println(videoDetails.title());
System.out.println(videoDetails.index());

Channel uploads

String channelId = "abc12345";  // for url https://www.youtube.com/channel/abc12345
// or 
String channelId = "someName";  // for url https://www.youtube.com/c/someName
RequestChannelUploads request = new RequestChannelUploads(channelId);
Response<PlaylistInfo> response = downloader.getChannelUploads(request);
PlaylistInfo playlistInfo = response.data();

Search

RequestSearchResult request = new RequestSearchResult("search query")
    // filters
    .type(TypeField.VIDEO)                 // Videos only
    .format(FormatField._3D,
        FormatField.HD)                    // 3D HD videos
    .match(FeatureField.SUBTITLES)         // with subtitles
    .during(DurationField.OVER_20_MINUTES) // more than 20 minutes videos
    .uploadedThis(UploadDateField.MONTH)   // uploaded this month

    // other parameters
    .forceExactQuery(true)                 // avoid auto correction
    .sortBy(SortField.VIEW_COUNT);         // results sorted by view count
// or
RequestSearchResult request = new RequestSearchResult("search query")
    .filter(
        TypeField.VIDEO,
        FormatField.HD,
        (...)
        UploadDateField.MONTH);

SearchResult result = downloader.search(request).data();

// retrieve next result (20 items max per continuation)
if (result.hasContinuation()) {
    RequestSearchContinuation nextRequest = new RequestSearchContinuation(result);
    SearchResult continuation = downloader.searchContinuation(nextRequest).data();
}

// a query is suggested, get its result
if (result.suggestion() != null) {
    System.out.println(result.suggestion().query()); // suggested query
    RequestSearchable suggestedRequest = new RequestSearchable(result.suggestion());
    SearchResult suggestedResult = downloader.search(suggestedRequest).data();
}

// query refinements
if (result.refinements() != null) {
    System.out.println(result.refinements().get(0).query()); // refinement query
    RequestSearchable refinedRequest = new RequestSearchable(result.refinements().get(0));
    SearchResult refinedResult = downloader.search(refinedRequest).data();
}

// the query has been auto corrected, force original query
if (result.isAutoCorrected()) {
	System.out.println(result.autoCorrectedQuery()); // corrected query
	SearchResult forcedResult = downloader.search(request.forceExactQuery(true)).data();    
}

// details
System.out.println(result.estimatedResults());

// items, 20 max per result (+ possible shelves on first result)
List<SearchResultItem> items = result.items();
List<SearchResultVideoDetails> videos = result.videos();
List<SearchResultChannelDetails> channels = result.channels();
List<SearchResultPlaylistDetails> playlists = result.playlists();
List<SearchResultShelf> shelves = result.shelves();

// item cast
SearchResultItem item = items.get(0);
switch (item.type()) {
case VIDEO:
    System.out.println(item.asVideo().description());
    break;
case SHELF:
    for (SearchResultVideoDetails video : item.asShelf().videos()) {
        System.out.println(video.author());
    }
    break;
(...)
}

// Base 64 (optional) : use another base 64 encoder for search parameters

// Classic JDK and Android API >= 26
Base64Encoder.setInstance(bytes -> Base64.getUrlEncoder().encodeToString(bytes));

// Android API < 26
Base64Encoder.setInstance(new Base64Encoder() {
    @Override
    public String encodeToString(byte[] bytes) {
        return Base64.encodeToString(bytes, Base64.URL_SAFE);
    }
};

Include

Maven

<repositories>
  <repository>
    <id>jitpack.io</id>
    <url>https://jitpack.io</url>
  </repository>
</repositories>
<dependency>
  <groupId>com.github.sealedtx</groupId>
  <artifactId>java-youtube-downloader</artifactId>
  <version>3.2.3</version>
</dependency>

Gradle

dependencyResolutionManagement {
	repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
	repositories {
		mavenCentral()
		maven { url 'https://jitpack.io' }
	}
}
dependencies {
  implementation 'com.github.sealedtx:java-youtube-downloader:3.2.3'
}

Android

android {
  ...
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
  // For Kotlin projects
  kotlinOptions {
    jvmTarget = "1.8"
  }
}

java-youtube-downloader's People

Contributors

dependabot[bot] avatar fabul00 avatar grodou avatar jamesvickers19 avatar josemaralves avatar kangslee avatar poornerd avatar sealedtx avatar sterta avatar tobias123567 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  avatar  avatar  avatar  avatar  avatar  avatar

java-youtube-downloader's Issues

java.lang.ClassNotFoundException: com.github.kiulian.downloader.YoutubeException

I have been battling with this error for a long time now. I am using maven with intellij ide ultimate

Caused by: java.lang.ClassNotFoundException: com.github.kiulian.downloader.YoutubeException
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1365)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)

Video quality options are missing

There's a video which is available in 1080p but I can only download it in 360p with this tool. How can I fix that and why is YouTube hiding the more high quality options?

No audio

Tested on mac (VLC 3.0.8 and QuickTime player 10.4), with the code on the README.md
No exceptions and file downloaded. When played, the video shows with no sound.

Below the console output:

Grace Jones - I've Seen That Face Before (12" Version)
1387648
Thumbnail: https://i.ytimg.com/vi/h02LY6KnyoI/hqdefault.jpg?sqp=-oaymwEYCKgBEF5IVfKriqkDCwgBFQAAiEIYAXAB&rs=AOn4CLArK7E-dP__1C2s3yF-GmYHsH_PlA
Thumbnail: https://i.ytimg.com/vi/h02LY6KnyoI/hqdefault.jpg?sqp=-oaymwEYCMQBEG5IVfKriqkDCwgBFQAAiEIYAXAB&rs=AOn4CLAY8U0h8RBIi6ZrEJGm-In1v475Iw
Thumbnail: https://i.ytimg.com/vi/h02LY6KnyoI/hqdefault.jpg?sqp=-oaymwEZCPYBEIoBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLB8ynUqF_-a0XPDXEJKgcJy2rERNw
Thumbnail: https://i.ytimg.com/vi/h02LY6KnyoI/hqdefault.jpg?sqp=-oaymwEZCNACELwBSFXyq4qpAwsIARUAAIhCGAFwAQ==&rs=AOn4CLCs8VR-o5o0Yt-rnn7fvOlyR71dXg
Thumbnail: https://i.ytimg.com/vi/h02LY6KnyoI/maxresdefault.jpg
hd720 : https://r2---sn-pf5t-1gie.googlevideo.com/videoplayback?expire=1580859402&ei=qqs5Xt-1MpadgAeqoamwBA&ip=212.25.6.70&id=o-ADvUdu2UF-f94EzyrXqk7hiZfBVUvdm_F-pQrsg5I8FG&itag=136&aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-pf5t-1gie%2Csn-1gieen7e&ms=au%2Crdu&mv=m&mvi=1&pcm2cms=yes&pl=19&initcwndbps=1586250&vprv=1&mime=video%2Fmp4&gir=yes&clen=1628635&dur=340.039&lmt=1539652670613484&mt=1580837698&fvip=4&keepalive=yes&fexp=23842630&c=WEB&txp=5432432&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHylml4wRQIgRMwiLBF-Q9aT3yavEdSYQNNeAkXcCV3VITBzUeH4g9YCIQDZ8CfYo09yFeWydpZ1D08a7ebYBDNXVUQE0TWcnlDNzw%3D%3D&sig=ALgxI2wwRAIgRFEv1dnZvwC_4UOjcTAG3p-Ty9QPLsAXVqzNHPBdhqECIFtxvzhBIRwzPoFHtADzu8Y80u3lb5xqOWz67siXpXL7
hd720 : https://r2---sn-pf5t-1gie.googlevideo.com/videoplayback?expire=1580859402&ei=qqs5Xt-1MpadgAeqoamwBA&ip=212.25.6.70&id=o-ADvUdu2UF-f94EzyrXqk7hiZfBVUvdm_F-pQrsg5I8FG&itag=247&aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-pf5t-1gie%2Csn-1gieen7e&ms=au%2Crdu&mv=m&mvi=1&pcm2cms=yes&pl=19&initcwndbps=1586250&vprv=1&mime=video%2Fwebm&gir=yes&clen=4534332&dur=340.039&lmt=1542445037508615&mt=1580837698&fvip=4&keepalive=yes&fexp=23842630&c=WEB&txp=5432432&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHylml4wRQIgRMwiLBF-Q9aT3yavEdSYQNNeAkXcCV3VITBzUeH4g9YCIQDZ8CfYo09yFeWydpZ1D08a7ebYBDNXVUQE0TWcnlDNzw%3D%3D&sig=ALgxI2wwRAIgfAv20l8lEpkcYRepmiGrikMWCJgl-ySHd1dZ0UrMmKwCIEiYyIdH5va2IvJHrrv8fwPpkZ-_qIeh7Gly5qUYWNuy
hd720 : https://r2---sn-pf5t-1gie.googlevideo.com/videoplayback?expire=1580859402&ei=qqs5Xt-1MpadgAeqoamwBA&ip=212.25.6.70&id=o-ADvUdu2UF-f94EzyrXqk7hiZfBVUvdm_F-pQrsg5I8FG&itag=398&aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-pf5t-1gie%2Csn-1gieen7e&ms=au%2Crdu&mv=m&mvi=1&pcm2cms=yes&pl=19&initcwndbps=1586250&vprv=1&mime=video%2Fmp4&gir=yes&clen=4479666&dur=340.039&lmt=1578200631696924&mt=1580837698&fvip=4&keepalive=yes&fexp=23842630&c=WEB&txp=5431432&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHylml4wRQIgRMwiLBF-Q9aT3yavEdSYQNNeAkXcCV3VITBzUeH4g9YCIQDZ8CfYo09yFeWydpZ1D08a7ebYBDNXVUQE0TWcnlDNzw%3D%3D&sig=ALgxI2wwRgIhAKgsH0oM1n9g73XL3XYaaxVz_YqBFeyQuKZ1INJ11lhOAiEA217V6hAexe4haPOh4Gy2eRGlnQN8ZPgF2yt0jGbzSS8=
https://r2---sn-pf5t-1gie.googlevideo.com/videoplayback?expire=1580859402&ei=qqs5Xt-1MpadgAeqoamwBA&ip=1.2.3.4&id=o-ADvUdu2UF-f94EzyrXqk7hiZfBVUvdm_F-pQrsg5I8FG&itag=136&aitags=133%2C134%2C135%2C136%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-pf5t-1gie%2Csn-1gieen7e&ms=au%2Crdu&mv=m&mvi=1&pcm2cms=yes&pl=19&initcwndbps=1586250&vprv=1&mime=video%2Fmp4&gir=yes&clen=1628635&dur=340.039&lmt=1539652670613484&mt=1580837698&fvip=4&keepalive=yes&fexp=23842630&c=WEB&txp=5432432&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpcm2cms%2Cpl%2Cinitcwndbps&lsig=AHylml4wRQIgRMwiLBF-Q9aT3yavEdSYQNNeAkXcCV3VITBzUeH4g9YCIQDZ8CfYo09yFeWydpZ1D08a7ebYBDNXVUQE0TWcnlDNzw%3D%3D&sig=ALgxI2wwRAIgRFEv1dnZvwC_4UOjcTAG3p-Ty9QPLsAXVqzNHPBdhqECIFtxvzhBIRwzPoFHtADzu8Y80u3lb5xqOWz67siXpXL7

Handbrake (https://handbrake.fr) report no audio track..

Notes

  1. Same issue on Windows
  2. The following maven dep is missing to run the unit test
 <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-commons</artifactId>
            <version>1.6.0</version>
 </dependency>

What are the Available Formats

Hello,

Thanks so much for this library.

i am stuck at this line.

Future future = video.downloadAsync(format, outputDir);

What are the available formats to pass in the constructor

How can I get the Stream URL

So if I do not want to download it, but watch it in the browser while being streamed (HLS), how can I get the right URL? Because if I use the videoWithAudioFormats.get(0).url() I get a URL which does not work with a 500 Internal Server Error.
However if I just download it, it works File file = video.download(videoWithAudioFormats.get(0), outputDir);.
Any tips here?

Fail on all videos

Hi bro, very nice work, i love it, at now fails in all videos:

W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.replace(java.lang.CharSequence, java.lang.CharSequence)' on a null object reference
W/System.err: at com.github.kiulian.downloader.model.formats.Format.(Format.java:55)
W/System.err: at com.github.kiulian.downloader.model.formats.AudioVideoFormat.(AudioVideoFormat.java:39)

Maby something related to Cypher ?

Question on extensions

I noticed that if there are multiple AudioFormats for audio download, not all formats get to a .m4a file, but some get to a .weba file.
Is there a way to avoid that?

Cannot load playlists

Hey there!

I'm currently experiencing an issue where I'm unable to get playlist-details, because apparently for some playlists (like OLAK5uy_kiTxC7OplYPiaW4EqzAdqmtguAY7s7f2g) the JSON element sidebar.playlistSidebarRenderer.items[1] does not exist (index 0 does exists though):

Caused by: java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:373)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at [email protected]/com.alibaba.fastjson.JSONArray.getJSONObject(JSONArray.java:241)
at [email protected]/com.github.kiulian.downloader.parser.DefaultParser.getPlaylistDetails(DefaultParser.java:217)
at [email protected]/com.github.kiulian.downloader.YoutubeDownloader.getPlaylist(YoutubeDownloader.java:87)
<my code...>

It's this part of the code that throws the exception (at DefaultParser#getPlaylistDetails(String, JSONObject):216):

JSONArray sideBarItems = initialData.getJSONObject("sidebar").getJSONObject("playlistSidebarRenderer").getJSONArray("items");
String author = sideBarItems.getJSONObject(1)
    <...>

Here's what I did: (this should be correct, right?)

YoutubePlaylist playlist = new YoutubeDownloader().getPlaylist("OLAK5uy_kiTxC7OplYPiaW4EqzAdqmtguAY7s7f2g");

It worked fine with the Bruce lee playlist (PLC3w7RzH8Yf9Zhgk43XX2w_HEDNptS-Ca) from the YoutubePlaylistTest.

Any idea what to do?

Downloaded Video has no sound

I have tried the exact code, as mentioned in README to test a download.
Regardless of the itag and link used, the Video has no sound in it.

is there any issue with that?

CipherException: Could not parse js function

Hello
I am using your api for +-2 weeks. This is really helpful, thank you a lot.
But i found some ytb id which generate this error :

com.github.kiulian.downloader.YoutubeException$CipherException: Could not parse js function
at com.github.kiulian.downloader.cipher.CachedCipherFactory.parseFunction(CachedCipherFactory.java:188)
at com.github.kiulian.downloader.cipher.CachedCipherFactory.getTransformFunctions(CachedCipherFactory.java:118)
at com.github.kiulian.downloader.cipher.CachedCipherFactory.createCipher(CachedCipherFactory.java:90)
at com.github.kiulian.downloader.parser.DefaultParser.parseFormat(DefaultParser.java:170)
at com.github.kiulian.downloader.parser.DefaultParser.parseFormats(DefaultParser.java:126)
at com.github.kiulian.downloader.YoutubeDownloader.getVideo(YoutubeDownloader.java:69)

Some links which do not work :
https://www.youtube.com/watch?v=Qe500eIK1oA
https://www.youtube.com/watch?v=RGwaDQURybk
https://www.youtube.com/watch?v=FvHHlKp923A

Maybe am i doing something wrong ? (i have release 2.2.2)

Thx for your help.

I am trying to implemet Coroutines With this Library , Need Help

how to make a call to function like: val video = ytDownloader?.getVideo(data.id),

As its been reporting as Inappropriate blocking method call, Even when Inside: withContext(Dispatchers.IO){}

So how to make this work asychronous...? even intellij is reporting Inappropriate blocking method call

Correct me if I am Wrong somewhere...,Thanks in Advance.

.formats()

.formats() always returns an empty list

Wrong key of the "cipher" field

Hello,

I am using currently your library to download videos(audio from video) from YouTube. It was working fine, before some time. Now, when I am trying to get audio formats by calling the function audioFormats on the instance of YouTubeVideo class, it returns null. I have dug into the problem and figured out the problem is in the DefaultParser. The function parseFormat checks whether given JSON object contains cipher keyword, if it is true, the parser retrieves it and then does necessary steps.
So, the problem is with the cipher field in the json. Now, this field is called signatureCipher.
I guess YouTube has changed a response structure again. By the way, I have created a custom parser and fix this error and it works fine. But, I prefer to use your default parser rather than creating my own, which is actually the same.

So, I hope you fix the issue as soon as possible:)

Is there Mp3 download support

Its possible to download audio formats , like m4a , but i am just wondering is there a way to download audio in mp3 file format ?
If not , is there any plan to implement that?

Can't make a working jar

I'm trying to use it in a personal project. I created a jar with your code but i can't make it work.

The same code works if i create a new class in your project, but if i use your project as a jar and i import that jar it doesn't.

This is the code that i'm using

String link = "NeQM1c-XCDc";
YoutubeDownloader youtubeDownloader = new YoutubeDownloader();
YoutubeVideo video = null;
File outputDir = new File(System.getProperty("user.home").concat("\Downloads\yt"));
outputDir.mkdir();
try {
video = youtubeDownloader.getVideo(link);
} catch (YoutubeException e) {
e.printStackTrace();
}
try {
assert video != null;
video.download(video.audioFormats().get(0),outputDir);
} catch (YoutubeException | IOException e) {
e.printStackTrace();
}

This is the exception
Exception in thread "main" java.lang.NoClassDefFoundError: com/alibaba/fastjson/JSON at com.github.kiulian.downloader.parser.DefaultParser.getPlayerConfig(DefaultParser.java:87) at com.github.kiulian.downloader.YoutubeDownloader.getVideo(YoutubeDownloader.java:69) at com.main.App.main(App.java:27) Caused by: java.lang.ClassNotFoundException: com.alibaba.fastjson.JSON at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ... 3 more

API 29 and above , File Save Doesnt Work!(Addition of Scoped Storage)

Probable Cause: "There was huge privacy change in android Q by introducing Scoped Storage."
In API level 29 direct access to shared/external storage devices is deprecated

.mkdirs() always return False!

Error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.shabinder.musicforeveryone, PID: 7005
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:915)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:915) 
Caused by: java.io.IOException: Could not create output directory: my_audios
at com.github.kiulian.downloader.model.Utils.createOutDir(Utils.java:22)
at com.github.kiulian.downloader.model.YoutubeVideo.download(YoutubeVideo.java:160)
at com.github.kiulian.downloader.model.YoutubeVideo.download(YoutubeVideo.java:153)
at com.github.kiulian.downloader.model.YoutubeVideo.download(YoutubeVideo.java:149)
at com.shabinder.musicForEveryone.fragments.MainFragment$onCreateView$3.onClick(MainFragment.kt:114)
at android.view.View.performClick(View.java:7259)
at android.view.View.performClickInternal(View.java:7236)
at android.view.View.access$3600(View.java:801)
at android.view.View$PerformClick.run(View.java:27896)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:915) 

output file naming bug

thank you for your program!

java.io.FileNotFoundException

com/github/kiulian/downloader/model/Utils.java

static File getOutputFile(final String name, Format format, File outDir, boolean overwrite) {
String fileName = removeIllegalChars(name) + "." + format.extension().value();
File outputFile = new File(outDir, fileName);

    if (!overwrite) {
        int i = 1;
        while (outputFile.exists()) {
            fileName = name + "(" + i++ + ")" + "." + format.extension().value();
            ===>> fileName = removeIllegalChars(name) + "(" + i++ + ")" + "." + format.extension().value();
            outputFile = new File(outDir, fileName);
        }
    }

    return outputFile;
}

Not working since 11/03/20 (Cannot get InputStream in DefaultExtractor.loadUrl)

Currently fails with the following StackTrace:
com.github.kiulian.downloader.YoutubeException$VideoUnavailableException: Could not load url: https://www.youtube.com/watch?v=y4jpzxZv5Zo at com.github.kiulian.downloader.extractor.DefaultExtractor.loadUrl(DefaultExtractor.java:97) at com.github.kiulian.downloader.parser.DefaultParser.getPlayerConfig(DefaultParser.java:66) at com.github.kiulian.downloader.YoutubeDownloader.getVideo(YoutubeDownloader.java:65)

Reproducible with (any video id):
new YoutubeDownloader().getVideo("y4jpzxZv5Zo");

Error to load url

com.github.kiulian.downloader.YoutubeException$VideoUnavailableException: Could not load url:

Check related to cipher in method parseFormat in DefaultParser should be changed to signatureCipher

Hi,

First of all I would like to appreciate the tremendous work which you have done here.
Now, I tried running the app on my local and found that in the method parseFormat(JSONObject json, JSONObject config) you have a check for "cipher" which should be replaced with "signatureCipher" imo. Do let me know if this is a valid bug.
Also, you you have anything in pipeline related to downloading videos from playlist. As of now, whenever I try to download something from playlist, it throws me an error.
I will try to contribute related to playlist if you dont have it in the pipeline. Happy to help

Thanks

Audio not downloading: Only video is being downloaded

When I download the video with findVideoWithQuality(VideoQuaity.large).. Only video downloaded.. Not Audio.

I have gone through every possible function but didn't find any clue.

What if I wanna download Specific video format with specific audio format.

Any help appreciated..

YoutubeException$VideoUnavailableException: Could not load url

It says that it can't load the URL and I don't know why. I checked the link is the video id is everything seems fine.

Error:
Exception in thread "main" com.github.kiulian.downloader.YoutubeException$VideoUnavailableException: Could not load url: https://www.youtube.com/watch?v=byUCOO2qm_A at com.github.kiulian.downloader.extractor.DefaultExtractor.loadUrl(DefaultExtractor.java:97) at com.github.kiulian.downloader.parser.DefaultParser.getPlayerConfig(DefaultParser.java:66) at com.github.kiulian.downloader.YoutubeDownloader.getVideo(YoutubeDownloader.java:65) at main.AnotherMAin.main(AnotherMAin.java:27)

Code:
`YoutubeDownloader downloader = new YoutubeDownloader();

    Scanner scanner = new Scanner(System.in);

    String videoId = scanner.nextLine().replace("https://www.youtube.com/watch?v=", "").replace("https://youtu.be/", "");

    System.out.println("videoId = " + videoId);
    YoutubeVideo video = downloader.getVideo(videoId); // LINE WITH ERROR
    List<AudioVideoFormat> videoWithAudioFormats = video.videoWithAudioFormats();
    videoWithAudioFormats.forEach(it -> {
        System.out.println(it.videoQuality() + " : " + it.url());
    });
    video.downloadAsync(videoWithAudioFormats.get(0), new File("D:\\Game Projects\\orihS Bot Project\\target\\classes\\songs\\ACertainMagicalIndexIII"), new OnYoutubeDownloadListener() {
        @Override
        public void onDownloading(int progress) {
            System.out.printf("Downloaded %d%%\n", progress);
        }

        @Override
        public void onFinished(File file) {
            System.out.println("Finished file: " + file);
            try {
                main(null);
            } catch (IOException | YoutubeException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onError(Throwable throwable) {
            System.out.println("Error: " + throwable.getLocalizedMessage());
        }
    });`

Could not extract js url: assets not found

Errors sometimes occur.
Please check the error below.

This error occurs with signature.
when I brought the html code, it did not include 'assets'.

test getVideo_WithSignature_Success()

com.github.kiulian.downloader.YoutubeException$BadPageException: Could not extract js url: assets not found
	at com.github.kiulian.downloader.parser.DefaultParser.getJsUrl(DefaultParser.java:93)
	at com.github.kiulian.downloader.parser.DefaultParser.parseFormat(DefaultParser.java:315)
	at com.github.kiulian.downloader.parser.DefaultParser.populateFormats(DefaultParser.java:274)
	at com.github.kiulian.downloader.parser.DefaultParser.parseFormats(DefaultParser.java:195)
	at com.github.kiulian.downloader.YoutubeDownloader.getVideo(YoutubeDownloader.java:73)
	at com.github.kiulian.downloader.YoutubeVideoExtractor_Tests.lambda$getVideo_WithSignature_Success$3(YoutubeVideoExtractor_Tests.java:81)
	at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:48)
	at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:35)
	at org.junit.jupiter.api.Assertions.assertDoesNotThrow(Assertions.java:1230)
	at com.github.kiulian.downloader.YoutubeVideoExtractor_Tests.getVideo_WithSignature_Success(YoutubeVideoExtractor_Tests.java:80)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:532)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:108)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)

org.opentest4j.AssertionFailedError: Unexpected exception thrown: org.opentest4j.AssertionFailedError

	at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:53)
	at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:35)
	at org.junit.jupiter.api.Assertions.assertDoesNotThrow(Assertions.java:1230)
	at com.github.kiulian.downloader.YoutubeVideoExtractor_Tests.getVideo_WithSignature_Success(YoutubeVideoExtractor_Tests.java:80)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:532)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:108)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: org.opentest4j.AssertionFailedError: formats should not be empty ==> expected: <false> but was: <true>
	at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:38)
	at org.junit.jupiter.api.AssertFalse.assertFalse(AssertFalse.java:40)
	at org.junit.jupiter.api.Assertions.assertFalse(Assertions.java:193)
	at com.github.kiulian.downloader.YoutubeVideoExtractor_Tests.lambda$getVideo_WithSignature_Success$3(YoutubeVideoExtractor_Tests.java:93)
	at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:48)
	... 42 more

FileNotFound issue

Hi guys,

Great library, but it looks like youtube is kinda trying to block you from downloading the urls. I implemented your library as said in the README. The library find the urls, but then downloading is impossible. Any idea what's causing this?

java.io.FileNotFoundException: https://r5---sn-5hnednlk.googlevideo.com/videoplayback?expire=1596592358&ei=hrwpX8X6F4mQ1wakjZjoCA&ip=87.214.227.252&id=o-ALCnNkQPbS3bLETiGP3fP3TUx33UzwdhivIvNJQ-VcdW&itag=136&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C248%2C278&source=yt_otf&requiressl=yes&mh=Ok&mm=31%2C26&mn=sn-5hnednlk%2Csn-4g5ednsz&ms=au%2Conr&mv=m&mvi=5&pl=17&initcwndbps=996250&vprv=1&mime=video%2Fmp4&otf=1&otfp=1&dur=0.000&lmt=1596550688211966&mt=1596570577&fvip=5&keepalive=yes&fexp=23883098&c=WEB&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cotf%2Cotfp%2Cdur%2Clmt&sig=AOq0QJ8wRQIhANCCSQFVdqRQNO-UbvO1Mek8LVPIzubuMIkcBbnr2KtrAiA_6qNJ5KdfX_dnR6X6eQBv5gm6faPxfBIzrluaFq8Odw%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhAIBnGSMkppK9b-AE2wxilE0Bm4r_CV2nhugXVcvtWjY0AiBJIH4PP2vhCUcOJVf8HMzfaNgIyhLSExFml9hVTs3hKg%3D%3D
Downloader.txt

Faster downloads

Hi,
Downloading a "regular" format (audio+video) is fast enough.
But for an "adaptive" format (video or audio only), the download starts, stops for seconds, then restarts, and so on.
To avoid this, it can be done part by part, using some extra parameters in each request:

  • range: first and last byte positions
  • part number: incremented at each request
  • client version: found in the initial data

Issue with non ASCII characters in video details if default charset is not utf-8

Hi,

With default Parser and default Extractor, the InputStreamReader that reads from HttpURLConnection inputstream uses default character encoding. In my case it was not a utf-8 what results in missing non ASCII characters in video details.

The simple solution is to explicitly specify the utf-8 charset:

BufferedReader in = new BufferedReader(new InputStreamReader(
                        connection.getInputStream(), StandardCharsets.UTF_8));

What I can also suggest is to use dependency injection to inject extractor in default parser, it would make life easier when man needs to alter just a default extractor and use derived version with default parser.

Issue with live streams

If video is live stream or already finished stream - video.videoWithAudioFormats() and video.videoFormats() are empty

CipherException: Transofrm object not found

Hi again bro !, today i have this error in some videos, this zr6HHU0fxOA for example:

com.github.kiulian.downloader.YoutubeException$CipherException: Transofrm object not found
at com.github.kiulian.downloader.cipher.CachedCipherFactory.getTransformObject(CachedCipherFactory.java:163)
at com.github.kiulian.downloader.cipher.CachedCipherFactory.getTransformFunctionsMap(CachedCipherFactory.java:142)
at com.github.kiulian.downloader.cipher.CachedCipherFactory.createCipher(CachedCipherFactory.java:93)

I hope you can help me, great job i love your work.

Thanks you very much.

Get video fragment of defined duration between two seconds/minutes

Have you considered a method to return a fragment of the video from a second to another second. So if the video has 15 min of duration, and I want only the fragment between the time from 1:30 min to 2:45 min, have a method to get this fragment instead of the whole video.

BadPageException: Could not parse player config json

Hello,

link of the video : https://www.youtube.com/watch?v=QUvVdTlA23w

When i try to parse the video, i have this error :
com.github.kiulian.downloader.YoutubeException$BadPageException: Could not parse player config json
at com.github.kiulian.downloader.parser.DefaultParser.getPlayerConfig(DefaultParser.java:72)
at com.github.kiulian.downloader.YoutubeDownloader.getVideo(YoutubeDownloader.java:65)

I don't know if there are others links which give this error.

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.