feat: add YouTube provider for lossy downloads via Cobalt API

- New YouTube download provider with Opus 256kbps and MP3 320kbps options
- SongLink/Odesli integration for Spotify/Deezer ID to YouTube URL conversion
- YouTube video ID detection for YT Music extension compatibility
- Parallel cover art and lyrics fetching during download
- Queue progress shows bytes (X.X MB) for streaming downloads
- Full metadata embedding: cover, lyrics, title, artist, album, track#, disc#, year, ISRC
- Removed Tidal HIGH (lossy AAC) option - use YouTube for lossy instead
- Bumped version to 3.6.0
This commit is contained in:
zarzet
2026-02-09 18:15:43 +07:00
parent 23f5aa11b0
commit 7ec5d28caf
30 changed files with 1225 additions and 166 deletions
+4
View File
@@ -28,6 +28,7 @@ class DownloadItem {
final DownloadStatus status;
final double progress;
final double speedMBps;
final int bytesReceived; // Bytes downloaded so far (for unknown size downloads)
final String? filePath;
final String? error;
final DownloadErrorType? errorType;
@@ -41,6 +42,7 @@ class DownloadItem {
this.status = DownloadStatus.queued,
this.progress = 0.0,
this.speedMBps = 0.0,
this.bytesReceived = 0,
this.filePath,
this.error,
this.errorType,
@@ -55,6 +57,7 @@ class DownloadItem {
DownloadStatus? status,
double? progress,
double? speedMBps,
int? bytesReceived,
String? filePath,
String? error,
DownloadErrorType? errorType,
@@ -68,6 +71,7 @@ class DownloadItem {
status: status ?? this.status,
progress: progress ?? this.progress,
speedMBps: speedMBps ?? this.speedMBps,
bytesReceived: bytesReceived ?? this.bytesReceived,
filePath: filePath ?? this.filePath,
error: error ?? this.error,
errorType: errorType ?? this.errorType,
+2
View File
@@ -15,6 +15,7 @@ DownloadItem _$DownloadItemFromJson(Map<String, dynamic> json) => DownloadItem(
DownloadStatus.queued,
progress: (json['progress'] as num?)?.toDouble() ?? 0.0,
speedMBps: (json['speedMBps'] as num?)?.toDouble() ?? 0.0,
bytesReceived: (json['bytesReceived'] as num?)?.toInt() ?? 0,
filePath: json['filePath'] as String?,
error: json['error'] as String?,
errorType: $enumDecodeNullable(_$DownloadErrorTypeEnumMap, json['errorType']),
@@ -30,6 +31,7 @@ Map<String, dynamic> _$DownloadItemToJson(DownloadItem instance) =>
'status': _$DownloadStatusEnumMap[instance.status]!,
'progress': instance.progress,
'speedMBps': instance.speedMBps,
'bytesReceived': instance.bytesReceived,
'filePath': instance.filePath,
'error': instance.error,
'errorType': _$DownloadErrorTypeEnumMap[instance.errorType],