From add1e6e2ebaee53ecbf9564bc05eade70b6f824f Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 8 Aug 2023 16:38:36 +0800 Subject: [PATCH] =?UTF-8?q?mod:=20=E8=A7=86=E9=A2=91=E5=8D=95=E4=BE=8B?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/liveRoom/controller.dart | 2 +- lib/pages/video/detail/controller.dart | 49 ++++++++++++------------ lib/pages/video/detail/view.dart | 33 +++++++++------- lib/plugin/pl_player/controller.dart | 52 +++++++++++++++++++------- 4 files changed, 85 insertions(+), 51 deletions(-) diff --git a/lib/pages/liveRoom/controller.dart b/lib/pages/liveRoom/controller.dart index 51ffd7a2..b4042e17 100644 --- a/lib/pages/liveRoom/controller.dart +++ b/lib/pages/liveRoom/controller.dart @@ -14,7 +14,7 @@ class LiveRoomController extends GetxController { // 静音状态 RxBool volumeOff = false.obs; PlPlayerController plPlayerController = - PlPlayerController(controlsEnabled: false); + PlPlayerController.getInstance(controlsEnabled: false); // MeeduPlayerController meeduPlayerController = MeeduPlayerController( // colorTheme: Theme.of(Get.context!).colorScheme.primary, diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index adbedcba..dc24df06 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -54,7 +54,7 @@ class VideoDetailController extends GetxController RxString bgCover = ''.obs; Box user = GStrorage.user; Box localCache = GStrorage.localCache; - PlPlayerController plPlayerController = PlPlayerController(); + PlPlayerController plPlayerController = PlPlayerController.getInstance(); // 是否开始自动播放 存在多p的情况下,第二p需要为true RxBool autoPlay = true.obs; // 视频资源是否有效 @@ -62,6 +62,11 @@ class VideoDetailController extends GetxController // 封面图的展示 RxBool isShowCover = true.obs; + late VideoItem firstVideo; + late String videoUrl; + late String audioUrl; + late Duration defaultST; + @override void onInit() { super.onInit(); @@ -107,7 +112,7 @@ class VideoDetailController extends GetxController /// 更新画质、音质 /// TODO 继续进度播放 updatePlayer() { - Duration position = plPlayerController.position.value; + defaultST = plPlayerController.position.value; plPlayerController.removeListeners(); plPlayerController.isBuffering.value = false; plPlayerController.buffered.value = Duration.zero; @@ -115,24 +120,23 @@ class VideoDetailController extends GetxController /// 暂不匹配解码规则 /// 根据currentVideoQa 重新设置videoUrl - VideoItem firstVideo = + firstVideo = data.dash!.video!.firstWhere((i) => i.id == currentVideoQa.code); - // String videoUrl = firstVideo.baseUrl!; + videoUrl = firstVideo.baseUrl!; /// 根据currentAudioQa 重新设置audioUrl AudioItem firstAudio = 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, - {Duration defaultST = Duration.zero, int duration = 0}) async { + Future playerInit({video, audio, seekToTime, duration}) async { await plPlayerController.setDataSource( DataSource( - videoSource: firstVideo.baseUrl, - audioSource: audioSource, + videoSource: video ?? videoUrl, + audioSource: audio ?? audioUrl, type: DataSourceType.network, httpHeaders: { 'user-agent': @@ -143,11 +147,14 @@ class VideoDetailController extends GetxController // 硬解 enableHA: true, autoplay: autoPlay.value, - seekTo: defaultST, - duration: Duration(milliseconds: duration), + seekTo: seekToTime ?? defaultST, + duration: duration ?? Duration(milliseconds: data.timeLength ?? 0), // 宽>高 水平 否则 垂直 - direction: - firstVideo.width - firstVideo.height > 0 ? 'horizontal' : 'vertical', + direction: (firstVideo.width! - firstVideo.height!) > 0 + ? 'horizontal' + : 'vertical', + // 默认1倍速 + speed: 1.0, ); } @@ -163,25 +170,21 @@ class VideoDetailController extends GetxController data = result['data']; /// 优先顺序 省流模式 -> 设置中指定质量 -> 当前可选的最高质量 - VideoItem firstVideo = data.dash!.video!.first; - // String videoUrl = firstVideo.baseUrl!; + firstVideo = data.dash!.video!.first; + videoUrl = firstVideo.baseUrl!; // currentVideoQa = VideoQualityCode.fromCode(firstVideo.id!)!; /// 优先顺序 设置中指定质量 -> 当前可选的最高质量 AudioItem firstAudio = data.dash!.audio!.isNotEmpty ? data.dash!.audio!.first : AudioItem(); - String audioUrl = firstAudio.baseUrl ?? ''; + audioUrl = firstAudio.baseUrl ?? ''; // if (firstAudio.id != null) { currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!; } - await playerInit( - firstVideo, - audioUrl, - defaultST: Duration(milliseconds: data.lastPlayTime!), - duration: data.timeLength ?? 0, - ); + defaultST = Duration(milliseconds: data.lastPlayTime!); + await playerInit(); } else { SmartDialog.showToast(result['msg'].toString()); } diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index f1c38b80..26c5de99 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -49,8 +49,25 @@ class _VideoDetailPageState extends State void initState() { super.initState(); plPlayerController = videoDetailController.plPlayerController; + playerListener(); + + appbarStream = StreamController(); + + _extendNestCtr.addListener( + () { + double offset = _extendNestCtr.position.pixels; + appbarStream.add(offset); + }, + ); + + statusBarHeight = localCache.get('statusBarHeight'); + _futureBuilderFuture = videoDetailController.queryVideoUrl(); + } + + // 播放器状态监听 + void playerListener() { plPlayerController!.onPlayerStatusChanged.listen( - (PlayerStatus status) { + (PlayerStatus status) async { videoDetailController.markHeartBeat(); playerStatus = status; if (status == PlayerStatus.playing) { @@ -68,18 +85,6 @@ class _VideoDetailPageState extends State } }, ); - - appbarStream = StreamController(); - - _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 if (videoDetailController.timer!.isActive) { videoDetailController.timer!.cancel(); } + videoDetailController.defaultST = plPlayerController!.position.value; plPlayerController!.pause(); super.didPushNext(); } @@ -111,6 +117,7 @@ class _VideoDetailPageState extends State @override // 返回当前页面时 void didPopNext() async { + videoDetailController.playerInit(); if (_extendNestCtr.position.pixels == 0) { await Future.delayed(const Duration(milliseconds: 300)); plPlayerController!.play(); diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 50be2477..934e34b4 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:flutter/material.dart'; -import 'package:flutter/painting.dart'; import 'package:get/get.dart'; import 'package:hive/hive.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:universal_platform/universal_platform.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/play_speed.dart'; @@ -25,6 +24,9 @@ class PlPlayerController { Player? _videoPlayerController; VideoController? _videoController; + // 添加一个私有静态变量来保存实例 + static PlPlayerController? _instance; + // 流事件 监听播放状态变化 StreamSubscription? _playerEventSubs; @@ -44,6 +46,8 @@ class PlPlayerController { final Rx _duration = Rx(Duration.zero); final Rx _buffered = Rx(Duration.zero); + final Rx _playerCount = Rx(0); + final Rx _playbackSpeed = 1.0.obs; final Rx _currentVolume = 1.0.obs; final Rx _currentBrightness = 0.0.obs; @@ -172,10 +176,24 @@ class PlPlayerController { /// 全屏方向 Rx get direction => _direction; - PlPlayerController({ - // 直播间 传false 关闭控制栏 - this.controlsEnabled = true, - this.fits = const [ + Rx get playerCount => _playerCount; + + // 添加一个私有构造函数 + PlPlayerController._() { + controlsEnabled = controlsEnabled; + // _playerEventSubs = onPlayerStatusChanged.listen((PlayerStatus status) { + // if (status == PlayerStatus.playing) { + // WakelockPlus.enable(); + // } else { + // WakelockPlus.disable(); + // } + // }); + } + + // 获取实例 传参 + static PlPlayerController getInstance({ + bool controlsEnabled = true, + List fits = const [ BoxFit.contain, BoxFit.cover, BoxFit.fill, @@ -184,14 +202,10 @@ class PlPlayerController { BoxFit.scaleDown ], }) { - controlsEnabled = controlsEnabled; - _playerEventSubs = onPlayerStatusChanged.listen((PlayerStatus status) { - if (status == PlayerStatus.playing) { - WakelockPlus.enable(); - } else { - WakelockPlus.enable(); - } - }); + // 如果实例尚未创建,则创建一个新实例 + _instance ??= PlPlayerController._(); + _instance!._playerCount.value += 1; + return _instance!; } // 初始化资源 @@ -258,6 +272,9 @@ class PlPlayerController { double? width, double? height, ) async { + // 每次配置时先移除监听 + removeListeners(); + Player player = _videoPlayerController ?? Player( configuration: const PlayerConfiguration( @@ -663,6 +680,12 @@ class PlPlayerController { } Future dispose() async { + // 每次减1,最后销毁 + _playerCount.value -= 1; + if (playerCount.value > 0) { + return; + } + _timer?.cancel(); _timerForVolume?.cancel(); _timerForGettingVolume?.cancel(); @@ -685,5 +708,6 @@ class PlPlayerController { removeListeners(); await _videoPlayerController?.dispose(); _videoPlayerController = null; + _instance = null; } }