diff --git a/CHANGELOG.md b/CHANGELOG.md index 14268e2..8dcf2dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.7.1 +- `ClosedCaptionTrackInfo` and it's members are now json serializable. ## 1.7.0 - BREAKING CHANGES: `ClosedCaptionManifest.getByLanguage` now returns a List. diff --git a/example/example.dart b/example/example.dart index 8b509c5..6debfde 100644 --- a/example/example.dart +++ b/example/example.dart @@ -1,15 +1,12 @@ import 'package:youtube_explode_dart/youtube_explode_dart.dart'; +import 'dart:convert'; Future main() async { var yt = YoutubeExplode(); var manifest = await yt.videos.closedCaptions - .getManifest('Pxgvgh9IFqA', autoGenerated: true); - print(manifest.tracks); - print('\n\n---------------------\n\n'); - - manifest = await yt.videos.closedCaptions - .getManifest('Pxgvgh9IFqA', autoGenerated: false); - print(manifest.tracks); - yt.close(); + .getManifest('ppJy5uGZLi4', autoGenerated: true); + var trackInfo = manifest.getByLanguage('en'); + var track = await yt.videos.closedCaptions.get(trackInfo.first); + print(json.encode(track.toJson())); } diff --git a/lib/src/videos/closed_captions/closed_caption.dart b/lib/src/videos/closed_captions/closed_caption.dart index 131a9d2..febf832 100644 --- a/lib/src/videos/closed_captions/closed_caption.dart +++ b/lib/src/videos/closed_captions/closed_caption.dart @@ -1,9 +1,14 @@ import 'dart:collection'; +import 'package:json_annotation/json_annotation.dart'; + import 'closed_caption_part.dart'; +part 'closed_caption.g.dart'; + /// Text that gets displayed at specific time during video playback, /// as part of a [ClosedCaptionTrack] +@JsonSerializable() class ClosedCaption { /// Text displayed by this caption. final String text; @@ -35,4 +40,11 @@ class ClosedCaption { @override String toString() => 'Text: $text'; + + /// + factory ClosedCaption.fromJson(Map json) => + _$ClosedCaptionFromJson(json); + + /// + Map toJson() => _$ClosedCaptionToJson(this); } diff --git a/lib/src/videos/closed_captions/closed_caption.g.dart b/lib/src/videos/closed_captions/closed_caption.g.dart new file mode 100644 index 0000000..df2ab58 --- /dev/null +++ b/lib/src/videos/closed_captions/closed_caption.g.dart @@ -0,0 +1,30 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'closed_caption.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ClosedCaption _$ClosedCaptionFromJson(Map 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)), + ); +} + +Map _$ClosedCaptionToJson(ClosedCaption instance) => + { + 'text': instance.text, + 'offset': instance.offset?.inMicroseconds, + 'duration': instance.duration?.inMicroseconds, + 'parts': instance.parts, + }; diff --git a/lib/src/videos/closed_captions/closed_caption_format.dart b/lib/src/videos/closed_captions/closed_caption_format.dart index 9734752..a64a768 100644 --- a/lib/src/videos/closed_captions/closed_caption_format.dart +++ b/lib/src/videos/closed_captions/closed_caption_format.dart @@ -1,19 +1,24 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'closed_caption_format.g.dart'; + /// SubTiles format. +@JsonSerializable() class ClosedCaptionFormat { /// .srv format(1). - static const ClosedCaptionFormat srv1 = ClosedCaptionFormat._('srv1'); + static const ClosedCaptionFormat srv1 = ClosedCaptionFormat('srv1'); /// .srv format(2). - static const ClosedCaptionFormat srv2 = ClosedCaptionFormat._('srv2'); + static const ClosedCaptionFormat srv2 = ClosedCaptionFormat('srv2'); /// .srv format(3). - static const ClosedCaptionFormat srv3 = ClosedCaptionFormat._('srv3'); + static const ClosedCaptionFormat srv3 = ClosedCaptionFormat('srv3'); /// .ttml format. - static const ClosedCaptionFormat ttml = ClosedCaptionFormat._('ttml'); + static const ClosedCaptionFormat ttml = ClosedCaptionFormat('ttml'); /// .vtt format. - static const ClosedCaptionFormat vtt = ClosedCaptionFormat._('vtt'); + static const ClosedCaptionFormat vtt = ClosedCaptionFormat('vtt'); /// List of all sub titles format. static const List values = [srv1, srv2, srv3, ttml, vtt]; @@ -21,5 +26,13 @@ class ClosedCaptionFormat { /// Format code as string. final String formatCode; - const ClosedCaptionFormat._(this.formatCode); + /// + const ClosedCaptionFormat(this.formatCode); + + /// + factory ClosedCaptionFormat.fromJson(Map json) => + _$ClosedCaptionFormatFromJson(json); + + /// + Map toJson() => _$ClosedCaptionFormatToJson(this); } \ No newline at end of file diff --git a/lib/src/videos/closed_captions/closed_caption_format.g.dart b/lib/src/videos/closed_captions/closed_caption_format.g.dart new file mode 100644 index 0000000..00c9e30 --- /dev/null +++ b/lib/src/videos/closed_captions/closed_caption_format.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'closed_caption_format.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ClosedCaptionFormat _$ClosedCaptionFormatFromJson(Map json) { + return ClosedCaptionFormat( + json['formatCode'] as String, + ); +} + +Map _$ClosedCaptionFormatToJson( + ClosedCaptionFormat instance) => + { + 'formatCode': instance.formatCode, + }; diff --git a/lib/src/videos/closed_captions/closed_caption_part.dart b/lib/src/videos/closed_captions/closed_caption_part.dart index 83d9527..74bf729 100644 --- a/lib/src/videos/closed_captions/closed_caption_part.dart +++ b/lib/src/videos/closed_captions/closed_caption_part.dart @@ -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). +@JsonSerializable() class ClosedCaptionPart { /// Text displayed by this caption part. final String text; @@ -12,4 +17,11 @@ class ClosedCaptionPart { @override String toString() => text; + + /// + factory ClosedCaptionPart.fromJson(Map json) => + _$ClosedCaptionPartFromJson(json); + + /// + Map toJson() => _$ClosedCaptionPartToJson(this); } diff --git a/lib/src/videos/closed_captions/closed_caption_part.g.dart b/lib/src/videos/closed_captions/closed_caption_part.g.dart new file mode 100644 index 0000000..8b01666 --- /dev/null +++ b/lib/src/videos/closed_captions/closed_caption_part.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'closed_caption_part.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ClosedCaptionPart _$ClosedCaptionPartFromJson(Map json) { + return ClosedCaptionPart( + json['text'] as String, + json['offset'] == null + ? null + : Duration(microseconds: json['offset'] as int), + ); +} + +Map _$ClosedCaptionPartToJson(ClosedCaptionPart instance) => + { + 'text': instance.text, + 'offset': instance.offset?.inMicroseconds, + }; diff --git a/lib/src/videos/closed_captions/closed_caption_track.dart b/lib/src/videos/closed_captions/closed_caption_track.dart index 33a4604..6b20d50 100644 --- a/lib/src/videos/closed_captions/closed_caption_track.dart +++ b/lib/src/videos/closed_captions/closed_caption_track.dart @@ -1,8 +1,13 @@ import 'dart:collection'; +import 'package:json_annotation/json_annotation.dart'; + import 'closed_caption.dart'; +part 'closed_caption_track.g.dart'; + /// Track that contains closed captions in a specific language. +@JsonSerializable() class ClosedCaptionTrack { /// Closed captions. final UnmodifiableListView captions; @@ -15,4 +20,11 @@ class ClosedCaptionTrack { /// Returns null if not found. ClosedCaption getByTime(Duration time) => captions .firstWhere((e) => time >= e.offset && time <= e.end, orElse: () => null); + + /// + factory ClosedCaptionTrack.fromJson(Map json) => + _$ClosedCaptionTrackFromJson(json); + + /// + Map toJson() => _$ClosedCaptionTrackToJson(this); } diff --git a/lib/src/videos/closed_captions/closed_caption_track.g.dart b/lib/src/videos/closed_captions/closed_caption_track.g.dart new file mode 100644 index 0000000..671ab66 --- /dev/null +++ b/lib/src/videos/closed_captions/closed_caption_track.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'closed_caption_track.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ClosedCaptionTrack _$ClosedCaptionTrackFromJson(Map json) { + return ClosedCaptionTrack( + (json['captions'] as List)?.map((e) => + e == null ? null : ClosedCaption.fromJson(e as Map)), + ); +} + +Map _$ClosedCaptionTrackToJson(ClosedCaptionTrack instance) => + { + 'captions': instance.captions, + }; diff --git a/lib/src/videos/closed_captions/closed_caption_track_info.dart b/lib/src/videos/closed_captions/closed_caption_track_info.dart index b09a942..fa1d477 100644 --- a/lib/src/videos/closed_captions/closed_caption_track_info.dart +++ b/lib/src/videos/closed_captions/closed_caption_track_info.dart @@ -1,10 +1,14 @@ import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; import '../../extensions/helpers_extension.dart'; import 'closed_caption_format.dart'; import 'language.dart'; +part 'closed_caption_track_info.g.dart'; + /// Metadata associated with a certain [ClosedCaptionTrack] +@JsonSerializable() class ClosedCaptionTrackInfo extends Equatable { /// Manifest URL of the associated track. final Uri url; @@ -25,13 +29,12 @@ class ClosedCaptionTrackInfo extends Equatable { /// Returns this auto-translated to another language. /// Keeping the same format. - ClosedCaptionTrackInfo autoTranslate( - ClosedCaptionTrackInfo trackInfo, String lang) { + ClosedCaptionTrackInfo autoTranslate(String lang) { return ClosedCaptionTrackInfo( - trackInfo.url.replaceQueryParameters({'tlang': lang}), + url.replaceQueryParameters({'tlang': lang}), Language(lang, ''), - isAutoGenerated: trackInfo.isAutoGenerated, - format: trackInfo.format); + isAutoGenerated: isAutoGenerated, + format: format); } @override @@ -39,4 +42,12 @@ class ClosedCaptionTrackInfo extends Equatable { @override List get props => [url, language, isAutoGenerated]; + + + /// + factory ClosedCaptionTrackInfo.fromJson(Map json) => + _$ClosedCaptionTrackInfoFromJson(json); + + /// + Map toJson() => _$ClosedCaptionTrackInfoToJson(this); } diff --git a/lib/src/videos/closed_captions/closed_caption_track_info.g.dart b/lib/src/videos/closed_captions/closed_caption_track_info.g.dart new file mode 100644 index 0000000..66b6bf1 --- /dev/null +++ b/lib/src/videos/closed_captions/closed_caption_track_info.g.dart @@ -0,0 +1,30 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'closed_caption_track_info.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ClosedCaptionTrackInfo _$ClosedCaptionTrackInfoFromJson( + Map json) { + return ClosedCaptionTrackInfo( + json['url'] == null ? null : Uri.parse(json['url'] as String), + json['language'] == null + ? null + : Language.fromJson(json['language'] as Map), + isAutoGenerated: json['isAutoGenerated'] as bool, + format: json['format'] == null + ? null + : ClosedCaptionFormat.fromJson(json['format'] as Map), + ); +} + +Map _$ClosedCaptionTrackInfoToJson( + ClosedCaptionTrackInfo instance) => + { + 'url': instance.url?.toString(), + 'language': instance.language, + 'isAutoGenerated': instance.isAutoGenerated, + 'format': instance.format, + }; diff --git a/lib/src/videos/closed_captions/language.dart b/lib/src/videos/closed_captions/language.dart index 08dabf4..282800c 100644 --- a/lib/src/videos/closed_captions/language.dart +++ b/lib/src/videos/closed_captions/language.dart @@ -1,6 +1,10 @@ import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'language.g.dart'; /// Language information. +@JsonSerializable() class Language extends Equatable { /// ISO 639-1 code of this language. final String code; @@ -16,4 +20,11 @@ class Language extends Equatable { @override String toString() => 'Language: $name'; + + /// + factory Language.fromJson(Map json) => + _$LanguageFromJson(json); + + /// + Map toJson() => _$LanguageToJson(this); } diff --git a/lib/src/videos/closed_captions/language.g.dart b/lib/src/videos/closed_captions/language.g.dart new file mode 100644 index 0000000..9258bad --- /dev/null +++ b/lib/src/videos/closed_captions/language.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'language.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Language _$LanguageFromJson(Map json) { + return Language( + json['code'] as String, + json['name'] as String, + ); +} + +Map _$LanguageToJson(Language instance) => { + 'code': instance.code, + 'name': instance.name, + }; diff --git a/pubspec.yaml b/pubspec.yaml index 6081d51..8a1e7c3 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. 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 environment: @@ -13,6 +13,7 @@ dependencies: xml: '>=3.0.0 <5.0.0' equatable: ^1.1.0 meta: ^1.1.8 + json_annotation: ^3.1.0 dev_dependencies: effective_dart: ^1.2.4 @@ -20,3 +21,5 @@ dev_dependencies: test: ^1.12.0 grinder: ^0.8.5 pedantic: ^1.9.2 + json_serializable: ^3.5.0 + build_runner: ^1.10.4