youtube_explode/lib/src/videos/streams/stream_info.dart

105 lines
2.7 KiB
Dart
Raw Normal View History

2021-10-04 13:00:22 +02:00
import 'package:http_parser/http_parser.dart';
2021-09-28 16:49:38 +02:00
import '../../reverse_engineering/models/fragment.dart';
2021-10-04 13:00:22 +02:00
import '../videos.dart';
2020-06-03 13:18:37 +02:00
/// Generic YouTube media stream.
mixin StreamInfo {
2020-06-03 13:18:37 +02:00
/// Stream tag.
/// Uniquely identifies a stream inside a manifest.
int get tag;
2020-06-03 13:18:37 +02:00
/// Stream URL.
Uri get url;
2020-06-03 13:18:37 +02:00
/// Stream container.
StreamContainer get container;
2020-06-03 13:18:37 +02:00
/// Stream size.
FileSize get size;
2020-06-03 13:18:37 +02:00
/// Stream bitrate.
Bitrate get bitrate;
2020-06-03 13:18:37 +02:00
2021-09-28 16:49:38 +02:00
/// DASH streams contain multiple stream fragments.
List<Fragment> get fragments;
2021-09-28 16:49:38 +02:00
2021-10-04 13:00:22 +02:00
/// Streams codec.
MediaType get codec;
2021-10-04 13:00:22 +02:00
/// Stream quality label.
String get qualityLabel;
2021-10-04 13:00:22 +02:00
/// Convert to a json-serialized type.
Map<String, dynamic> toJson();
2020-06-03 13:18:37 +02:00
}
2020-06-16 21:49:30 +02:00
/// Extension for Iterables of StreamInfo.
extension StreamInfoIterableExt<T extends StreamInfo> on Iterable<T> {
/// Gets the stream with highest bitrate.
T withHighestBitrate() => sortByBitrate().first;
2020-06-16 21:49:30 +02:00
/// Gets the video streams sorted by bitrate in ascending order.
/// This returns new list without editing the original list.
List<T> sortByBitrate() =>
toList()..sort((a, b) => b.bitrate.compareTo(a.bitrate));
2021-10-04 13:00:22 +02:00
/// Print a formatted text of all the streams. Like youtube-dl -F option.
String describe() {
final column = _Column(['format code', 'extension', 'resolution', 'note']);
for (final e in this) {
column.write([
e.tag,
e.container.name,
if (e is VideoStreamInfo) e.videoResolution else 'audio only',
e.qualityLabel,
e.bitrate,
e.codec.parameters['codecs'],
if (e is VideoStreamInfo) e.framerate,
if (e is VideoOnlyStreamInfo) 'video only',
if (e is MuxedStreamInfo) 'muxed',
2021-10-04 13:00:22 +02:00
e.size
]);
}
return column.toString();
}
}
/// Utility for [StreamInfoIterableExt.describe]
class _Column {
final List<String> header;
final List<List<String>> _values = [];
_Column(this.header);
void write(List<Object?> value) => _values
.add(value.where((e) => e != null).map((e) => e.toString()).toList());
@override
String toString() {
final headerLen = <int>[];
final buffer = StringBuffer();
for (final e in header) {
headerLen.add(e.length + 2);
buffer.write('$e ');
}
buffer.writeln();
for (final valueList in _values) {
for (var i = 0; i < valueList.length; i++) {
final v = valueList[i];
if (headerLen.length <= i) {
buffer.write(', $v');
continue;
}
buffer.write(v.padRight(headerLen[i]));
}
buffer.writeln();
}
return buffer.toString();
}
2020-06-16 21:49:30 +02:00
}
String mediaTypeToJson(MediaType value) => value.toString();
MediaType mediaTypeFromJson(String value) => MediaType.parse(value);