Files
PiliPlus/lib/utils/video_utils.dart
bggRGjQaUbCoE ffd4f9ee73 feat: video download
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-11-09 22:06:19 +08:00

110 lines
4.1 KiB
Dart

import 'package:PiliPlus/grpc/bilibili/app/listener/v1.pb.dart'
show DashItem, ResponseUrl;
import 'package:PiliPlus/models/common/video/cdn_type.dart';
import 'package:PiliPlus/models/video/play/url.dart';
import 'package:PiliPlus/models_new/live/live_room_play_info/codec.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
abstract final class VideoUtils {
static String cdnService = Pref.defaultCDNService;
static bool disableAudioCDN = Pref.disableAudioCDN;
/// [DashItem] audio
/// [VideoItem] [AudioItem] video
/// [CodecItem] live
static String getCdnUrl(dynamic item, [String? defaultCDNService]) {
String? backupUrl;
String? videoUrl;
defaultCDNService ??= cdnService;
if (item case final AudioItem e) {
if (disableAudioCDN) {
return e.backupUrl?.isNotEmpty == true ? e.backupUrl! : e.baseUrl ?? '';
}
}
if (defaultCDNService == CDNService.baseUrl.code) {
if (item case final BaseItem e) {
return e.baseUrl?.isNotEmpty == true ? e.baseUrl! : e.backupUrl ?? '';
}
}
if (item case final CodecItem e) {
backupUrl = e.urlInfo!.first.host! + e.baseUrl! + e.urlInfo!.first.extra!;
} else if (item case final DashItem e) {
backupUrl = e.backupUrl.lastOrNull;
} else {
backupUrl = item.backupUrl;
}
if (defaultCDNService == CDNService.backupUrl.code) {
return backupUrl?.isNotEmpty == true ? backupUrl! : item.baseUrl ?? '';
}
videoUrl = backupUrl?.isNotEmpty == true ? backupUrl : item.baseUrl;
if (videoUrl == null || videoUrl.isEmpty) {
return '';
}
// if (kDebugMode) debugPrint('videoUrl:$videoUrl');
String defaultCDNHost = CDNService.fromCode(defaultCDNService).host;
// if (kDebugMode) debugPrint('defaultCDNHost:$defaultCDNHost');
if (videoUrl.contains('szbdyd.com')) {
final uri = Uri.parse(videoUrl);
String hostname = uri.queryParameters['xy_usource'] ?? defaultCDNHost;
videoUrl = uri.replace(host: hostname, port: 443).toString();
} else if (videoUrl.contains('.mcdn.bilivideo') ||
videoUrl.contains('/upgcxcode/')) {
videoUrl = Uri.parse(
videoUrl,
).replace(host: defaultCDNHost, port: 443).toString();
// videoUrl =
// 'https://proxy-tf-all-ws.bilivideo.com/?url=${Uri.encodeComponent(videoUrl)}';
}
// if (kDebugMode) debugPrint('videoUrl:$videoUrl');
// /// 先获取backupUrl 一般是upgcxcode地址 播放更稳定
// if (item is VideoItem) {
// backupUrl = item.backupUrl ?? '';
// videoUrl = backupUrl.contains('http') ? backupUrl : (item.baseUrl ?? '');
// } else if (item is AudioItem) {
// backupUrl = item.backupUrl ?? '';
// videoUrl = backupUrl.contains('http') ? backupUrl : (item.baseUrl ?? '');
// } else if (item is CodecItem) {
// backupUrl = (item.urlInfo?.first.host)! +
// item.baseUrl! +
// item.urlInfo!.first.extra!;
// videoUrl = backupUrl.contains('http') ? backupUrl : (item.baseUrl ?? '');
// } else {
// return '';
// }
//
// /// issues #70
// if (videoUrl.contains('.mcdn.bilivideo')) {
// videoUrl =
// 'https://proxy-tf-all-ws.bilivideo.com/?url=${Uri.encodeComponent(videoUrl)}';
// } else if (videoUrl.contains('/upgcxcode/')) {
// //CDN列表
// var cdnList = {
// 'ali': 'upos-sz-mirrorali.bilivideo.com',
// 'cos': 'upos-sz-mirrorcos.bilivideo.com',
// 'hw': 'upos-sz-mirrorhw.bilivideo.com',
// };
// //取一个CDN
// var cdn = cdnList['cos'] ?? '';
// var reg = RegExp(r'(http|https)://(.*?)/upgcxcode/');
// videoUrl = videoUrl.replaceAll(reg, 'https://$cdn/upgcxcode/');
// }
return videoUrl;
}
static String getDurlCdnUrl(ResponseUrl item) {
if (disableAudioCDN || cdnService == CDNService.backupUrl.code) {
return item.backupUrl.lastOrNull ?? item.url;
}
if (cdnService == CDNService.baseUrl.code) {
return item.url;
}
return Uri.parse(
item.backupUrl.lastOrNull ?? item.url,
).replace(host: CDNService.fromCode(cdnService).host, port: 443).toString();
}
}