diff --git a/lib/models/video/play/url.dart b/lib/models/video/play/url.dart index 26363663..71894406 100644 --- a/lib/models/video/play/url.dart +++ b/lib/models/video/play/url.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:pilipala/models/video/play/quality.dart'; class PlayUrlModel { @@ -77,8 +79,8 @@ class Dash { double? minBufferTime; List? video; List? audio; - Map? dolby; - Map? flac; + Dolby? dolby; + Flac? flac; Dash.fromJson(Map json) { duration = json['duration']; @@ -87,8 +89,8 @@ class Dash { audio = json['audio'] != null ? json['audio'].map((e) => AudioItem.fromJson(e)).toList() : []; - dolby = json['dolby']; - flac = json['flac'] ?? {}; + dolby = json['dolby'] != null ? Dolby.fromJson(json['dolby']) : null; + flac = json['flac'] != null ? Flac.fromJson(json['flac']) : null; } } @@ -220,3 +222,33 @@ class FormatItem { codecs = json['codecs']; } } + +class Dolby { + Dolby({ + this.type, + this.audio, + }); + + // 1:普通杜比音效 2:全景杜比音效 + int? type; + List? audio; + + Dolby.fromJson(Map json) { + type = json['type']; + audio = json['audio'] != null + ? json['audio'].map((e) => AudioItem.fromJson(e)).toList() + : []; + } +} + +class Flac { + Flac({this.display, this.audio}); + + bool? display; + AudioItem? audio; + + Flac.fromJson(Map json) { + display = json['display']; + audio = json['audio'] != null ? AudioItem.fromJson(json['audio']) : null; + } +} diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 27cf35c2..dca500f7 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -65,6 +65,7 @@ class VideoDetailController extends GetxController PlPlayerController plPlayerController = PlPlayerController.getInstance(); late VideoItem firstVideo; + late AudioItem firstAudio; late String videoUrl; late String audioUrl; late Duration defaultST; @@ -130,13 +131,6 @@ class VideoDetailController extends GetxController plPlayerController.isBuffering.value = false; plPlayerController.buffered.value = Duration.zero; - /// 暂不匹配解码规则 - - /// 根据currentVideoQa 重新设置videoUrl - // firstVideo = - // data.dash!.video!.firstWhere((i) => i.id == currentVideoQa.code); - // videoUrl = firstVideo.baseUrl!; - /// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl List videoList = data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList(); @@ -144,19 +138,27 @@ class VideoDetailController extends GetxController firstVideo = videoList .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); } catch (_) { - // 当前格式不可用 - currentDecodeFormats = VideoDecodeFormatsCode.fromString(setting.get( - SettingBoxKey.defaultDecode, - defaultValue: VideoDecodeFormats.values.last.code))!; - firstVideo = videoList - .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); + 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)); + } } videoUrl = firstVideo.baseUrl!; /// 根据currentAudioQa 重新设置audioUrl if (currentAudioQa != null) { - AudioItem firstAudio = - data.dash!.audio!.firstWhere((i) => i.id == currentAudioQa!.code); + AudioItem firstAudio = data.dash!.audio!.firstWhere( + (i) => i.id == currentAudioQa!.code, + orElse: () => data.dash!.audio!.first, + ); audioUrl = firstAudio.baseUrl ?? ''; } @@ -263,24 +265,33 @@ class VideoDetailController extends GetxController } /// 优先顺序 设置中指定质量 -> 当前可选的最高质量 - late AudioItem firstAudio; - List audiosList = data.dash!.audio!; - try { - if (audiosList.isNotEmpty) { - firstAudio = audiosList.first; - int resultAudioQa = setting.get(SettingBoxKey.defaultAudioQa, - defaultValue: firstAudio.id); - // 选择最接近的那个音轨 - firstAudio = audiosList.firstWhere( - (e) => e.id == resultAudioQa, - orElse: () => AudioItem(), - ); - } else { - firstAudio = AudioItem(); - } - } catch (_) {} + late AudioItem? firstAudio; + List audiosList = data.dash!.audio!; - audioUrl = firstAudio.baseUrl ?? ''; + try { + int resultAudioQa = setting.get(SettingBoxKey.defaultAudioQa, + defaultValue: AudioQuality.hiRes.code); + + if (data.dash!.dolby?.audio?.isNotEmpty == true) { + // 杜比 + audiosList.insert(0, data.dash!.dolby!.audio!.first); + } + + if (data.dash!.flac?.audio != null) { + // 无损 + audiosList.insert(0, data.dash!.flac!.audio!); + } + + if (audiosList.isNotEmpty) { + List numbers = audiosList.map((map) => map.id!).toList(); + int closestNumber = Utils.findClosestNumber(resultAudioQa, numbers); + firstAudio = audiosList.firstWhere((e) => e.id == closestNumber); + } + } catch (e) { + print(e); + } + + audioUrl = firstAudio!.baseUrl ?? ''; // if (firstAudio.id != null) { currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!; diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index 0a84a193..9d98c52c 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -4,7 +4,6 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; import 'package:pilipala/models/video/play/quality.dart'; import 'package:pilipala/models/video/play/url.dart'; -import 'package:pilipala/pages/main/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; @@ -276,6 +275,10 @@ class _HeaderControlState extends State { for (var i = 0; i < totalQaSam; i++) ...[ ListTile( onTap: () { + if (currentVideoQa.code == + videoFormat[i].quality) { + return; + } final int quality = videoFormat[i].quality!; widget.videoDetailCtr!.currentVideoQa = VideoQualityCode.fromCode(quality)!; @@ -345,6 +348,7 @@ class _HeaderControlState extends State { for (var i in audio) ...[ ListTile( onTap: () { + if (currentAudioQa.code == i.id) return; final int quality = i.id!; widget.videoDetailCtr!.currentAudioQa = AudioQualityCode.fromCode(quality)!; @@ -416,6 +420,7 @@ class _HeaderControlState extends State { for (var i in list) ...[ ListTile( onTap: () { + if (i.startsWith(currentDecodeFormats.code)) return; widget.videoDetailCtr!.currentDecodeFormats = VideoDecodeFormatsCode.fromString(i)!; widget.videoDetailCtr!.updatePlayer();