mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
feat: 新增更多CDN选项,且默认单独关闭音频CDN
This commit is contained in:
114
lib/models/video/play/CDN.dart
Normal file
114
lib/models/video/play/CDN.dart
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
//https://github.com/yujincheng08/BiliRoaming/blob/master/app/src/main/res/values/strings_raw.xml
|
||||||
|
//https://github.com/yujincheng08/BiliRoaming/blob/master/app/src/main/res/values/arrays.xml
|
||||||
|
enum CDNService {
|
||||||
|
baseUrl,
|
||||||
|
backupUrl,
|
||||||
|
ali,
|
||||||
|
alib,
|
||||||
|
alio1,
|
||||||
|
cos,
|
||||||
|
cosb,
|
||||||
|
coso1,
|
||||||
|
hw,
|
||||||
|
hwb,
|
||||||
|
hwo1,
|
||||||
|
hw_08c,
|
||||||
|
hw_08h,
|
||||||
|
hw_08ct,
|
||||||
|
tf_hw,
|
||||||
|
tf_tx,
|
||||||
|
akamai,
|
||||||
|
aliov,
|
||||||
|
cosov,
|
||||||
|
hwov,
|
||||||
|
hk_bcache,
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CDNServiceDesc on CDNService {
|
||||||
|
static final List<String> _descList = [
|
||||||
|
'基础 URL(不推荐)',
|
||||||
|
'备用 URL',
|
||||||
|
'ali(阿里云)',
|
||||||
|
'alib(阿里云)',
|
||||||
|
'alio1(阿里云)',
|
||||||
|
'cos(腾讯云)',
|
||||||
|
'cosb(腾讯云,VOD 加速类型)',
|
||||||
|
'coso1(腾讯云)',
|
||||||
|
'hw(华为云,融合 CDN)',
|
||||||
|
'hwb(华为云,融合 CDN)',
|
||||||
|
'hwo1(华为云,融合 CDN)',
|
||||||
|
'08c(华为云,融合 CDN)',
|
||||||
|
'08h(华为云,融合 CDN)',
|
||||||
|
'08ct(华为云,融合 CDN)',
|
||||||
|
'tf_hw(华为云)',
|
||||||
|
'tf_tx(腾讯云)',
|
||||||
|
'akamai(Akamai 海外)',
|
||||||
|
'aliov(阿里云海外)',
|
||||||
|
'cosov(腾讯云海外)',
|
||||||
|
'hwov(华为云海外)',
|
||||||
|
'hk_bcache(Bilibili海外)',
|
||||||
|
];
|
||||||
|
String get description => _descList[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CDNServiceHost on CDNService {
|
||||||
|
static final List<String> _hostList = [
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'upos-sz-mirrorali.bilivideo.com',
|
||||||
|
'upos-sz-mirroralib.bilivideo.com',
|
||||||
|
'upos-sz-mirroralio1.bilivideo.com',
|
||||||
|
'upos-sz-mirrorcos.bilivideo.com',
|
||||||
|
'upos-sz-mirrorcosb.bilivideo.com',
|
||||||
|
'upos-sz-mirrorcoso1.bilivideo.com',
|
||||||
|
'upos-sz-mirrorhw.bilivideo.com',
|
||||||
|
'upos-sz-mirrorhwb.bilivideo.com',
|
||||||
|
'upos-sz-mirrorhwo1.bilivideo.com',
|
||||||
|
'upos-sz-mirror08c.bilivideo.com',
|
||||||
|
'upos-sz-mirror08h.bilivideo.com',
|
||||||
|
'upos-sz-mirror08ct.bilivideo.com',
|
||||||
|
'upos-tf-all-hw.bilivideo.com',
|
||||||
|
'upos-tf-all-tx.bilivideo.com',
|
||||||
|
'upos-hz-mirrorakam.akamaized.net',
|
||||||
|
'upos-sz-mirroraliov.bilivideo.com',
|
||||||
|
'upos-sz-mirrorcosov.bilivideo.com',
|
||||||
|
'upos-sz-mirrorhwov.bilivideo.com',
|
||||||
|
'cn-hk-eq-bcache-01.bilivideo.com',
|
||||||
|
];
|
||||||
|
String get host => _hostList[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CDNServiceCode on CDNService {
|
||||||
|
static final List<String> _codeList = [
|
||||||
|
'baseUrl',
|
||||||
|
'backupUrl',
|
||||||
|
'ali',
|
||||||
|
'alib',
|
||||||
|
'alio1',
|
||||||
|
'cos',
|
||||||
|
'cosb',
|
||||||
|
'coso1',
|
||||||
|
'hw',
|
||||||
|
'hwb',
|
||||||
|
'hwo1',
|
||||||
|
'hw_08c',
|
||||||
|
'hw_08h',
|
||||||
|
'hw_08ct',
|
||||||
|
'tf_hw',
|
||||||
|
'tf_tx',
|
||||||
|
'akamai',
|
||||||
|
'aliov',
|
||||||
|
'cosov',
|
||||||
|
'hwov',
|
||||||
|
'hk_bcache',
|
||||||
|
];
|
||||||
|
String get code => _codeList[index];
|
||||||
|
|
||||||
|
static CDNService? fromCode(String code) {
|
||||||
|
final index = _codeList.indexOf(code);
|
||||||
|
if (index != -1) {
|
||||||
|
return CDNService.values[index];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ class LiveRoomController extends GetxController {
|
|||||||
PlPlayerController plPlayerController =
|
PlPlayerController plPlayerController =
|
||||||
PlPlayerController.getInstance(videoType: 'live');
|
PlPlayerController.getInstance(videoType: 'live');
|
||||||
Rx<RoomInfoH5Model> roomInfoH5 = RoomInfoH5Model().obs;
|
Rx<RoomInfoH5Model> roomInfoH5 = RoomInfoH5Model().obs;
|
||||||
late bool enableCDN;
|
// late bool enableCDN;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@@ -35,7 +35,7 @@ class LiveRoomController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// CDN优化
|
// CDN优化
|
||||||
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
// enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
playerInit(source) async {
|
playerInit(source) async {
|
||||||
@@ -62,11 +62,7 @@ class LiveRoomController extends GetxController {
|
|||||||
List<CodecItem> codec =
|
List<CodecItem> codec =
|
||||||
res['data'].playurlInfo.playurl.stream.first.format.first.codec;
|
res['data'].playurlInfo.playurl.stream.first.format.first.codec;
|
||||||
CodecItem item = codec.first;
|
CodecItem item = codec.first;
|
||||||
String videoUrl = enableCDN
|
String videoUrl = VideoUtils.getCdnUrl(item);
|
||||||
? VideoUtils.getCdnUrl(item)
|
|
||||||
: (item.urlInfo?.first.host)! +
|
|
||||||
item.baseUrl! +
|
|
||||||
item.urlInfo!.first.extra!;
|
|
||||||
await playerInit(videoUrl);
|
await playerInit(videoUrl);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ import 'dart:io';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:PiliPalaX/models/video/play/quality.dart';
|
import 'package:PiliPalaX/models/video/play/quality.dart';
|
||||||
|
import 'package:PiliPalaX/models/video/play/CDN.dart';
|
||||||
import 'package:PiliPalaX/pages/setting/widgets/select_dialog.dart';
|
import 'package:PiliPalaX/pages/setting/widgets/select_dialog.dart';
|
||||||
import 'package:PiliPalaX/utils/storage.dart';
|
import 'package:PiliPalaX/utils/storage.dart';
|
||||||
|
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||||
|
|
||||||
import 'widgets/switch_item.dart';
|
import 'widgets/switch_item.dart';
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@ class _VideoSettingState extends State<VideoSetting> {
|
|||||||
late dynamic secondDecode;
|
late dynamic secondDecode;
|
||||||
late dynamic hardwareDecoding;
|
late dynamic hardwareDecoding;
|
||||||
late dynamic videoSync;
|
late dynamic videoSync;
|
||||||
|
late dynamic defaultCDNService;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -39,6 +42,8 @@ class _VideoSettingState extends State<VideoSetting> {
|
|||||||
defaultValue: Platform.isAndroid ? 'auto-safe' : 'auto');
|
defaultValue: Platform.isAndroid ? 'auto-safe' : 'auto');
|
||||||
videoSync =
|
videoSync =
|
||||||
setting.get(SettingBoxKey.videoSync, defaultValue: 'display-resample');
|
setting.get(SettingBoxKey.videoSync, defaultValue: 'display-resample');
|
||||||
|
defaultCDNService = setting.get(SettingBoxKey.CDNService,
|
||||||
|
defaultValue: CDNService.ali.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -80,11 +85,37 @@ class _VideoSettingState extends State<VideoSetting> {
|
|||||||
setKey: SettingBoxKey.p1080,
|
setKey: SettingBoxKey.p1080,
|
||||||
defaultVal: true,
|
defaultVal: true,
|
||||||
),
|
),
|
||||||
const SetSwitchItem(
|
ListTile(
|
||||||
title: 'CDN优化',
|
title: Text('CDN 设置', style: titleStyle),
|
||||||
subTitle: '使用优质CDN线路',
|
leading: Icon(MdiIcons.cloudPlusOutline),
|
||||||
leading: Icon(Icons.network_check_outlined),
|
subtitle: Text(
|
||||||
setKey: SettingBoxKey.enableCDN,
|
'当前使用:${CDNServiceCode.fromCode(defaultCDNService)!.description},部分 CDN 可能失效,如无法播放请尝试切换',
|
||||||
|
style: subTitleStyle,
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
String? result = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return SelectDialog<String>(
|
||||||
|
title: 'CDN 设置',
|
||||||
|
value: defaultCDNService,
|
||||||
|
values: CDNService.values.map((e) {
|
||||||
|
return {'title': e.description, 'value': e.code};
|
||||||
|
}).toList());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
defaultCDNService = result;
|
||||||
|
setting.put(SettingBoxKey.CDNService, result);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SetSwitchItem(
|
||||||
|
title: '音频不跟随 CDN 设置',
|
||||||
|
subTitle: '直接采用备用 URL,可解决部分视频无声',
|
||||||
|
leading: Icon(MdiIcons.musicNotePlus),
|
||||||
|
setKey: SettingBoxKey.disableAudioCDN,
|
||||||
defaultVal: true,
|
defaultVal: true,
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -117,7 +148,7 @@ class _VideoSettingState extends State<VideoSetting> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
dense: false,
|
dense: false,
|
||||||
title: Text('默认音质', style: titleStyle),
|
title: Text('默认音质', style: titleStyle),
|
||||||
leading: const Icon(Icons.audiotrack_outlined),
|
leading: const Icon(Icons.music_video_outlined),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
'当前音质:${AudioQualityCode.fromCode(defaultAudioQa)!.description!}',
|
'当前音质:${AudioQualityCode.fromCode(defaultAudioQa)!.description!}',
|
||||||
style: subTitleStyle,
|
style: subTitleStyle,
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class VideoDetailController extends GetxController
|
|||||||
Floating? floating;
|
Floating? floating;
|
||||||
late PreferredSizeWidget headerControl;
|
late PreferredSizeWidget headerControl;
|
||||||
|
|
||||||
late bool enableCDN;
|
// late bool enableCDN;
|
||||||
late int? cacheVideoQa;
|
late int? cacheVideoQa;
|
||||||
late String cacheDecode;
|
late String cacheDecode;
|
||||||
late String cacheSecondDecode;
|
late String cacheSecondDecode;
|
||||||
@@ -138,7 +138,8 @@ class VideoDetailController extends GetxController
|
|||||||
heroTag: heroTag,
|
heroTag: heroTag,
|
||||||
);
|
);
|
||||||
// CDN优化
|
// CDN优化
|
||||||
enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
// enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true);
|
||||||
|
|
||||||
// 预设的画质
|
// 预设的画质
|
||||||
cacheVideoQa = setting.get(SettingBoxKey.defaultVideoQa,
|
cacheVideoQa = setting.get(SettingBoxKey.defaultVideoQa,
|
||||||
defaultValue: VideoQuality.values.last.code);
|
defaultValue: VideoQuality.values.last.code);
|
||||||
@@ -388,9 +389,10 @@ class VideoDetailController extends GetxController
|
|||||||
(e) => e.codecs!.startsWith(currentDecodeFormats.code),
|
(e) => e.codecs!.startsWith(currentDecodeFormats.code),
|
||||||
orElse: () => videosList.first);
|
orElse: () => videosList.first);
|
||||||
|
|
||||||
videoUrl = enableCDN
|
// videoUrl = enableCDN
|
||||||
? VideoUtils.getCdnUrl(firstVideo)
|
// ? VideoUtils.getCdnUrl(firstVideo)
|
||||||
: (firstVideo.backupUrl ?? firstVideo.baseUrl!);
|
// : (firstVideo.backupUrl ?? firstVideo.baseUrl!);
|
||||||
|
videoUrl = VideoUtils.getCdnUrl(firstVideo);
|
||||||
|
|
||||||
/// 优先顺序 设置中指定质量 -> 当前可选的最高质量
|
/// 优先顺序 设置中指定质量 -> 当前可选的最高质量
|
||||||
late AudioItem? firstAudio;
|
late AudioItem? firstAudio;
|
||||||
@@ -415,9 +417,10 @@ class VideoDetailController extends GetxController
|
|||||||
}
|
}
|
||||||
firstAudio = audiosList.firstWhere((e) => e.id == closestNumber,
|
firstAudio = audiosList.firstWhere((e) => e.id == closestNumber,
|
||||||
orElse: () => audiosList.first);
|
orElse: () => audiosList.first);
|
||||||
audioUrl = enableCDN
|
// audioUrl = enableCDN
|
||||||
? VideoUtils.getCdnUrl(firstAudio)
|
// ? VideoUtils.getCdnUrl(firstAudio)
|
||||||
: (firstAudio.backupUrl ?? firstAudio.baseUrl!);
|
// : (firstAudio.backupUrl ?? firstAudio.baseUrl!);
|
||||||
|
audioUrl = VideoUtils.getCdnUrl(firstAudio);
|
||||||
if (firstAudio.id != null) {
|
if (firstAudio.id != null) {
|
||||||
currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!;
|
currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,9 @@ class SettingBoxKey {
|
|||||||
allowRotateScreen = 'allowRotateScreen',
|
allowRotateScreen = 'allowRotateScreen',
|
||||||
horizontalScreen = 'horizontalScreen',
|
horizontalScreen = 'horizontalScreen',
|
||||||
p1080 = 'p1080',
|
p1080 = 'p1080',
|
||||||
enableCDN = 'enableCDN',
|
CDNService = 'CDNService',
|
||||||
|
disableAudioCDN = 'disableAudioCDN',
|
||||||
|
// enableCDN = 'enableCDN',
|
||||||
autoPiP = 'autoPiP',
|
autoPiP = 'autoPiP',
|
||||||
pipNoDanmaku = 'pipNoDanmaku',
|
pipNoDanmaku = 'pipNoDanmaku',
|
||||||
enableAutoLongPressSpeed = 'enableAutoLongPressSpeed',
|
enableAutoLongPressSpeed = 'enableAutoLongPressSpeed',
|
||||||
|
|||||||
@@ -1,44 +1,101 @@
|
|||||||
|
import 'package:PiliPalaX/models/video/play/CDN.dart';
|
||||||
import 'package:PiliPalaX/models/video/play/url.dart';
|
import 'package:PiliPalaX/models/video/play/url.dart';
|
||||||
|
import 'package:PiliPalaX/utils/storage.dart';
|
||||||
|
|
||||||
import '../models/live/room_info.dart';
|
import '../models/live/room_info.dart';
|
||||||
|
|
||||||
class VideoUtils {
|
class VideoUtils {
|
||||||
static String getCdnUrl(dynamic item) {
|
static bool isMCDNorPCDN(String url) {
|
||||||
var backupUrl = "";
|
return url.contains("szbdyd.com") ||
|
||||||
var videoUrl = "";
|
url.contains(".mcdn.bilivideo") ||
|
||||||
|
RegExp(r'^https?://\d{1,3}\.\d{1,3}').hasMatch(url);
|
||||||
|
}
|
||||||
|
|
||||||
/// 先获取backupUrl 一般是upgcxcode地址 播放更稳定
|
static String getCdnUrl(dynamic item) {
|
||||||
if (item is VideoItem) {
|
String? backupUrl;
|
||||||
backupUrl = item.backupUrl ?? "";
|
String? videoUrl;
|
||||||
videoUrl = backupUrl.contains("http") ? backupUrl : (item.baseUrl ?? "");
|
String defaultCDNService = GStorage.setting
|
||||||
} else if (item is AudioItem) {
|
.get(SettingBoxKey.CDNService, defaultValue: CDNService.ali.code);
|
||||||
backupUrl = item.backupUrl ?? "";
|
if (item is AudioItem) {
|
||||||
videoUrl = backupUrl.contains("http") ? backupUrl : (item.baseUrl ?? "");
|
if (GStorage.setting
|
||||||
} else if (item is CodecItem) {
|
.get(SettingBoxKey.disableAudioCDN, defaultValue: true)) {
|
||||||
|
return item.backupUrl ?? item.baseUrl ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (defaultCDNService == CDNService.baseUrl.code) {
|
||||||
|
return item.baseUrl ?? "";
|
||||||
|
}
|
||||||
|
if (item is CodecItem) {
|
||||||
backupUrl = (item.urlInfo?.first.host)! +
|
backupUrl = (item.urlInfo?.first.host)! +
|
||||||
item.baseUrl! +
|
item.baseUrl! +
|
||||||
item.urlInfo!.first.extra!;
|
item.urlInfo!.first.extra!;
|
||||||
videoUrl = backupUrl.contains("http") ? backupUrl : (item.baseUrl ?? "");
|
|
||||||
} else {
|
} else {
|
||||||
|
backupUrl = item.backupUrl;
|
||||||
|
}
|
||||||
|
if (defaultCDNService == CDNService.backupUrl.code) {
|
||||||
|
return backupUrl ?? item.baseUrl ?? "";
|
||||||
|
}
|
||||||
|
videoUrl = (backupUrl == null || isMCDNorPCDN(backupUrl))
|
||||||
|
? item.baseUrl
|
||||||
|
: backupUrl;
|
||||||
|
|
||||||
|
if (videoUrl == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
print("videoUrl:$videoUrl");
|
||||||
|
|
||||||
/// issues #70
|
String defaultCDNHost = CDNServiceCode.fromCode(defaultCDNService)!.host;
|
||||||
if (videoUrl.contains(".mcdn.bilivideo")) {
|
print("defaultCDNHost:$defaultCDNHost");
|
||||||
|
if (videoUrl.contains("szbdyd.com")) {
|
||||||
|
String hostname =
|
||||||
|
Uri.parse(videoUrl).queryParameters['xy_usource'] ?? defaultCDNHost;
|
||||||
videoUrl =
|
videoUrl =
|
||||||
'https://proxy-tf-all-ws.bilivideo.com/?url=${Uri.encodeComponent(videoUrl)}';
|
Uri.parse(videoUrl).replace(host: hostname, port: 443).toString();
|
||||||
|
} else if (videoUrl.contains(".mcdn.bilivideo")) {
|
||||||
|
videoUrl = Uri.parse(videoUrl)
|
||||||
|
.replace(host: defaultCDNHost, port: 443)
|
||||||
|
.toString();
|
||||||
|
// videoUrl =
|
||||||
|
// 'https://proxy-tf-all-ws.bilivideo.com/?url=${Uri.encodeComponent(videoUrl)}';
|
||||||
} else if (videoUrl.contains("/upgcxcode/")) {
|
} else if (videoUrl.contains("/upgcxcode/")) {
|
||||||
//CDN列表
|
videoUrl = Uri.parse(videoUrl)
|
||||||
var cdnList = {
|
.replace(host: defaultCDNHost, port: 443)
|
||||||
'ali': 'upos-sz-mirrorali.bilivideo.com',
|
.toString();
|
||||||
'cos': 'upos-sz-mirrorcos.bilivideo.com',
|
|
||||||
'hw': 'upos-sz-mirrorhw.bilivideo.com',
|
|
||||||
};
|
|
||||||
//取一个CDN
|
|
||||||
var cdn = cdnList['ali'] ?? "";
|
|
||||||
var reg = RegExp(r'(http|https)://(.*?)/upgcxcode/');
|
|
||||||
videoUrl = videoUrl.replaceAll(reg, "https://$cdn/upgcxcode/");
|
|
||||||
}
|
}
|
||||||
|
print("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;
|
return videoUrl;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user