From 545808fd973483d0f43c735c0bc7aee3d9ddcd5b Mon Sep 17 00:00:00 2001 From: Hexah Date: Fri, 6 Mar 2020 23:18:33 +0100 Subject: [PATCH] Add DownloadExtension --- CHANGELOG.md | 6 ++++- README.md | 13 ++++++++--- example/video_download.dart | 15 +++++------- lib/src/extensions/download_extension.dart | 27 ++++++++++++++++++++++ lib/src/extensions/extensions.dart | 1 + pubspec.yaml | 2 +- 6 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 lib/src/extensions/download_extension.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a296bb..611a4ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,4 +42,8 @@ ## 0.0.10 - Bug fix: Don't throw when captions are not present. -- New extension: CaptionListExtension adding `getByTime` function. \ No newline at end of file +- New extension: CaptionListExtension adding `getByTime` function. + +## 0.0.11 + +- New extension: DownloadExtension adding `downloadStream` function. \ No newline at end of file diff --git a/README.md b/README.md index fdc5eb8..2d97f75 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ This doesn't require an API key and has no usage quotas. - Provides static methods to validate IDs and to parse IDs from URLs - No need for an API key and no usage quotas - All model extend `Equatable` to easily perform equality checks +- Download Stream ## Features not implemented - Adaptive streams -- Download streams functions. ## Differences from YoutubeExplode @@ -103,13 +103,20 @@ You need to close `YoutubeExplode`'s http client when done otherwise this could yt.close(); ``` + +# Examples: + +Available on [GitHub][Examples] + --- + Check the [api doc][API] for additional information. -More features are provided thru extensions. +More features are provided through extensions. [YoutubeExplode]: https://github.com/Tyrrrz/YoutubeExplode/ [Video]: https://pub.dev/documentation/youtube_explode_dart/latest/youtube_explode/Video-class.html [MediaStreamsInfoSet]: https://pub.dev/documentation/youtube_explode_dart/latest/youtube_explode/MediaStreamInfoSet-class.html [VidExample]: https://github.com/Hexer10/youtube_explode_dart/blob/master/example/video_download.dart -[API]: https://pub.dev/documentation/youtube_explode_dart/latest/youtube_explode/youtube_explode-library.html \ No newline at end of file +[API]: https://pub.dev/documentation/youtube_explode_dart/latest/youtube_explode/youtube_explode-library.html +[Examples][https://github.com/Hexer10/youtube_explode_dart/tree/master/example] \ No newline at end of file diff --git a/example/video_download.dart b/example/video_download.dart index e7bcbe3..6a8ba54 100644 --- a/example/video_download.dart +++ b/example/video_download.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:dart_console/dart_console.dart'; import 'package:youtube_explode_dart/youtube_explode_dart.dart'; -import 'package:http/http.dart' as http; // Initialize the YoutubeExplode instance. final yt = YoutubeExplode(); @@ -12,7 +11,7 @@ final console = Console(); Future main() async { console.writeLine('Type the video id or url: '); - + var url = stdin.readLineSync().trim(); // Get the video url. @@ -56,14 +55,12 @@ Future download(String id) async { var file = File('downloads/$fileName'); // Create the StreamedRequest to track the download status. - var req = http.Request('get', audio.url); - var resp = await req.send(); // Open the file in appendMode. var output = file.openWrite(mode: FileMode.writeOnlyAppend); // Track the file download status. - var len = resp.contentLength; + var len = audio.size; var count = 0; var oldProgress = -1; @@ -75,7 +72,7 @@ Future download(String id) async { console.write(msg); // Listen for data received. - return resp.stream.listen((data) { + await for (var data in audio.downloadStream()) { count += data.length; var progress = ((count / len) * 100).round(); if (progress != oldProgress) { @@ -84,7 +81,7 @@ Future download(String id) async { oldProgress = progress; } output.add(data); - }, onDone: () async { - await output.close(); - }).asFuture(); + } + console.writeLine(); + await output.close(); } diff --git a/lib/src/extensions/download_extension.dart b/lib/src/extensions/download_extension.dart new file mode 100644 index 0000000..6d5fcd8 --- /dev/null +++ b/lib/src/extensions/download_extension.dart @@ -0,0 +1,27 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:http/http.dart' as http; + +import '../models/models.dart'; + +/// Download extension for [MediaStreamInfo] +extension DownloadExtension on MediaStreamInfo { + static final _rateBypassExp = RegExp('ratebypass[=/]yes'); + + /// Returns the stream of this media stream object. + /// The download is split in multiple requests using the `range` parameter. + /// + Stream> downloadStream() async* { + var maxSize = _rateBypassExp.hasMatch(url.toString()) ? 9898989 : size + 1; + var total = 0; + + for (var i = 1; total < size; i++) { + var req = http.Request('get', url); + req.headers[HttpHeaders.rangeHeader] = 'bytes=$total-${total + maxSize}'; + var resp = await req.send(); + yield* resp.stream; + total += maxSize + 1; + } + } +} diff --git a/lib/src/extensions/extensions.dart b/lib/src/extensions/extensions.dart index 2094623..149f2ad 100644 --- a/lib/src/extensions/extensions.dart +++ b/lib/src/extensions/extensions.dart @@ -1,5 +1,6 @@ export 'caption_extension.dart'; export 'channel_extension.dart'; +export 'download_extension.dart'; export 'helpers_extension.dart'; export 'playlist_extension.dart'; export 'search_extension.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index fe330ce..37e2cbc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: youtube_explode_dart description: A port in dart of the youtube explode library. Support serveral API functions. -version: 0.0.10 +version: 0.0.11 homepage: https://github.com/Hexer10/youtube_explode_dart environment: