fix: 视频画质加载异常

This commit is contained in:
guozhigq
2023-08-11 11:45:33 +08:00
parent bc2e363d6a
commit 4458e13787
3 changed files with 72 additions and 58 deletions

View File

@ -29,7 +29,7 @@ class PlayUrlModel {
int? timeLength; int? timeLength;
String? acceptFormat; String? acceptFormat;
List<dynamic>? acceptDesc; List<dynamic>? acceptDesc;
List<dynamic>? acceptQuality; List<int>? acceptQuality;
int? videoCodecid; int? videoCodecid;
String? seekParam; String? seekParam;
String? seekType; String? seekType;
@ -48,7 +48,7 @@ class PlayUrlModel {
timeLength = json['timelength']; timeLength = json['timelength'];
acceptFormat = json['accept_format']; acceptFormat = json['accept_format'];
acceptDesc = json['accept_description']; acceptDesc = json['accept_description'];
acceptQuality = json['accept_quality']; acceptQuality = json['accept_quality'].map<int>((e) => e as int).toList();
videoCodecid = json['video_codecid']; videoCodecid = json['video_codecid'];
seekParam = json['seek_param']; seekParam = json['seek_param'];
seekType = json['seek_type']; seekType = json['seek_type'];

View File

@ -13,40 +13,47 @@ import 'package:pilipala/models/video/reply/item.dart';
import 'package:pilipala/pages/video/detail/replyReply/index.dart'; import 'package:pilipala/pages/video/detail/replyReply/index.dart';
import 'package:pilipala/plugin/pl_player/index.dart'; import 'package:pilipala/plugin/pl_player/index.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
import 'package:pilipala/utils/utils.dart';
class VideoDetailController extends GetxController class VideoDetailController extends GetxController
with GetSingleTickerProviderStateMixin { with GetSingleTickerProviderStateMixin {
int tabInitialIndex = 0; /// 路由传参
TabController? tabCtr;
// tabs
RxList<String> tabs = <String>['简介', '评论'].obs;
// 视频aid
String bvid = Get.parameters['bvid']!; String bvid = Get.parameters['bvid']!;
int cid = int.parse(Get.parameters['cid']!); int cid = int.parse(Get.parameters['cid']!);
// 视频类型 默认投稿视频 String heroTag = Get.arguments['heroTag'];
SearchType videoType = SearchType.video; // 视频详情
late PlayUrlModel data;
Box setting = GStrorage.setting;
// 当前画质
late VideoQuality currentVideoQa;
// 当前音质
late AudioQuality currentAudioQa;
// 当前解码格式
late VideoDecodeFormats currentDecodeFormats;
// 是否预渲染 骨架屏
bool preRender = false;
// 视频详情 上个页面传入
Map videoItem = {}; Map videoItem = {};
// 视频类型 默认投稿视频
SearchType videoType = Get.arguments['videoType'] ?? SearchType.video;
/// tabs相关配置
int tabInitialIndex = 0;
late TabController tabCtr;
RxList<String> tabs = <String>['简介', '评论'].obs;
// 请求返回的视频信息
late PlayUrlModel data;
// 请求状态 // 请求状态
RxBool isLoading = false.obs; RxBool isLoading = false.obs;
String heroTag = ''; /// 播放器配置 画质 音质 解码格式
late VideoQuality currentVideoQa;
late AudioQuality currentAudioQa;
late VideoDecodeFormats currentDecodeFormats;
PlPlayerController plPlayerController = PlPlayerController();
// 是否开始自动播放 存在多p的情况下第二p需要为true
RxBool autoPlay = true.obs;
// 视频资源是否有效
RxBool isEffective = true.obs;
// 封面图的展示
RxBool isShowCover = true.obs;
// 硬解
RxBool enableHA = true.obs;
/// 本地存储
Box user = GStrorage.user;
Box localCache = GStrorage.localCache;
Box setting = GStrorage.setting;
int oid = 0; int oid = 0;
// 评论id 请求楼中楼评论使用 // 评论id 请求楼中楼评论使用
@ -55,38 +62,27 @@ class VideoDetailController extends GetxController
ReplyItemModel? firstFloor; ReplyItemModel? firstFloor;
final scaffoldKey = GlobalKey<ScaffoldState>(); final scaffoldKey = GlobalKey<ScaffoldState>();
Timer? timer; Timer? timer;
RxString bgCover = ''.obs;
Box user = GStrorage.user;
Box localCache = GStrorage.localCache;
PlPlayerController plPlayerController = PlPlayerController();
// 是否开始自动播放 存在多p的情况下第二p需要为true
RxBool autoPlay = true.obs;
// 视频资源是否有效
RxBool isEffective = true.obs;
// 封面图的展示
RxBool isShowCover = true.obs;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
if (Get.arguments.isNotEmpty) { Map argMap = Get.arguments;
if (Get.arguments.containsKey('videoItem')) { var keys = argMap.keys.toList();
preRender = true; if (keys.isNotEmpty) {
var args = Get.arguments['videoItem']; if (keys.contains('videoItem')) {
var args = argMap['videoItem'];
if (args.pic != null && args.pic != '') { if (args.pic != null && args.pic != '') {
videoItem['pic'] = args.pic; videoItem['pic'] = args.pic;
bgCover.value = args.pic;
} }
} }
if (Get.arguments.containsKey('pic')) { if (keys.contains('pic')) {
videoItem['pic'] = Get.arguments['pic']; videoItem['pic'] = argMap['pic'];
bgCover.value = Get.arguments['pic'];
} }
heroTag = Get.arguments['heroTag'];
videoType = Get.arguments['videoType'] ?? SearchType.video;
} }
tabCtr = TabController(length: 2, vsync: this); tabCtr = TabController(length: 2, vsync: this);
// queryVideoUrl(); autoPlay.value =
setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true);
enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: true);
} }
showReplyReplyPanel() { showReplyReplyPanel() {
@ -123,7 +119,6 @@ class VideoDetailController extends GetxController
data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList(); data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList();
VideoItem firstVideo = videoList VideoItem firstVideo = videoList
.firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code));
// String videoUrl = firstVideo.baseUrl!;
/// 根据currentAudioQa 重新设置audioUrl /// 根据currentAudioQa 重新设置audioUrl
AudioItem firstAudio = AudioItem firstAudio =
@ -147,7 +142,7 @@ class VideoDetailController extends GetxController
}, },
), ),
// 硬解 // 硬解
enableHA: true, enableHA: enableHA.value,
autoplay: autoPlay.value, autoplay: autoPlay.value,
seekTo: defaultST, seekTo: defaultST,
duration: Duration(milliseconds: duration), duration: Duration(milliseconds: duration),
@ -180,8 +175,10 @@ class VideoDetailController extends GetxController
defaultValue: currentHighVideoQa); defaultValue: currentHighVideoQa);
int resVideoQa = currentHighVideoQa; int resVideoQa = currentHighVideoQa;
if (cacheVideoQa <= currentHighVideoQa) { if (cacheVideoQa <= currentHighVideoQa) {
// 如果默认设置的画质比当前可用的低,使用默认值 List<int> numbers = data.acceptQuality!
resVideoQa = cacheVideoQa; .where((e) => e <= currentHighVideoQa)
.toList();
resVideoQa = Utils.findClosestNumber(cacheVideoQa, numbers);
} }
currentVideoQa = VideoQualityCode.fromCode(resVideoQa)!; currentVideoQa = VideoQualityCode.fromCode(resVideoQa)!;
@ -208,16 +205,17 @@ class VideoDetailController extends GetxController
/// 优先顺序 设置中指定质量 -> 当前可选的最高质量 /// 优先顺序 设置中指定质量 -> 当前可选的最高质量
late AudioItem firstAudio; late AudioItem firstAudio;
List audiosList = data.dash!.audio!;
try { try {
if (data.dash!.audio!.isNotEmpty) { if (audiosList.isNotEmpty) {
firstAudio = data.dash!.audio!.first; firstAudio = audiosList.first;
int resultAudioQa = setting.get(SettingBoxKey.defaultAudioQa, int resultAudioQa = setting.get(SettingBoxKey.defaultAudioQa,
defaultValue: data.dash!.audio!.first.id); defaultValue: firstAudio.id);
// 选择最接近的那个音轨 // 选择最接近的那个音轨
try { firstAudio = audiosList.firstWhere(
firstAudio = (e) => e.id == resultAudioQa,
data.dash!.audio!.firstWhere((e) => e.id == resultAudioQa); orElse: () => AudioItem(),
} catch (_) {} );
} else { } else {
firstAudio = AudioItem(); firstAudio = AudioItem();
} }

View File

@ -162,4 +162,20 @@ class Utils {
} }
return 0; return 0;
} }
static int findClosestNumber(int target, List<int> numbers) {
int minDiff = 127;
late int closestNumber;
try {
for (int number in numbers) {
int diff = (number - target).abs();
if (diff < minDiff) {
minDiff = diff;
closestNumber = number;
}
}
} catch (_) {}
return closestNumber;
}
} }