Merge branch 'feature-media_kit' into alpha

This commit is contained in:
guozhigq
2023-08-08 16:39:54 +08:00
4 changed files with 85 additions and 51 deletions

View File

@ -14,7 +14,7 @@ class LiveRoomController extends GetxController {
// 静音状态 // 静音状态
RxBool volumeOff = false.obs; RxBool volumeOff = false.obs;
PlPlayerController plPlayerController = PlPlayerController plPlayerController =
PlPlayerController(controlsEnabled: false); PlPlayerController.getInstance(controlsEnabled: false);
// MeeduPlayerController meeduPlayerController = MeeduPlayerController( // MeeduPlayerController meeduPlayerController = MeeduPlayerController(
// colorTheme: Theme.of(Get.context!).colorScheme.primary, // colorTheme: Theme.of(Get.context!).colorScheme.primary,

View File

@ -54,7 +54,7 @@ class VideoDetailController extends GetxController
RxString bgCover = ''.obs; RxString bgCover = ''.obs;
Box user = GStrorage.user; Box user = GStrorage.user;
Box localCache = GStrorage.localCache; Box localCache = GStrorage.localCache;
PlPlayerController plPlayerController = PlPlayerController(); PlPlayerController plPlayerController = PlPlayerController.getInstance();
// 是否开始自动播放 存在多p的情况下第二p需要为true // 是否开始自动播放 存在多p的情况下第二p需要为true
RxBool autoPlay = true.obs; RxBool autoPlay = true.obs;
// 视频资源是否有效 // 视频资源是否有效
@ -62,6 +62,11 @@ class VideoDetailController extends GetxController
// 封面图的展示 // 封面图的展示
RxBool isShowCover = true.obs; RxBool isShowCover = true.obs;
late VideoItem firstVideo;
late String videoUrl;
late String audioUrl;
late Duration defaultST;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
@ -107,7 +112,7 @@ class VideoDetailController extends GetxController
/// 更新画质、音质 /// 更新画质、音质
/// TODO 继续进度播放 /// TODO 继续进度播放
updatePlayer() { updatePlayer() {
Duration position = plPlayerController.position.value; defaultST = plPlayerController.position.value;
plPlayerController.removeListeners(); plPlayerController.removeListeners();
plPlayerController.isBuffering.value = false; plPlayerController.isBuffering.value = false;
plPlayerController.buffered.value = Duration.zero; plPlayerController.buffered.value = Duration.zero;
@ -115,24 +120,23 @@ class VideoDetailController extends GetxController
/// 暂不匹配解码规则 /// 暂不匹配解码规则
/// 根据currentVideoQa 重新设置videoUrl /// 根据currentVideoQa 重新设置videoUrl
VideoItem firstVideo = firstVideo =
data.dash!.video!.firstWhere((i) => i.id == currentVideoQa.code); data.dash!.video!.firstWhere((i) => i.id == currentVideoQa.code);
// String videoUrl = firstVideo.baseUrl!; videoUrl = firstVideo.baseUrl!;
/// 根据currentAudioQa 重新设置audioUrl /// 根据currentAudioQa 重新设置audioUrl
AudioItem firstAudio = AudioItem firstAudio =
data.dash!.audio!.firstWhere((i) => i.id == currentAudioQa.code); data.dash!.audio!.firstWhere((i) => i.id == currentAudioQa.code);
String audioUrl = firstAudio.baseUrl ?? ''; audioUrl = firstAudio.baseUrl ?? '';
playerInit(firstVideo, audioUrl, defaultST: position); playerInit();
} }
Future playerInit(firstVideo, audioSource, Future playerInit({video, audio, seekToTime, duration}) async {
{Duration defaultST = Duration.zero, int duration = 0}) async {
await plPlayerController.setDataSource( await plPlayerController.setDataSource(
DataSource( DataSource(
videoSource: firstVideo.baseUrl, videoSource: video ?? videoUrl,
audioSource: audioSource, audioSource: audio ?? audioUrl,
type: DataSourceType.network, type: DataSourceType.network,
httpHeaders: { httpHeaders: {
'user-agent': 'user-agent':
@ -143,11 +147,14 @@ class VideoDetailController extends GetxController
// 硬解 // 硬解
enableHA: true, enableHA: true,
autoplay: autoPlay.value, autoplay: autoPlay.value,
seekTo: defaultST, seekTo: seekToTime ?? defaultST,
duration: Duration(milliseconds: duration), duration: duration ?? Duration(milliseconds: data.timeLength ?? 0),
// 宽>高 水平 否则 垂直 // 宽>高 水平 否则 垂直
direction: direction: (firstVideo.width! - firstVideo.height!) > 0
firstVideo.width - firstVideo.height > 0 ? 'horizontal' : 'vertical', ? 'horizontal'
: 'vertical',
// 默认1倍速
speed: 1.0,
); );
} }
@ -163,25 +170,21 @@ class VideoDetailController extends GetxController
data = result['data']; data = result['data'];
/// 优先顺序 省流模式 -> 设置中指定质量 -> 当前可选的最高质量 /// 优先顺序 省流模式 -> 设置中指定质量 -> 当前可选的最高质量
VideoItem firstVideo = data.dash!.video!.first; firstVideo = data.dash!.video!.first;
// String videoUrl = firstVideo.baseUrl!; videoUrl = firstVideo.baseUrl!;
// //
currentVideoQa = VideoQualityCode.fromCode(firstVideo.id!)!; currentVideoQa = VideoQualityCode.fromCode(firstVideo.id!)!;
/// 优先顺序 设置中指定质量 -> 当前可选的最高质量 /// 优先顺序 设置中指定质量 -> 当前可选的最高质量
AudioItem firstAudio = AudioItem firstAudio =
data.dash!.audio!.isNotEmpty ? data.dash!.audio!.first : AudioItem(); data.dash!.audio!.isNotEmpty ? data.dash!.audio!.first : AudioItem();
String audioUrl = firstAudio.baseUrl ?? ''; audioUrl = firstAudio.baseUrl ?? '';
// //
if (firstAudio.id != null) { if (firstAudio.id != null) {
currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!; currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!;
} }
await playerInit( defaultST = Duration(milliseconds: data.lastPlayTime!);
firstVideo, await playerInit();
audioUrl,
defaultST: Duration(milliseconds: data.lastPlayTime!),
duration: data.timeLength ?? 0,
);
} else { } else {
SmartDialog.showToast(result['msg'].toString()); SmartDialog.showToast(result['msg'].toString());
} }

View File

@ -49,8 +49,25 @@ class _VideoDetailPageState extends State<VideoDetailPage>
void initState() { void initState() {
super.initState(); super.initState();
plPlayerController = videoDetailController.plPlayerController; plPlayerController = videoDetailController.plPlayerController;
playerListener();
appbarStream = StreamController<double>();
_extendNestCtr.addListener(
() {
double offset = _extendNestCtr.position.pixels;
appbarStream.add(offset);
},
);
statusBarHeight = localCache.get('statusBarHeight');
_futureBuilderFuture = videoDetailController.queryVideoUrl();
}
// 播放器状态监听
void playerListener() {
plPlayerController!.onPlayerStatusChanged.listen( plPlayerController!.onPlayerStatusChanged.listen(
(PlayerStatus status) { (PlayerStatus status) async {
videoDetailController.markHeartBeat(); videoDetailController.markHeartBeat();
playerStatus = status; playerStatus = status;
if (status == PlayerStatus.playing) { if (status == PlayerStatus.playing) {
@ -68,18 +85,6 @@ class _VideoDetailPageState extends State<VideoDetailPage>
} }
}, },
); );
appbarStream = StreamController<double>();
_extendNestCtr.addListener(
() {
double offset = _extendNestCtr.position.pixels;
appbarStream.add(offset);
},
);
statusBarHeight = localCache.get('statusBarHeight');
_futureBuilderFuture = videoDetailController.queryVideoUrl();
} }
// 继续播放或重新播放 // 继续播放或重新播放
@ -104,6 +109,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
if (videoDetailController.timer!.isActive) { if (videoDetailController.timer!.isActive) {
videoDetailController.timer!.cancel(); videoDetailController.timer!.cancel();
} }
videoDetailController.defaultST = plPlayerController!.position.value;
plPlayerController!.pause(); plPlayerController!.pause();
super.didPushNext(); super.didPushNext();
} }
@ -111,6 +117,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
@override @override
// 返回当前页面时 // 返回当前页面时
void didPopNext() async { void didPopNext() async {
videoDetailController.playerInit();
if (_extendNestCtr.position.pixels == 0) { if (_extendNestCtr.position.pixels == 0) {
await Future.delayed(const Duration(milliseconds: 300)); await Future.delayed(const Duration(milliseconds: 300));
plPlayerController!.play(); plPlayerController!.play();

View File

@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:media_kit/media_kit.dart'; import 'package:media_kit/media_kit.dart';
@ -13,7 +12,7 @@ import 'package:pilipala/utils/storage.dart';
import 'package:screen_brightness/screen_brightness.dart'; import 'package:screen_brightness/screen_brightness.dart';
import 'package:universal_platform/universal_platform.dart'; import 'package:universal_platform/universal_platform.dart';
import 'package:volume_controller/volume_controller.dart'; import 'package:volume_controller/volume_controller.dart';
import 'package:wakelock_plus/wakelock_plus.dart'; // import 'package:wakelock_plus/wakelock_plus.dart';
import 'models/data_status.dart'; import 'models/data_status.dart';
import 'models/play_speed.dart'; import 'models/play_speed.dart';
@ -25,6 +24,9 @@ class PlPlayerController {
Player? _videoPlayerController; Player? _videoPlayerController;
VideoController? _videoController; VideoController? _videoController;
// 添加一个私有静态变量来保存实例
static PlPlayerController? _instance;
// 流事件 监听播放状态变化 // 流事件 监听播放状态变化
StreamSubscription? _playerEventSubs; StreamSubscription? _playerEventSubs;
@ -44,6 +46,8 @@ class PlPlayerController {
final Rx<Duration> _duration = Rx(Duration.zero); final Rx<Duration> _duration = Rx(Duration.zero);
final Rx<Duration> _buffered = Rx(Duration.zero); final Rx<Duration> _buffered = Rx(Duration.zero);
final Rx<int> _playerCount = Rx(0);
final Rx<double> _playbackSpeed = 1.0.obs; final Rx<double> _playbackSpeed = 1.0.obs;
final Rx<double> _currentVolume = 1.0.obs; final Rx<double> _currentVolume = 1.0.obs;
final Rx<double> _currentBrightness = 0.0.obs; final Rx<double> _currentBrightness = 0.0.obs;
@ -172,10 +176,24 @@ class PlPlayerController {
/// 全屏方向 /// 全屏方向
Rx<String> get direction => _direction; Rx<String> get direction => _direction;
PlPlayerController({ Rx<int> get playerCount => _playerCount;
// 直播间 传false 关闭控制栏
this.controlsEnabled = true, // 添加一个私有构造函数
this.fits = const [ PlPlayerController._() {
controlsEnabled = controlsEnabled;
// _playerEventSubs = onPlayerStatusChanged.listen((PlayerStatus status) {
// if (status == PlayerStatus.playing) {
// WakelockPlus.enable();
// } else {
// WakelockPlus.disable();
// }
// });
}
// 获取实例 传参
static PlPlayerController getInstance({
bool controlsEnabled = true,
List<BoxFit> fits = const [
BoxFit.contain, BoxFit.contain,
BoxFit.cover, BoxFit.cover,
BoxFit.fill, BoxFit.fill,
@ -184,14 +202,10 @@ class PlPlayerController {
BoxFit.scaleDown BoxFit.scaleDown
], ],
}) { }) {
controlsEnabled = controlsEnabled; // 如果实例尚未创建,则创建一个新实例
_playerEventSubs = onPlayerStatusChanged.listen((PlayerStatus status) { _instance ??= PlPlayerController._();
if (status == PlayerStatus.playing) { _instance!._playerCount.value += 1;
WakelockPlus.enable(); return _instance!;
} else {
WakelockPlus.enable();
}
});
} }
// 初始化资源 // 初始化资源
@ -258,6 +272,9 @@ class PlPlayerController {
double? width, double? width,
double? height, double? height,
) async { ) async {
// 每次配置时先移除监听
removeListeners();
Player player = _videoPlayerController ?? Player player = _videoPlayerController ??
Player( Player(
configuration: const PlayerConfiguration( configuration: const PlayerConfiguration(
@ -663,6 +680,12 @@ class PlPlayerController {
} }
Future<void> dispose() async { Future<void> dispose() async {
// 每次减1最后销毁
_playerCount.value -= 1;
if (playerCount.value > 0) {
return;
}
_timer?.cancel(); _timer?.cancel();
_timerForVolume?.cancel(); _timerForVolume?.cancel();
_timerForGettingVolume?.cancel(); _timerForGettingVolume?.cancel();
@ -685,5 +708,6 @@ class PlPlayerController {
removeListeners(); removeListeners();
await _videoPlayerController?.dispose(); await _videoPlayerController?.dispose();
_videoPlayerController = null; _videoPlayerController = null;
_instance = null;
} }
} }