diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/FMDB.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/FMDB.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/FMDB.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/Flutter.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/Flutter.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/Flutter.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/Pods-Runner.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/Pods-Runner.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/Pods-Runner.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/ReachabilitySwift.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/ReachabilitySwift.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/ReachabilitySwift.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/connectivity_plus.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/connectivity_plus.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/connectivity_plus.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/device_info_plus.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/device_info_plus.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/device_info_plus.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/image_gallery_saver.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/image_gallery_saver.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/image_gallery_saver.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_libs_ios_video.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_libs_ios_video.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_libs_ios_video.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_native_event_loop.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_native_event_loop.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_native_event_loop.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_video.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_video.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/media_kit_video.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/package_info_plus.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/package_info_plus.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/package_info_plus.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/path_provider_foundation.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/path_provider_foundation.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/path_provider_foundation.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/permission_handler_apple.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/permission_handler_apple.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/permission_handler_apple.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/screen_brightness_ios.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/screen_brightness_ios.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/screen_brightness_ios.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/share_plus.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/share_plus.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/share_plus.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/sqflite.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/sqflite.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/sqflite.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/url_launcher_ios.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/url_launcher_ios.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/url_launcher_ios.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/volume_controller.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/volume_controller.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/volume_controller.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/wakelock_plus.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/wakelock_plus.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/wakelock_plus.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/webview_cookie_manager.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/webview_cookie_manager.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/webview_cookie_manager.build/dgph and /dev/null differ diff --git a/android/build/ios/Pods.build/Release-iphonesimulator/webview_flutter_wkwebview.build/dgph b/android/build/ios/Pods.build/Release-iphonesimulator/webview_flutter_wkwebview.build/dgph deleted file mode 100644 index c431c0f7..00000000 Binary files a/android/build/ios/Pods.build/Release-iphonesimulator/webview_flutter_wkwebview.build/dgph and /dev/null differ diff --git a/lib/pages/setting/play_setting.dart b/lib/pages/setting/play_setting.dart index cc3f3b88..6606f3c4 100644 --- a/lib/pages/setting/play_setting.dart +++ b/lib/pages/setting/play_setting.dart @@ -67,6 +67,12 @@ class _PlaySettingState extends State { setKey: SettingBoxKey.p1080, defaultVal: true, ), + const SetSwitchItem( + title: 'CDN优化', + subTitle: '使用优质CDN线路', + setKey: SettingBoxKey.enableCDN, + defaultVal: true, + ), const SetSwitchItem( title: '自动播放', subTitle: '进入详情页自动播放', diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index cbf08162..6fa0df6f 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -16,6 +16,7 @@ import 'package:pilipala/pages/video/detail/replyReply/index.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; +import 'package:pilipala/utils/video_utils.dart'; import 'package:screen_brightness/screen_brightness.dart'; import 'widgets/header_control.dart'; @@ -83,6 +84,11 @@ class VideoDetailController extends GetxController Floating? floating; late PreferredSizeWidget headerControl; + late bool enableCDN; + late int? cacheVideoQa; + late String cacheDecode; + late int cacheAudioQa; + @override void onInit() { super.onInit(); @@ -120,6 +126,15 @@ class VideoDetailController extends GetxController videoDetailCtr: this, floating: floating, ); + // CDN优化 + enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true); + // 预设的画质 + cacheVideoQa = setting.get(SettingBoxKey.defaultVideoQa); + // 预设的解码格式 + cacheDecode = setting.get(SettingBoxKey.defaultDecode, + defaultValue: VideoDecodeFormats.values.last.code); + cacheAudioQa = setting.get(SettingBoxKey.defaultAudioQa, + defaultValue: AudioQuality.hiRes.code); } showReplyReplyPanel() { @@ -231,22 +246,19 @@ class VideoDetailController extends GetxController var result = await VideoHttp.videoUrl(cid: cid.value, bvid: bvid); if (result['status']) { data = result['data']; - List allVideosList = data.dash!.video!; - try { // 当前可播放的最高质量视频 int currentHighVideoQa = allVideosList.first.quality!.code; - // 使用预设的画质 | 当前可用的最高质量 - int cacheVideoQa = setting.get(SettingBoxKey.defaultVideoQa, - defaultValue: currentHighVideoQa); + // 预设的画质为null,则当前可用的最高质量 + cacheVideoQa ??= currentHighVideoQa; int resVideoQa = currentHighVideoQa; - if (cacheVideoQa <= currentHighVideoQa) { + if (cacheVideoQa! <= currentHighVideoQa) { // 如果预设的画质低于当前最高 List numbers = data.acceptQuality! .where((e) => e <= currentHighVideoQa) .toList(); - resVideoQa = Utils.findClosestNumber(cacheVideoQa, numbers); + resVideoQa = Utils.findClosestNumber(cacheVideoQa!, numbers); } currentVideoQa = VideoQualityCode.fromCode(resVideoQa)!; @@ -260,9 +272,7 @@ class VideoDetailController extends GetxController List supportDecodeFormats = supportFormats.firstWhere((e) => e.quality == resVideoQa).codecs!; // 默认从设置中取AVC - currentDecodeFormats = VideoDecodeFormatsCode.fromString(setting.get( - SettingBoxKey.defaultDecode, - defaultValue: VideoDecodeFormats.values.last.code))!; + currentDecodeFormats = VideoDecodeFormatsCode.fromString(cacheDecode)!; try { // 当前视频没有对应格式返回第一个 bool flag = false; @@ -285,7 +295,9 @@ class VideoDetailController extends GetxController } catch (_) { firstVideo = videosList.first; } - videoUrl = firstVideo.baseUrl!; + videoUrl = enableCDN + ? VideoUtils.getCdnUrl(firstVideo) + : (firstVideo.backupUrl ?? firstVideo.baseUrl!); } catch (err) { SmartDialog.showToast('firstVideo error: $err'); } @@ -295,8 +307,6 @@ class VideoDetailController extends GetxController List audiosList = data.dash!.audio!; 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); @@ -309,9 +319,9 @@ class VideoDetailController extends GetxController if (audiosList.isNotEmpty) { List numbers = audiosList.map((map) => map.id!).toList(); - int closestNumber = Utils.findClosestNumber(resultAudioQa, numbers); - if (!numbers.contains(resultAudioQa) && - numbers.any((e) => e > resultAudioQa)) { + int closestNumber = Utils.findClosestNumber(cacheAudioQa, numbers); + if (!numbers.contains(cacheAudioQa) && + numbers.any((e) => e > cacheAudioQa)) { closestNumber = 30280; } firstAudio = audiosList.firstWhere((e) => e.id == closestNumber); @@ -323,7 +333,9 @@ class VideoDetailController extends GetxController SmartDialog.showToast('firstAudio error: $err'); } - audioUrl = firstAudio.baseUrl ?? ''; + audioUrl = enableCDN + ? VideoUtils.getCdnUrl(firstAudio) + : (firstAudio.backupUrl ?? firstAudio.baseUrl!); // if (firstAudio.id != null) { currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!; diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 568a4bee..0debd259 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -3,18 +3,15 @@ import 'dart:io'; import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:floating/floating.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; -import 'package:pilipala/common/widgets/sliver_header.dart'; import 'package:pilipala/http/user.dart'; import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/pages/bangumi/introduction/index.dart'; import 'package:pilipala/pages/danmaku/view.dart'; -import 'package:pilipala/pages/video/detail/introduction/widgets/menu_row.dart'; import 'package:pilipala/pages/video/detail/reply/index.dart'; import 'package:pilipala/pages/video/detail/controller.dart'; import 'package:pilipala/pages/video/detail/introduction/index.dart'; @@ -23,7 +20,6 @@ import 'package:pilipala/plugin/pl_player/index.dart'; import 'package:pilipala/plugin/pl_player/models/play_repeat.dart'; import 'package:pilipala/utils/storage.dart'; -import 'widgets/app_bar.dart'; import 'widgets/header_control.dart'; class VideoDetailPage extends StatefulWidget { diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 2c116b16..537dde58 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -332,12 +332,11 @@ class PlPlayerController { // 数据加载完成 dataStatus.status.value = DataStatus.loaded; - await _initializePlayer(seekTo: seekTo); - // listen the video player events if (!_listenersInitialized) { startListeners(); } + await _initializePlayer(seekTo: seekTo); bool autoEnterFullcreen = setting.get(SettingBoxKey.enableAutoEnter, defaultValue: false); if (autoEnterFullcreen && _isFirstTime) { @@ -407,6 +406,7 @@ class PlPlayerController { player, configuration: VideoControllerConfiguration( enableHardwareAcceleration: enableHA, + androidAttachSurfaceAfterVideoParameters: false, ), ); @@ -542,6 +542,7 @@ class PlPlayerController { } _position.value = position; _heartDuration = position.inSeconds; + print('seek duration: $duration'); if (duration.value.inSeconds != 0) { if (type != 'slider') { /// 拖动进度条调节时,不等待第一帧,防止抖动 @@ -552,17 +553,19 @@ class PlPlayerController { // play(); // } } else { + print('seek duration else'); _timerForSeek?.cancel(); _timerForSeek = Timer.periodic(const Duration(milliseconds: 200), (Timer t) async { //_timerForSeek = null; if (duration.value.inSeconds != 0) { + await _videoPlayerController!.stream.buffer.first; await _videoPlayerController?.seek(position); - // if (playerStatus.stopped) { - // play(); - // } + if (playerStatus.status.value == PlayerStatus.paused) { + play(); + } t.cancel(); - //_timerForSeek = null; + _timerForSeek = null; } }); } @@ -595,6 +598,8 @@ class PlPlayerController { /// 播放视频 Future play({bool repeat = false, bool hideControls = true}) async { + // 播放时自动隐藏控制条 + controls = !hideControls; // repeat为true,将从头播放 if (repeat) { await seekTo(Duration.zero); @@ -606,11 +611,6 @@ class PlPlayerController { playerStatus.status.value = PlayerStatus.playing; // screenManager.setOverlays(false); - - // 播放时自动隐藏控制条 - if (hideControls) { - _hideTaskControls(); - } } /// 暂停播放 diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 8d31726c..4689d7f2 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -105,6 +105,7 @@ class SettingBoxKey { static const String enableAutoEnter = 'enableAutoEnter'; static const String enableAutoExit = 'enableAutoExit'; static const String p1080 = 'p1080'; + static const String enableCDN = 'enableCDN'; // youtube 双击快进快退 static const String enableQuickDouble = 'enableQuickDouble'; diff --git a/lib/utils/video_utils.dart b/lib/utils/video_utils.dart new file mode 100644 index 00000000..88faba3c --- /dev/null +++ b/lib/utils/video_utils.dart @@ -0,0 +1,36 @@ +import 'package:pilipala/models/video/play/url.dart'; + +class VideoUtils { + static String getCdnUrl(dynamic item) { + var backupUrl = ""; + var videoUrl = ""; + + /// 先获取backupUrl 一般是upgcxcode地址 播放更稳定 + if (item is VideoItem) { + backupUrl = item.backupUrl ?? ""; + videoUrl = backupUrl.contains("http") ? backupUrl : (item.baseUrl ?? ""); + } else if (item is AudioItem) { + backupUrl = item.backupUrl ?? ""; + videoUrl = backupUrl.contains("http") ? backupUrl : (item.baseUrl ?? ""); + } else { + return ""; + } + + /// issues #70 + if (videoUrl.contains(".mcdn.bilivideo") || + videoUrl.contains("/upgcxcode/")) { + //CDN列表 + var cdnList = { + 'ali': 'upos-sz-mirrorali.bilivideo.com', + 'cos': 'upos-sz-mirrorcos.bilivideo.com', + 'hw': 'upos-sz-mirrorhw.bilivideo.com', + }; + //取一个CDN + var cdn = cdnList['ali'] ?? ""; + var reg = RegExp(r'(http|https)://(.*?)/upgcxcode/'); + videoUrl = videoUrl.replaceAll(reg, "https://$cdn/upgcxcode/"); + } + + return videoUrl; + } +} diff --git a/pubspec.lock b/pubspec.lock index 55c4c0a6..8354dd69 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -761,10 +761,10 @@ packages: dependency: "direct main" description: name: media_kit - sha256: d652c2bdb0cd876bf1046e24d0b614651fefe59f7c3a2d9b7ed57217b9e7db94 + sha256: "3dffc6d0c19117d51fbc42a7f89612e0595665800a596289ab7a80bdd93e0ad1" url: "https://pub.dev" source: hosted - version: "1.1.8+1" + version: "1.1.9" media_kit_libs_android_video: dependency: transitive description: @@ -825,10 +825,10 @@ packages: dependency: "direct main" description: name: media_kit_video - sha256: b1a427f0540c5f052dfab73e4b76a5eb8efa7ebb5d83179cb23fc3932afc315a + sha256: b8df9cf97aba1861af83b00ac16f5cac536debe0781a934a554b77c157a8f7e8 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" meta: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e2f00f2c..2b8fc115 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -84,8 +84,8 @@ dependencies: crypto: ^3.0.3 # 视频播放器 - media_kit: ^1.1.8 # Primary package. - media_kit_video: ^1.2.1 # For video rendering. + media_kit: ^1.1.9 # Primary package. + media_kit_video: ^1.2.2 # For video rendering. media_kit_libs_video: ^1.0.3 # 音量、亮度、屏幕控制