parent
cb14e37f39
commit
4f01455f8f
|
@ -1,3 +1,5 @@
|
||||||
|
## 1.7.1
|
||||||
|
- `ClosedCaptionTrackInfo` and it's members are now json serializable.
|
||||||
|
|
||||||
## 1.7.0
|
## 1.7.0
|
||||||
- BREAKING CHANGES: `ClosedCaptionManifest.getByLanguage` now returns a List.
|
- BREAKING CHANGES: `ClosedCaptionManifest.getByLanguage` now returns a List.
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
import 'package:youtube_explode_dart/youtube_explode_dart.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
var yt = YoutubeExplode();
|
var yt = YoutubeExplode();
|
||||||
|
|
||||||
var manifest = await yt.videos.closedCaptions
|
var manifest = await yt.videos.closedCaptions
|
||||||
.getManifest('Pxgvgh9IFqA', autoGenerated: true);
|
.getManifest('ppJy5uGZLi4', autoGenerated: true);
|
||||||
print(manifest.tracks);
|
var trackInfo = manifest.getByLanguage('en');
|
||||||
print('\n\n---------------------\n\n');
|
var track = await yt.videos.closedCaptions.get(trackInfo.first);
|
||||||
|
print(json.encode(track.toJson()));
|
||||||
manifest = await yt.videos.closedCaptions
|
|
||||||
.getManifest('Pxgvgh9IFqA', autoGenerated: false);
|
|
||||||
print(manifest.tracks);
|
|
||||||
yt.close();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
import 'closed_caption_part.dart';
|
import 'closed_caption_part.dart';
|
||||||
|
|
||||||
|
part 'closed_caption.g.dart';
|
||||||
|
|
||||||
/// Text that gets displayed at specific time during video playback,
|
/// Text that gets displayed at specific time during video playback,
|
||||||
/// as part of a [ClosedCaptionTrack]
|
/// as part of a [ClosedCaptionTrack]
|
||||||
|
@JsonSerializable()
|
||||||
class ClosedCaption {
|
class ClosedCaption {
|
||||||
/// Text displayed by this caption.
|
/// Text displayed by this caption.
|
||||||
final String text;
|
final String text;
|
||||||
|
@ -35,4 +40,11 @@ class ClosedCaption {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'Text: $text';
|
String toString() => 'Text: $text';
|
||||||
|
|
||||||
|
///
|
||||||
|
factory ClosedCaption.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ClosedCaptionFromJson(json);
|
||||||
|
|
||||||
|
///
|
||||||
|
Map<String, dynamic> toJson() => _$ClosedCaptionToJson(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'closed_caption.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
ClosedCaption _$ClosedCaptionFromJson(Map<String, dynamic> json) {
|
||||||
|
return ClosedCaption(
|
||||||
|
json['text'] as String,
|
||||||
|
json['offset'] == null
|
||||||
|
? null
|
||||||
|
: Duration(microseconds: json['offset'] as int),
|
||||||
|
json['duration'] == null
|
||||||
|
? null
|
||||||
|
: Duration(microseconds: json['duration'] as int),
|
||||||
|
(json['parts'] as List)?.map((e) => e == null
|
||||||
|
? null
|
||||||
|
: ClosedCaptionPart.fromJson(e as Map<String, dynamic>)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$ClosedCaptionToJson(ClosedCaption instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'text': instance.text,
|
||||||
|
'offset': instance.offset?.inMicroseconds,
|
||||||
|
'duration': instance.duration?.inMicroseconds,
|
||||||
|
'parts': instance.parts,
|
||||||
|
};
|
|
@ -1,19 +1,24 @@
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'closed_caption_format.g.dart';
|
||||||
|
|
||||||
/// SubTiles format.
|
/// SubTiles format.
|
||||||
|
@JsonSerializable()
|
||||||
class ClosedCaptionFormat {
|
class ClosedCaptionFormat {
|
||||||
/// .srv format(1).
|
/// .srv format(1).
|
||||||
static const ClosedCaptionFormat srv1 = ClosedCaptionFormat._('srv1');
|
static const ClosedCaptionFormat srv1 = ClosedCaptionFormat('srv1');
|
||||||
|
|
||||||
/// .srv format(2).
|
/// .srv format(2).
|
||||||
static const ClosedCaptionFormat srv2 = ClosedCaptionFormat._('srv2');
|
static const ClosedCaptionFormat srv2 = ClosedCaptionFormat('srv2');
|
||||||
|
|
||||||
/// .srv format(3).
|
/// .srv format(3).
|
||||||
static const ClosedCaptionFormat srv3 = ClosedCaptionFormat._('srv3');
|
static const ClosedCaptionFormat srv3 = ClosedCaptionFormat('srv3');
|
||||||
|
|
||||||
/// .ttml format.
|
/// .ttml format.
|
||||||
static const ClosedCaptionFormat ttml = ClosedCaptionFormat._('ttml');
|
static const ClosedCaptionFormat ttml = ClosedCaptionFormat('ttml');
|
||||||
|
|
||||||
/// .vtt format.
|
/// .vtt format.
|
||||||
static const ClosedCaptionFormat vtt = ClosedCaptionFormat._('vtt');
|
static const ClosedCaptionFormat vtt = ClosedCaptionFormat('vtt');
|
||||||
|
|
||||||
/// List of all sub titles format.
|
/// List of all sub titles format.
|
||||||
static const List<ClosedCaptionFormat> values = [srv1, srv2, srv3, ttml, vtt];
|
static const List<ClosedCaptionFormat> values = [srv1, srv2, srv3, ttml, vtt];
|
||||||
|
@ -21,5 +26,13 @@ class ClosedCaptionFormat {
|
||||||
/// Format code as string.
|
/// Format code as string.
|
||||||
final String formatCode;
|
final String formatCode;
|
||||||
|
|
||||||
const ClosedCaptionFormat._(this.formatCode);
|
///
|
||||||
|
const ClosedCaptionFormat(this.formatCode);
|
||||||
|
|
||||||
|
///
|
||||||
|
factory ClosedCaptionFormat.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ClosedCaptionFormatFromJson(json);
|
||||||
|
|
||||||
|
///
|
||||||
|
Map<String, dynamic> toJson() => _$ClosedCaptionFormatToJson(this);
|
||||||
}
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'closed_caption_format.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
ClosedCaptionFormat _$ClosedCaptionFormatFromJson(Map<String, dynamic> json) {
|
||||||
|
return ClosedCaptionFormat(
|
||||||
|
json['formatCode'] as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$ClosedCaptionFormatToJson(
|
||||||
|
ClosedCaptionFormat instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'formatCode': instance.formatCode,
|
||||||
|
};
|
|
@ -1,4 +1,9 @@
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'closed_caption_part.g.dart';
|
||||||
|
|
||||||
/// Part of a closed caption (usually a single word).
|
/// Part of a closed caption (usually a single word).
|
||||||
|
@JsonSerializable()
|
||||||
class ClosedCaptionPart {
|
class ClosedCaptionPart {
|
||||||
/// Text displayed by this caption part.
|
/// Text displayed by this caption part.
|
||||||
final String text;
|
final String text;
|
||||||
|
@ -12,4 +17,11 @@ class ClosedCaptionPart {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => text;
|
String toString() => text;
|
||||||
|
|
||||||
|
///
|
||||||
|
factory ClosedCaptionPart.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ClosedCaptionPartFromJson(json);
|
||||||
|
|
||||||
|
///
|
||||||
|
Map<String, dynamic> toJson() => _$ClosedCaptionPartToJson(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'closed_caption_part.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
ClosedCaptionPart _$ClosedCaptionPartFromJson(Map<String, dynamic> json) {
|
||||||
|
return ClosedCaptionPart(
|
||||||
|
json['text'] as String,
|
||||||
|
json['offset'] == null
|
||||||
|
? null
|
||||||
|
: Duration(microseconds: json['offset'] as int),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$ClosedCaptionPartToJson(ClosedCaptionPart instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'text': instance.text,
|
||||||
|
'offset': instance.offset?.inMicroseconds,
|
||||||
|
};
|
|
@ -1,8 +1,13 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
import 'closed_caption.dart';
|
import 'closed_caption.dart';
|
||||||
|
|
||||||
|
part 'closed_caption_track.g.dart';
|
||||||
|
|
||||||
/// Track that contains closed captions in a specific language.
|
/// Track that contains closed captions in a specific language.
|
||||||
|
@JsonSerializable()
|
||||||
class ClosedCaptionTrack {
|
class ClosedCaptionTrack {
|
||||||
/// Closed captions.
|
/// Closed captions.
|
||||||
final UnmodifiableListView<ClosedCaption> captions;
|
final UnmodifiableListView<ClosedCaption> captions;
|
||||||
|
@ -15,4 +20,11 @@ class ClosedCaptionTrack {
|
||||||
/// Returns null if not found.
|
/// Returns null if not found.
|
||||||
ClosedCaption getByTime(Duration time) => captions
|
ClosedCaption getByTime(Duration time) => captions
|
||||||
.firstWhere((e) => time >= e.offset && time <= e.end, orElse: () => null);
|
.firstWhere((e) => time >= e.offset && time <= e.end, orElse: () => null);
|
||||||
|
|
||||||
|
///
|
||||||
|
factory ClosedCaptionTrack.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ClosedCaptionTrackFromJson(json);
|
||||||
|
|
||||||
|
///
|
||||||
|
Map<String, dynamic> toJson() => _$ClosedCaptionTrackToJson(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'closed_caption_track.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
ClosedCaptionTrack _$ClosedCaptionTrackFromJson(Map<String, dynamic> json) {
|
||||||
|
return ClosedCaptionTrack(
|
||||||
|
(json['captions'] as List)?.map((e) =>
|
||||||
|
e == null ? null : ClosedCaption.fromJson(e as Map<String, dynamic>)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$ClosedCaptionTrackToJson(ClosedCaptionTrack instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'captions': instance.captions,
|
||||||
|
};
|
|
@ -1,10 +1,14 @@
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
import '../../extensions/helpers_extension.dart';
|
import '../../extensions/helpers_extension.dart';
|
||||||
import 'closed_caption_format.dart';
|
import 'closed_caption_format.dart';
|
||||||
import 'language.dart';
|
import 'language.dart';
|
||||||
|
|
||||||
|
part 'closed_caption_track_info.g.dart';
|
||||||
|
|
||||||
/// Metadata associated with a certain [ClosedCaptionTrack]
|
/// Metadata associated with a certain [ClosedCaptionTrack]
|
||||||
|
@JsonSerializable()
|
||||||
class ClosedCaptionTrackInfo extends Equatable {
|
class ClosedCaptionTrackInfo extends Equatable {
|
||||||
/// Manifest URL of the associated track.
|
/// Manifest URL of the associated track.
|
||||||
final Uri url;
|
final Uri url;
|
||||||
|
@ -25,13 +29,12 @@ class ClosedCaptionTrackInfo extends Equatable {
|
||||||
|
|
||||||
/// Returns this auto-translated to another language.
|
/// Returns this auto-translated to another language.
|
||||||
/// Keeping the same format.
|
/// Keeping the same format.
|
||||||
ClosedCaptionTrackInfo autoTranslate(
|
ClosedCaptionTrackInfo autoTranslate(String lang) {
|
||||||
ClosedCaptionTrackInfo trackInfo, String lang) {
|
|
||||||
return ClosedCaptionTrackInfo(
|
return ClosedCaptionTrackInfo(
|
||||||
trackInfo.url.replaceQueryParameters({'tlang': lang}),
|
url.replaceQueryParameters({'tlang': lang}),
|
||||||
Language(lang, ''),
|
Language(lang, ''),
|
||||||
isAutoGenerated: trackInfo.isAutoGenerated,
|
isAutoGenerated: isAutoGenerated,
|
||||||
format: trackInfo.format);
|
format: format);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -39,4 +42,12 @@ class ClosedCaptionTrackInfo extends Equatable {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [url, language, isAutoGenerated];
|
List<Object> get props => [url, language, isAutoGenerated];
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
factory ClosedCaptionTrackInfo.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ClosedCaptionTrackInfoFromJson(json);
|
||||||
|
|
||||||
|
///
|
||||||
|
Map<String, dynamic> toJson() => _$ClosedCaptionTrackInfoToJson(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'closed_caption_track_info.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
ClosedCaptionTrackInfo _$ClosedCaptionTrackInfoFromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
return ClosedCaptionTrackInfo(
|
||||||
|
json['url'] == null ? null : Uri.parse(json['url'] as String),
|
||||||
|
json['language'] == null
|
||||||
|
? null
|
||||||
|
: Language.fromJson(json['language'] as Map<String, dynamic>),
|
||||||
|
isAutoGenerated: json['isAutoGenerated'] as bool,
|
||||||
|
format: json['format'] == null
|
||||||
|
? null
|
||||||
|
: ClosedCaptionFormat.fromJson(json['format'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$ClosedCaptionTrackInfoToJson(
|
||||||
|
ClosedCaptionTrackInfo instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'url': instance.url?.toString(),
|
||||||
|
'language': instance.language,
|
||||||
|
'isAutoGenerated': instance.isAutoGenerated,
|
||||||
|
'format': instance.format,
|
||||||
|
};
|
|
@ -1,6 +1,10 @@
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'language.g.dart';
|
||||||
|
|
||||||
/// Language information.
|
/// Language information.
|
||||||
|
@JsonSerializable()
|
||||||
class Language extends Equatable {
|
class Language extends Equatable {
|
||||||
/// ISO 639-1 code of this language.
|
/// ISO 639-1 code of this language.
|
||||||
final String code;
|
final String code;
|
||||||
|
@ -16,4 +20,11 @@ class Language extends Equatable {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'Language: $name';
|
String toString() => 'Language: $name';
|
||||||
|
|
||||||
|
///
|
||||||
|
factory Language.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$LanguageFromJson(json);
|
||||||
|
|
||||||
|
///
|
||||||
|
Map<String, dynamic> toJson() => _$LanguageToJson(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'language.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
Language _$LanguageFromJson(Map<String, dynamic> json) {
|
||||||
|
return Language(
|
||||||
|
json['code'] as String,
|
||||||
|
json['name'] as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$LanguageToJson(Language instance) => <String, dynamic>{
|
||||||
|
'code': instance.code,
|
||||||
|
'name': instance.name,
|
||||||
|
};
|
|
@ -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.7.0
|
version: 1.7.1
|
||||||
homepage: https://github.com/Hexer10/youtube_explode_dart
|
homepage: https://github.com/Hexer10/youtube_explode_dart
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
@ -13,6 +13,7 @@ dependencies:
|
||||||
xml: '>=3.0.0 <5.0.0'
|
xml: '>=3.0.0 <5.0.0'
|
||||||
equatable: ^1.1.0
|
equatable: ^1.1.0
|
||||||
meta: ^1.1.8
|
meta: ^1.1.8
|
||||||
|
json_annotation: ^3.1.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
effective_dart: ^1.2.4
|
effective_dart: ^1.2.4
|
||||||
|
@ -20,3 +21,5 @@ dev_dependencies:
|
||||||
test: ^1.12.0
|
test: ^1.12.0
|
||||||
grinder: ^0.8.5
|
grinder: ^0.8.5
|
||||||
pedantic: ^1.9.2
|
pedantic: ^1.9.2
|
||||||
|
json_serializable: ^3.5.0
|
||||||
|
build_runner: ^1.10.4
|
||||||
|
|
Loading…
Reference in New Issue