Version 1.7.0 - Better captions
This commit is contained in:
parent
9c514ceadc
commit
26c0780991
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,7 +1,10 @@
|
||||||
## 1.x.x - WIP
|
|
||||||
- Implement `getSrt` a video closed captions in srt format.
|
## 1.7.0
|
||||||
- Only throw custom exceptions from the library.
|
- BREAKING CHANGES: `ClosedCaptionManifest.getByLanguage` now returns a List.
|
||||||
- `getUploadsFromPage` no longer throws.
|
- New Enum-Like class: `ClosedCaptionFormat`, which holds all the available YouTube subtiles format.
|
||||||
|
- `ClosedCaptionManifest.getByLanguage` now has a parameter named `format`.
|
||||||
|
- `ClosedCaptionClient.getManifest` now has a parameter named `autoGenerated`
|
||||||
|
- Fix: #82, #83
|
||||||
|
|
||||||
## 1.6.2
|
## 1.6.2
|
||||||
- Bug fixes: #80
|
- Bug fixes: #80
|
||||||
|
|
|
@ -30,10 +30,10 @@ Future<void> download(String id) async {
|
||||||
|
|
||||||
// Get the video manifest.
|
// Get the video manifest.
|
||||||
var manifest = await yt.videos.streamsClient.getManifest(id);
|
var manifest = await yt.videos.streamsClient.getManifest(id);
|
||||||
var streams = manifest.audioOnly;
|
var streams = manifest.videoOnly;
|
||||||
|
|
||||||
// Get the audio track with the highest bitrate.
|
// Get the audio track with the highest bitrate.
|
||||||
var audio = streams.withHighestBitrate();
|
var audio = streams.first;
|
||||||
var audioStream = yt.videos.streamsClient.get(audio);
|
var audioStream = yt.videos.streamsClient.get(audio);
|
||||||
|
|
||||||
// Compose the file name removing the unallowed characters in windows.
|
// Compose the file name removing the unallowed characters in windows.
|
||||||
|
|
|
@ -92,7 +92,7 @@ class YoutubeHttpClient extends http.BaseClient {
|
||||||
int errorCount = 0}) async* {
|
int errorCount = 0}) async* {
|
||||||
var url = streamInfo.url;
|
var url = streamInfo.url;
|
||||||
|
|
||||||
var query = Map.from(url.queryParameters);
|
var query = Map<String, String>.from(url.queryParameters);
|
||||||
query['ratebypass'] = 'yes';
|
query['ratebypass'] = 'yes';
|
||||||
url = url.replace(queryParameters: query);
|
url = url.replace(queryParameters: query);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import '../../reverse_engineering/responses/responses.dart'
|
||||||
import '../../reverse_engineering/youtube_http_client.dart';
|
import '../../reverse_engineering/youtube_http_client.dart';
|
||||||
import '../videos.dart';
|
import '../videos.dart';
|
||||||
import 'closed_caption.dart';
|
import 'closed_caption.dart';
|
||||||
|
import 'closed_caption_format.dart';
|
||||||
import 'closed_caption_manifest.dart';
|
import 'closed_caption_manifest.dart';
|
||||||
import 'closed_caption_part.dart';
|
import 'closed_caption_part.dart';
|
||||||
import 'closed_caption_track.dart';
|
import 'closed_caption_track.dart';
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/// SubTiles format.
|
||||||
|
class ClosedCaptionFormat {
|
||||||
|
/// .srv format(1).
|
||||||
|
static const ClosedCaptionFormat srv1 = ClosedCaptionFormat._('srv1');
|
||||||
|
|
||||||
|
/// .srv format(2).
|
||||||
|
static const ClosedCaptionFormat srv2 = ClosedCaptionFormat._('srv2');
|
||||||
|
|
||||||
|
/// .srv format(3).
|
||||||
|
static const ClosedCaptionFormat srv3 = ClosedCaptionFormat._('srv3');
|
||||||
|
|
||||||
|
/// .ttml format.
|
||||||
|
static const ClosedCaptionFormat ttml = ClosedCaptionFormat._('ttml');
|
||||||
|
|
||||||
|
/// .vtt format.
|
||||||
|
static const ClosedCaptionFormat vtt = ClosedCaptionFormat._('vtt');
|
||||||
|
|
||||||
|
/// List of all sub titles format.
|
||||||
|
static const List<ClosedCaptionFormat> values = [srv1, srv2, srv3, ttml, vtt];
|
||||||
|
|
||||||
|
/// Format code as string.
|
||||||
|
final String formatCode;
|
||||||
|
|
||||||
|
const ClosedCaptionFormat._(this.formatCode);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'closed_caption_format.dart';
|
||||||
import 'closed_caption_track_info.dart';
|
import 'closed_caption_track_info.dart';
|
||||||
|
|
||||||
/// Manifest that contains information about available closed caption tracks
|
/// Manifest that contains information about available closed caption tracks
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
import '../../extensions/helpers_extension.dart';
|
import '../../extensions/helpers_extension.dart';
|
||||||
|
import 'closed_caption_format.dart';
|
||||||
import 'language.dart';
|
import 'language.dart';
|
||||||
|
|
||||||
/// Metadata associated with a certain [ClosedCaptionTrack]
|
/// Metadata associated with a certain [ClosedCaptionTrack]
|
||||||
|
@ -39,29 +40,3 @@ class ClosedCaptionTrackInfo extends Equatable {
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [url, language, isAutoGenerated];
|
List<Object> get props => [url, language, isAutoGenerated];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SubTiles format.
|
|
||||||
class ClosedCaptionFormat {
|
|
||||||
/// .srv format(1).
|
|
||||||
static const ClosedCaptionFormat srv1 = ClosedCaptionFormat._('srv1');
|
|
||||||
|
|
||||||
/// .srv format(2).
|
|
||||||
static const ClosedCaptionFormat srv2 = ClosedCaptionFormat._('srv2');
|
|
||||||
|
|
||||||
/// .srv format(3).
|
|
||||||
static const ClosedCaptionFormat srv3 = ClosedCaptionFormat._('srv3');
|
|
||||||
|
|
||||||
/// .ttml format.
|
|
||||||
static const ClosedCaptionFormat ttml = ClosedCaptionFormat._('ttml');
|
|
||||||
|
|
||||||
/// .vtt format.
|
|
||||||
static const ClosedCaptionFormat vtt = ClosedCaptionFormat._('vtt');
|
|
||||||
|
|
||||||
/// List of all sub titles format.
|
|
||||||
static const List<ClosedCaptionFormat> values = [srv1, srv2, srv3, ttml, vtt];
|
|
||||||
|
|
||||||
/// Format code as string.
|
|
||||||
final String formatCode;
|
|
||||||
|
|
||||||
const ClosedCaptionFormat._(this.formatCode);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export 'closed_caption.dart';
|
export 'closed_caption.dart';
|
||||||
export 'closed_caption_client.dart';
|
export 'closed_caption_client.dart';
|
||||||
|
export 'closed_caption_format.dart';
|
||||||
export 'closed_caption_manifest.dart';
|
export 'closed_caption_manifest.dart';
|
||||||
export 'closed_caption_part.dart';
|
export 'closed_caption_part.dart';
|
||||||
export 'closed_caption_track.dart';
|
export 'closed_caption_track.dart';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: youtube_explode_dart
|
name: youtube_explode_dart
|
||||||
description: A port in dart of the youtube explode library. Supports several API functions without the need of Youtube API Key.
|
description: A port in dart of the youtube explode library. Supports several API functions without the need of Youtube API Key.
|
||||||
version: 1.6.2
|
version: 1.7.0
|
||||||
homepage: https://github.com/Hexer10/youtube_explode_dart
|
homepage: https://github.com/Hexer10/youtube_explode_dart
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
import 'package:youtube_explode_dart/src/videos/closed_captions/closed_caption_format.dart';
|
||||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -22,9 +23,23 @@ void main() {
|
||||||
|
|
||||||
expect(track.captions, isNotEmpty);
|
expect(track.captions, isNotEmpty);
|
||||||
});
|
});
|
||||||
|
test('Get closed caption track at a specific time', () async {
|
||||||
|
var manifest = await yt.videos.closedCaptions
|
||||||
|
.getManifest('WOxr2dmLHLo', autoGenerated: false);
|
||||||
|
var trackInfo = manifest.getByLanguage('en');
|
||||||
|
var track = await yt.videos.closedCaptions.get(trackInfo.first);
|
||||||
|
var caption =
|
||||||
|
track.getByTime(const Duration(hours: 0, minutes: 1, seconds: 48));
|
||||||
|
|
||||||
|
expect(caption, isNotNull);
|
||||||
|
expect(caption.parts, isEmpty);
|
||||||
|
expect(caption.text,
|
||||||
|
'The second way to add subtitles is the one\nwe always use.');
|
||||||
|
});
|
||||||
|
|
||||||
test('Get auto-generated closed caption track at a specific time', () async {
|
test('Get auto-generated closed caption track at a specific time', () async {
|
||||||
var manifest = await yt.videos.closedCaptions
|
var manifest = await yt.videos.closedCaptions
|
||||||
.getManifest('https://www.youtube.com/watch?v=ppJy5uGZLi4', autoGenerated: true);
|
.getManifest('ppJy5uGZLi4', autoGenerated: true);
|
||||||
var trackInfo = manifest.getByLanguage('en');
|
var trackInfo = manifest.getByLanguage('en');
|
||||||
var track = await yt.videos.closedCaptions.get(trackInfo.first);
|
var track = await yt.videos.closedCaptions.get(trackInfo.first);
|
||||||
var caption =
|
var caption =
|
||||||
|
|
Loading…
Reference in New Issue