diff --git a/dartdoc_options.yaml b/dartdoc_options.yaml new file mode 100644 index 0000000..090cd9f --- /dev/null +++ b/dartdoc_options.yaml @@ -0,0 +1,2 @@ +dartdoc: + showUndocumentedCategories: true \ No newline at end of file diff --git a/lib/src/channels/channels.dart b/lib/src/channels/channels.dart index 7c3fd46..63b1aa5 100644 --- a/lib/src/channels/channels.dart +++ b/lib/src/channels/channels.dart @@ -1,3 +1,6 @@ +/// APIs related to YouTube channels. +/// +/// {@category Channels} library youtube_explode.channels; export 'channel.dart'; diff --git a/lib/src/playlists/playlists.dart b/lib/src/playlists/playlists.dart index 79c52c3..6d5def2 100644 --- a/lib/src/playlists/playlists.dart +++ b/lib/src/playlists/playlists.dart @@ -1,3 +1,6 @@ +/// APIs related to YouTube playlists. +/// +/// {@category Playlists} library youtube_explode.playlists; export 'playlist.dart'; diff --git a/lib/src/search/search.dart b/lib/src/search/search.dart index 65931ba..c5fbd08 100644 --- a/lib/src/search/search.dart +++ b/lib/src/search/search.dart @@ -1,3 +1,6 @@ +/// APIs related to YouTube search queries. +/// +/// {@category Search} library youtube_explode.search; export 'related_query.dart'; diff --git a/lib/src/videos/closed_captions/closed_caption_client.dart b/lib/src/videos/closed_captions/closed_caption_client.dart index 22562fb..783f766 100644 --- a/lib/src/videos/closed_captions/closed_caption_client.dart +++ b/lib/src/videos/closed_captions/closed_caption_client.dart @@ -33,7 +33,8 @@ class ClosedCaptionClient { return ClosedCaptionManifest(tracks); } - /// + /// Gets the actual closed caption track which is + /// identified by the specified metadata. Future get(ClosedCaptionTrackInfo trackInfo) async { var response = await ClosedCaptionTrackResponse.get( _httpClient, trackInfo.url.toString()); @@ -44,4 +45,63 @@ class ClosedCaptionClient { e.getParts().map((f) => ClosedCaptionPart(f.text, f.offset)))); return ClosedCaptionTrack(captions); } + + Future getSrt(ClosedCaptionTrackInfo trackInfo) async { + var track = await get(trackInfo); + + var buffer = StringBuffer(); + for (var i = 0; i < track.captions.length; i++) { + var caption = track.captions[i]; + + // Line number + buffer.writeln('${i + 1}'); + + // Time start --> time end + buffer.write(caption.offset.toSrtFormat()); + buffer.write(' --> '); + buffer.write(caption.end.toSrtFormat()); + buffer.writeln(); + + // Actual text + buffer.writeln(caption.text); + buffer.writeln(); + } + return buffer.toString(); + } +} + +extension on Duration { + String toSrtFormat() { + String threeDigits(int n) { + if (n >= 1000) { + return n.toString().substring(0, 3); + } + if (n >= 100) { + return '$n'; + } + if (n >= 10) { + return '0$n'; + } + return '00$n'; + } + + String twoDigits(int n) { + if (n >= 10) { + return '$n'; + } + return '0$n'; + } + + if (inMicroseconds < 0) { + return "-${-this}"; + } + var twoDigitHours = twoDigits(inHours); + var twoDigitMinutes = + twoDigits(inMinutes.remainder(Duration.minutesPerHour)); + var twoDigitSeconds = + twoDigits(inSeconds.remainder(Duration.secondsPerMinute)); + var fourDigitsUs = + threeDigits(inMilliseconds.remainder(1000)); + return "$twoDigitHours:$twoDigitMinutes:$twoDigitSeconds,$fourDigitsUs"; + } } diff --git a/lib/src/videos/videos.dart b/lib/src/videos/videos.dart index 298b557..a732b1d 100644 --- a/lib/src/videos/videos.dart +++ b/lib/src/videos/videos.dart @@ -1,3 +1,6 @@ +/// APIs related to YouTube videos. +/// +/// {@category Videos} library youtube_explode.videos; export 'comments/comments.dart'; diff --git a/lib/youtube_explode_dart.dart b/lib/youtube_explode_dart.dart index 5bc9635..0063053 100644 --- a/lib/youtube_explode_dart.dart +++ b/lib/youtube_explode_dart.dart @@ -1,3 +1,4 @@ +/// Provides all the APIs implemented by this library. library youtube_explode; export 'src/channels/channels.dart';