2020-05-31 23:36:23 +02:00
|
|
|
import 'package:xml/xml.dart' as xml;
|
2020-06-03 23:02:21 +02:00
|
|
|
|
2020-11-01 15:05:19 +01:00
|
|
|
import '../../extensions/helpers_extension.dart';
|
2020-06-03 23:02:21 +02:00
|
|
|
import '../../retry.dart';
|
|
|
|
import '../youtube_http_client.dart';
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-07-22 15:03:07 +02:00
|
|
|
class ClosedCaptionClient {
|
2021-03-11 14:20:10 +01:00
|
|
|
final xml.XmlDocument root;
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-03-11 14:20:10 +01:00
|
|
|
late final Iterable<ClosedCaption> closedCaptions =
|
|
|
|
root.findAllElements('p').map((e) => ClosedCaption._(e));
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-07-22 15:03:07 +02:00
|
|
|
ClosedCaptionClient(this.root);
|
2020-06-22 17:40:57 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
|
|
|
// ignore: deprecated_member_use
|
2021-07-22 15:03:07 +02:00
|
|
|
ClosedCaptionClient.parse(String raw) : root = xml.parse(raw);
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-07-22 15:03:07 +02:00
|
|
|
static Future<ClosedCaptionClient> get(
|
2020-11-02 13:03:56 +01:00
|
|
|
YoutubeHttpClient httpClient, Uri url) {
|
2021-07-22 15:03:07 +02:00
|
|
|
final formatUrl = url.replaceQueryParameters({'fmt': 'srv3'});
|
2021-09-10 11:44:47 +02:00
|
|
|
return retry(httpClient, () async {
|
2020-05-31 23:36:23 +02:00
|
|
|
var raw = await httpClient.getString(formatUrl);
|
2021-07-22 15:03:07 +02:00
|
|
|
return ClosedCaptionClient.parse(raw);
|
2020-05-31 23:36:23 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2020-05-31 23:36:23 +02:00
|
|
|
class ClosedCaption {
|
2021-03-11 14:20:10 +01:00
|
|
|
final xml.XmlElement root;
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-03-11 14:20:10 +01:00
|
|
|
String get text => root.text;
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-03-11 14:20:10 +01:00
|
|
|
late final Duration offset =
|
|
|
|
Duration(milliseconds: int.parse(root.getAttribute('t') ?? '0'));
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-03-11 14:20:10 +01:00
|
|
|
late final Duration duration =
|
|
|
|
Duration(milliseconds: int.parse(root.getAttribute('d') ?? '0'));
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-03-11 14:20:10 +01:00
|
|
|
late final Duration end = offset + duration;
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-03-11 14:20:10 +01:00
|
|
|
late final List<ClosedCaptionPart> parts =
|
|
|
|
root.findAllElements('s').map((e) => ClosedCaptionPart._(e)).toList();
|
2020-06-22 17:40:57 +02:00
|
|
|
|
2021-03-11 14:20:10 +01:00
|
|
|
ClosedCaption._(this.root);
|
2020-05-31 23:36:23 +02:00
|
|
|
}
|
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2020-05-31 23:36:23 +02:00
|
|
|
class ClosedCaptionPart {
|
2021-03-11 14:20:10 +01:00
|
|
|
final xml.XmlElement root;
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-03-11 14:20:10 +01:00
|
|
|
String get text => root.text;
|
2020-05-31 23:36:23 +02:00
|
|
|
|
2020-07-16 20:02:54 +02:00
|
|
|
///
|
2021-03-11 14:20:10 +01:00
|
|
|
late final Duration offset =
|
|
|
|
Duration(milliseconds: int.parse(root.getAttribute('t') ?? '0'));
|
2020-06-22 17:40:57 +02:00
|
|
|
|
2021-03-11 14:20:10 +01:00
|
|
|
ClosedCaptionPart._(this.root);
|
2020-05-31 23:36:23 +02:00
|
|
|
}
|