diff --git a/lib/models/live/quality.dart b/lib/models/live/quality.dart new file mode 100644 index 00000000..47938416 --- /dev/null +++ b/lib/models/live/quality.dart @@ -0,0 +1,43 @@ +enum LiveQuality { + dolby, + super4K, + origin, + veryHigh, + bluRay, + superHD, + smooth, + flunt, +} + +extension LiveQualityCode on LiveQuality { + static final List _codeList = [ + 30000, + 20000, + 10000, + 400, + 250, + 150, + 80, + ]; + int get code => _codeList[index]; + + static LiveQuality? fromCode(int code) { + final index = _codeList.indexOf(code); + if (index != -1) { + return LiveQuality.values[index]; + } + return null; + } +} + +extension VideoQualityDesc on LiveQuality { + static final List _descList = [ + '杜比', + '4K', + '原画', + '蓝光', + '超清', + '流畅', + ]; + get description => _descList[index]; +} diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index 2bb1cd0a..a1878c74 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -1,6 +1,7 @@ import 'package:get/get.dart'; import 'package:pilipala/http/constants.dart'; import 'package:pilipala/http/live.dart'; +import 'package:pilipala/models/live/quality.dart'; import 'package:pilipala/models/live/room_info.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; import '../../models/live/room_info_h5.dart'; @@ -19,10 +20,14 @@ class LiveRoomController extends GetxController { PlPlayerController.getInstance(videoType: 'live'); Rx roomInfoH5 = RoomInfoH5Model().obs; late bool enableCDN; + late int currentQn; + late List> acceptQnList; + RxString currentQnDesc = ''.obs; @override void onInit() { super.onInit(); + currentQn = 10000; roomId = int.parse(Get.parameters['roomid']!); if (Get.arguments != null) { liveItem = Get.arguments['liveItem']; @@ -57,11 +62,26 @@ class LiveRoomController extends GetxController { } Future queryLiveInfo() async { - var res = await LiveHttp.liveRoomInfo(roomId: roomId, qn: 10000); + /// TODO 默认获取预设质量的直播资源 + var res = await LiveHttp.liveRoomInfo(roomId: roomId, qn: currentQn); if (res['status']) { List codec = res['data'].playurlInfo.playurl.stream.first.format.first.codec; CodecItem item = codec.first; + // 以服务端返回的码率为准 + currentQn = item.currentQn!; + List acceptQn = item.acceptQn!; + acceptQnList = acceptQn.map((e) { + return { + 'code': e, + 'desc': LiveQuality.values + .firstWhere((element) => element.code == e) + .description, + }; + }).toList(); + currentQnDesc.value = LiveQuality.values + .firstWhere((element) => element.code == currentQn) + .description; String videoUrl = enableCDN ? VideoUtils.getCdnUrl(item) : (item.urlInfo?.first.host)! + @@ -90,4 +110,16 @@ class LiveRoomController extends GetxController { } return res; } + + // 修改画质 + void changeQn(int qn) async { + if (currentQn == qn) { + return; + } + currentQn = qn; + currentQnDesc.value = LiveQuality.values + .firstWhere((element) => element.code == currentQn) + .description; + await queryLiveInfo(); + } } diff --git a/lib/pages/live_room/widgets/bottom_control.dart b/lib/pages/live_room/widgets/bottom_control.dart index a00f3d92..0dcedc2c 100644 --- a/lib/pages/live_room/widgets/bottom_control.dart +++ b/lib/pages/live_room/widgets/bottom_control.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:floating/floating.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/models/video/play/url.dart'; import 'package:pilipala/pages/live_room/index.dart'; @@ -113,6 +114,30 @@ class _BottomControlState extends State { ), const SizedBox(width: 4), ], + SizedBox( + width: 30, + child: PopupMenuButton( + padding: EdgeInsets.zero, + onSelected: (value) { + widget.liveRoomCtr!.changeQn(value); + }, + child: Obx( + () => Text( + widget.liveRoomCtr!.currentQnDesc.value, + style: const TextStyle(color: Colors.white, fontSize: 13), + ), + ), + itemBuilder: (BuildContext context) { + return widget.liveRoomCtr!.acceptQnList.map((e) { + return PopupMenuItem( + value: e['code'], + child: Text(e['desc']), + ); + }).toList(); + }, + ), + ), + const SizedBox(width: 10), ComBtn( icon: const Icon( Icons.fullscreen,