From b12b0b0d085a3e4444dbdf00644e4ca1c92fb4e0 Mon Sep 17 00:00:00 2001 From: orz12 Date: Thu, 7 Mar 2024 13:27:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=88=86=E4=B8=BA=E9=A6=96=E9=80=89=E5=92=8C=E6=AC=A1=E9=80=89?= =?UTF-8?q?=EF=BC=8C=E8=B0=83=E6=95=B4=E9=83=A8=E5=88=86=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/setting/play_setting.dart | 39 +++++++++++-- lib/pages/video/detail/controller.dart | 81 +++++++++++++++++++------- lib/utils/storage.dart | 1 + 3 files changed, 95 insertions(+), 26 deletions(-) diff --git a/lib/pages/setting/play_setting.dart b/lib/pages/setting/play_setting.dart index 1af808c7..153687b4 100644 --- a/lib/pages/setting/play_setting.dart +++ b/lib/pages/setting/play_setting.dart @@ -24,6 +24,7 @@ class _PlaySettingState extends State { late dynamic defaultVideoQa; late dynamic defaultAudioQa; late dynamic defaultDecode; + late dynamic secondDecode; late String defaultSubtitlePreference; late int defaultFullScreenMode; late int defaultBtmProgressBehavior; @@ -37,6 +38,8 @@ class _PlaySettingState extends State { defaultValue: AudioQuality.values.last.code); defaultDecode = setting.get(SettingBoxKey.defaultDecode, defaultValue: VideoDecodeFormats.values.last.code); + secondDecode = setting.get(SettingBoxKey.secondDecode, + defaultValue: VideoDecodeFormats.values[1].code); defaultFullScreenMode = setting.get(SettingBoxKey.fullScreenMode, defaultValue: FullScreenMode.values.first.code); defaultBtmProgressBehavior = setting.get(SettingBoxKey.btmProgressBehavior, @@ -163,7 +166,7 @@ class _PlaySettingState extends State { dense: false, title: Text('默认画质', style: titleStyle), subtitle: Text( - '当前画质${VideoQualityCode.fromCode(defaultVideoQa)!.description!}', + '当前画质:${VideoQualityCode.fromCode(defaultVideoQa)!.description!}', style: subTitleStyle, ), onTap: () async { @@ -189,7 +192,7 @@ class _PlaySettingState extends State { dense: false, title: Text('默认音质', style: titleStyle), subtitle: Text( - '当前音质${AudioQualityCode.fromCode(defaultAudioQa)!.description!}', + '当前音质:${AudioQualityCode.fromCode(defaultAudioQa)!.description!}', style: subTitleStyle, ), onTap: () async { @@ -213,9 +216,9 @@ class _PlaySettingState extends State { ), ListTile( dense: false, - title: Text('默认解码格式', style: titleStyle), + title: Text('首选解码格式', style: titleStyle), subtitle: Text( - '当前解码格式${VideoDecodeFormatsCode.fromCode(defaultDecode)!.description!}', + '首选解码格式:${VideoDecodeFormatsCode.fromCode(defaultDecode)!.description!},请根据设备支持情况与需求调整', style: subTitleStyle, ), onTap: () async { @@ -237,9 +240,35 @@ class _PlaySettingState extends State { } }, ), + ListTile( + dense: false, + title: Text('次选解码格式', style: titleStyle), + subtitle: Text( + '非杜比视频次选:${VideoDecodeFormatsCode.fromCode(secondDecode)!.description!},仍无则选择首个提供的解码格式', + style: subTitleStyle, + ), + onTap: () async { + String? result = await showDialog( + context: context, + builder: (context) { + return SelectDialog( + title: '次选解码格式', + value: secondDecode, + values: VideoDecodeFormats.values.map((e) { + return {'title': e.description, 'value': e.code}; + }).toList()); + }, + ); + if (result != null) { + secondDecode = result; + setting.put(SettingBoxKey.secondDecode, result); + setState(() {}); + } + }, + ), const SetSwitchItem( title: '开启硬解', - subTitle: '以较低功耗播放视频', + subTitle: '以较低功耗播放视频,若使用中异常卡死,请尝试关闭', setKey: SettingBoxKey.enableHA, defaultVal: true, ), diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 43768713..8a9436ea 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -88,6 +88,7 @@ class VideoDetailController extends GetxController late bool enableCDN; late int? cacheVideoQa; late String cacheDecode; + late String cacheSecondDecode; late int cacheAudioQa; PersistentBottomSheetController? replyReplyBottomSheetCtr; @@ -136,6 +137,8 @@ class VideoDetailController extends GetxController // 预设的解码格式 cacheDecode = setting.get(SettingBoxKey.defaultDecode, defaultValue: VideoDecodeFormats.values.last.code); + cacheSecondDecode = setting.get(SettingBoxKey.secondDecode, + defaultValue: VideoDecodeFormats.values[1].code); cacheAudioQa = setting.get(SettingBoxKey.defaultAudioQa, defaultValue: AudioQuality.hiRes.code); oid.value = IdUtils.bv2av(Get.parameters['bvid']!); @@ -172,23 +175,52 @@ class VideoDetailController extends GetxController /// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl List videoList = data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList(); + + final List supportDecodeFormats = videoList.map((e) => e.codecs!).toList(); + VideoDecodeFormats defaultDecodeFormats = + VideoDecodeFormatsCode.fromString(cacheDecode)!; + VideoDecodeFormats secondDecodeFormats = + VideoDecodeFormatsCode.fromString(cacheSecondDecode)!; try { - firstVideo = videoList - .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); - } catch (_) { - if (currentVideoQa == VideoQuality.dolbyVision) { - firstVideo = videoList.first; - currentDecodeFormats = - VideoDecodeFormatsCode.fromString(videoList.first.codecs!)!; - } else { - // 当前格式不可用 - currentDecodeFormats = VideoDecodeFormatsCode.fromString(setting.get( - SettingBoxKey.defaultDecode, - defaultValue: VideoDecodeFormats.values.last.code))!; - firstVideo = videoList - .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); + // 当前视频没有对应格式返回第一个 + int flag = 0; + for (var i in supportDecodeFormats) { + if (i.startsWith(currentDecodeFormats.code)) { + flag = 1; + break; + } else if (i.startsWith(defaultDecodeFormats.code)) { + flag += 2; + } else if (i.startsWith(secondDecodeFormats.code)) { + flag += 4; + } } + if (flag == 1) {//currentDecodeFormats + firstVideo = videoList.first; + } else { + if (currentVideoQa == VideoQuality.dolbyVision) { + currentDecodeFormats = + VideoDecodeFormatsCode.fromString(videoList.first.codecs!)!; + firstVideo = videoList.first; + } else if (flag == 2 || flag == 6) {//defaultDecodeFormats + currentDecodeFormats = defaultDecodeFormats; + firstVideo = videoList.firstWhere( + (i) => i.codecs!.startsWith(defaultDecodeFormats.code), + ); + } else if (flag == 4) {//secondDecodeFormats + currentDecodeFormats = secondDecodeFormats; + firstVideo = videoList.firstWhere( + (i) => i.codecs!.startsWith(secondDecodeFormats.code), + ); + } else if (flag == 0) { + currentDecodeFormats = + VideoDecodeFormatsCode.fromString(supportDecodeFormats.first)!; + firstVideo = videoList.first; + } + } + } catch (err) { + SmartDialog.showToast('DecodeFormats error: $err'); } + videoUrl = firstVideo.baseUrl!; /// 根据currentAudioQa 重新设置audioUrl @@ -292,23 +324,30 @@ class VideoDetailController extends GetxController // 根据画质选编码格式 final List supportDecodeFormats = supportFormats.firstWhere((e) => e.quality == resVideoQa).codecs!; - // 默认从设置中取AVC + // 默认从设置中取AV1 currentDecodeFormats = VideoDecodeFormatsCode.fromString(cacheDecode)!; + VideoDecodeFormats secondDecodeFormats = + VideoDecodeFormatsCode.fromString(cacheSecondDecode)!; try { // 当前视频没有对应格式返回第一个 - bool flag = false; + int flag = 0; for (var i in supportDecodeFormats) { if (i.startsWith(currentDecodeFormats.code)) { - flag = true; + flag = 1; + break; + } else if (i.startsWith(secondDecodeFormats.code)) { + flag += 2; } } - currentDecodeFormats = flag - ? currentDecodeFormats - : VideoDecodeFormatsCode.fromString(supportDecodeFormats.first)!; + if (flag == 2) { + currentDecodeFormats = secondDecodeFormats; + } else if (flag == 0) { + currentDecodeFormats = + VideoDecodeFormatsCode.fromString(supportDecodeFormats.first)!; + } } catch (err) { SmartDialog.showToast('DecodeFormats error: $err'); } - /// 取出符合当前解码格式的videoItem try { firstVideo = videosList.firstWhere( diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index e1d64fd2..26e83481 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -82,6 +82,7 @@ class SettingBoxKey { autoPlayEnable = 'autoPlayEnable', fullScreenMode = 'fullScreenMode', defaultDecode = 'defaultDecode', + secondDecode = 'secondDecode', danmakuEnable = 'danmakuEnable', defaultToastOp = 'defaultToastOp', defaultPicQa = 'defaultPicQa',