diff --git a/lib/common/widgets/image/cached_network_svg_image.dart b/lib/common/widgets/image/cached_network_svg_image.dart index f7ca210be..7842d9556 100644 --- a/lib/common/widgets/image/cached_network_svg_image.dart +++ b/lib/common/widgets/image/cached_network_svg_image.dart @@ -60,9 +60,7 @@ class _CachedNetworkSVGImageState extends State { double? height; late TextScaler textScaler; - static final _sizeRegExp = RegExp( - r'height="([\d\.]+)([c-x]{2})?"', - ); + static final _sizeRegExp = RegExp(r'height="([\d\.]+)([c-x]{2})?"'); @override void initState() { diff --git a/lib/pages/setting/models/extra_settings.dart b/lib/pages/setting/models/extra_settings.dart index 541f5220e..7bc7d54a5 100644 --- a/lib/pages/setting/models/extra_settings.dart +++ b/lib/pages/setting/models/extra_settings.dart @@ -32,6 +32,7 @@ import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/cache_manager.dart'; import 'package:PiliPlus/utils/extension/num_ext.dart'; import 'package:PiliPlus/utils/feed_back.dart'; +import 'package:PiliPlus/utils/filtering_text.dart'; import 'package:PiliPlus/utils/global_data.dart'; import 'package:PiliPlus/utils/image_utils.dart'; import 'package:PiliPlus/utils/path_utils.dart'; @@ -858,9 +859,7 @@ void _showDmHeightDialog(BuildContext context, VoidCallback setState) { initialValue: danmakuLineHeight, keyboardType: const .numberWithOptions(decimal: true), onChanged: (value) => danmakuLineHeight = value, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[\d\.]+')), - ], + inputFormatters: FilteringText.decimal, ), actions: [ TextButton( @@ -902,9 +901,7 @@ void _showTouchSlopDialog(BuildContext context, VoidCallback setState) { initialValue: initialValue, keyboardType: const .numberWithOptions(decimal: true), onChanged: (value) => initialValue = value, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[\d\.]+')), - ], + inputFormatters: FilteringText.decimal, ), actions: [ TextButton( @@ -1188,9 +1185,7 @@ void _showProxyDialog(BuildContext context) { decoration: const InputDecoration( isDense: true, labelText: '请输入Port', - border: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(6)), - ), + border: OutlineInputBorder(borderRadius: .all(.circular(6))), ), inputFormatters: [FilteringTextInputFormatter.digitsOnly], onChanged: (e) => systemProxyPort = e, @@ -1234,9 +1229,7 @@ void _showCacheDialog(BuildContext context, VoidCallback setState) { autofocus: true, onChanged: (value) => valueStr = value, keyboardType: TextInputType.number, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[\d\.]+')), - ], + inputFormatters: FilteringText.decimal, decoration: const InputDecoration(suffixText: 'MB'), ), actions: [ diff --git a/lib/pages/setting/models/style_settings.dart b/lib/pages/setting/models/style_settings.dart index 6a70f87df..5be370a61 100644 --- a/lib/pages/setting/models/style_settings.dart +++ b/lib/pages/setting/models/style_settings.dart @@ -442,9 +442,7 @@ void _showUiScaleDialog( ), TextFormField( controller: textController, - keyboardType: const TextInputType.numberWithOptions( - decimal: true, - ), + keyboardType: const .numberWithOptions(decimal: true), inputFormatters: [ LengthLimitingTextInputFormatter(4), FilteringTextInputFormatter.allow(RegExp(r'[\d.]+')), diff --git a/lib/pages/setting/models/video_settings.dart b/lib/pages/setting/models/video_settings.dart index 138dadcd1..886e9d2c8 100644 --- a/lib/pages/setting/models/video_settings.dart +++ b/lib/pages/setting/models/video_settings.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/pages/setting/widgets/ordered_multi_select_dialog.dart' import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart'; import 'package:PiliPlus/plugin/pl_player/models/audio_output_type.dart'; import 'package:PiliPlus/plugin/pl_player/models/hwdec_type.dart'; +import 'package:PiliPlus/utils/filtering_text.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; @@ -144,12 +145,19 @@ List get videoSettings => [ getSubtitle: () => '当前:${Pref.audioOutput}', onTap: _showAudioOutputDialog, ), - const SwitchModel( - title: '扩大缓冲区', - leading: Icon(Icons.storage_outlined), - subtitle: '默认缓冲区为视频4MB/直播16MB,开启后为32MB/64MB,加载时间变长', - setKey: SettingBoxKey.expandBuffer, - defaultVal: false, + NormalModel( + title: '缓冲大小', + leading: const Icon(Icons.storage_outlined), + getSubtitle: () => + '当前:${Pref.bufferSize}MB。同时为前向和后向缓冲区大小。对于直播流,无后向缓冲大小,全部转给前向(此选项即mpv的--demuxer-max-bytes,--demuxer-max-back-bytes)', + onTap: _showBufferSizeDialog, + ), + NormalModel( + title: '缓冲时长', + leading: const Icon(Icons.av_timer), + getSubtitle: () => + '当前:${Pref.bufferSec}s。实际缓冲为二者最小值。对于直播流,该选项无效(此选项即mpv的--cache-secs)', + onTap: _showBufferSecDialog, ), NormalModel( title: '自动同步', @@ -494,3 +502,70 @@ void _showAutoSyncDialog(BuildContext context, VoidCallback setState) { ), ); } + +void _showDecimalDialog( + BuildContext context, + VoidCallback setState, { + required String key, + required double defVal, + required String title, + required String? suffix, +}) { + String value = (GStorage.setting.get(key) ?? defVal).toString(); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(title), + content: TextFormField( + autofocus: true, + initialValue: value, + keyboardType: const .numberWithOptions(decimal: true), + onChanged: (val) => value = val, + inputFormatters: FilteringText.decimal, + decoration: suffix == null ? null : InputDecoration(suffixText: suffix), + ), + actions: [ + TextButton( + onPressed: Get.back, + child: Text( + '取消', + style: TextStyle(color: ColorScheme.of(context).outline), + ), + ), + TextButton( + onPressed: () async { + try { + final val = double.parse(value); + Get.back(); + await GStorage.setting.put(key, val); + setState(); + } catch (e) { + SmartDialog.showToast(e.toString()); + } + }, + child: const Text('确定'), + ), + ], + ), + ); +} + +void _showBufferSizeDialog(BuildContext context, VoidCallback setState) => + _showDecimalDialog( + context, + setState, + key: SettingBoxKey.bufferSize, + defVal: Pref.bufferSize, + title: '缓冲大小', + suffix: 'MB', + ); + +void _showBufferSecDialog(BuildContext context, VoidCallback setState) => + _showDecimalDialog( + context, + setState, + key: SettingBoxKey.bufferSec, + defVal: Pref.bufferSec, + title: '缓冲时长', + suffix: 's', + ); diff --git a/lib/pages/setting/pages/play_speed_set.dart b/lib/pages/setting/pages/play_speed_set.dart index aa67061b3..16f300059 100644 --- a/lib/pages/setting/pages/play_speed_set.dart +++ b/lib/pages/setting/pages/play_speed_set.dart @@ -4,11 +4,11 @@ import 'package:PiliPlus/common/widgets/flutter/list_tile.dart'; import 'package:PiliPlus/common/widgets/view_safe_area.dart'; import 'package:PiliPlus/pages/setting/widgets/switch_item.dart'; import 'package:PiliPlus/utils/extension/context_ext.dart'; +import 'package:PiliPlus/utils/filtering_text.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:flutter/material.dart' hide ListTile; -import 'package:flutter/services.dart' show FilteringTextInputFormatter; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive_ce/hive.dart'; @@ -74,9 +74,7 @@ class _PlaySpeedPageState extends State { border: OutlineInputBorder(borderRadius: .all(.circular(6))), ), onChanged: (value) => initialValue = value, - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[\d\.]+')), - ], + inputFormatters: FilteringText.decimal, ), ], ), diff --git a/lib/pages/sponsor_block/view.dart b/lib/pages/sponsor_block/view.dart index b372b532b..b053bbb72 100644 --- a/lib/pages/sponsor_block/view.dart +++ b/lib/pages/sponsor_block/view.dart @@ -7,6 +7,7 @@ import 'package:PiliPlus/models/common/sponsor_block/segment_type.dart'; import 'package:PiliPlus/models/common/sponsor_block/skip_type.dart'; import 'package:PiliPlus/models_new/sponsor_block/user_info.dart'; import 'package:PiliPlus/pages/setting/slide_color_picker.dart'; +import 'package:PiliPlus/utils/filtering_text.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; @@ -82,15 +83,11 @@ class _SponsorBlockPageState extends State { builder: (_) => AlertDialog( title: Text('最短片段时长', style: titleStyle), content: TextFormField( - keyboardType: const TextInputType.numberWithOptions( - decimal: true, - ), + keyboardType: const .numberWithOptions(decimal: true), controller: _textController, autofocus: true, decoration: const InputDecoration(suffixText: 's'), - inputFormatters: [ - FilteringTextInputFormatter.allow(RegExp(r'[\d\.]+')), - ], + inputFormatters: FilteringText.decimal, ), actions: [ TextButton( diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index 314a44324..05d7a0bf3 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -843,12 +843,6 @@ class HeaderControlState extends State onTap: () => Utils.copyText('VideoTrack\n${state.track.audio}'), ), - ListTile( - dense: true, - title: const Text("pitch"), - subtitle: Text(state.pitch.toString()), - onTap: () => Utils.copyText('pitch\n${state.pitch}'), - ), ListTile( dense: true, title: const Text("rate"), diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 16471b8fc..45625a48b 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -789,9 +789,6 @@ class PlPlayerController with BlockConfigMixin { final player = await Player.create( configuration: PlayerConfiguration( - bufferSize: Pref.expandBuffer - ? (isLive ? 64 * 1024 * 1024 : 32 * 1024 * 1024) - : (isLive ? 16 * 1024 * 1024 : 4 * 1024 * 1024), logLevel: kDebugMode ? .warn : .error, options: opt, ), @@ -808,17 +805,38 @@ class PlPlayerController with BlockConfigMixin { ), ); - player.setMediaHeader( - userAgent: BrowserUa.pc, - referer: HttpString.baseUrl, - ); - // await player.setAudioTrack(.auto()); + player.setMediaHeader(userAgent: BrowserUa.pc, referer: HttpString.baseUrl); _startListeners(player); return player; } + Map? _buffer; + Map get buffer => _buffer ??= _initBuffer(); + Map? _liveBuffer; + Map get liveBuffer => _liveBuffer ??= _initLiveBuffer(); + + Map _initBuffer() { + final bufSec = Pref.bufferSec * _playbackSpeed.value; + final bufSiz = (Pref.bufferSize * 0x100000).toStringAsFixed(0); + return { + 'cache': 'yes', + 'cache-secs': bufSec.toStringAsFixed(3), + 'demuxer-hysteresis-secs': (bufSec / 1.5).toStringAsFixed(3), + 'demuxer-max-bytes': bufSiz, + 'demuxer-max-back-bytes': bufSiz, + }; + } + + Map _initLiveBuffer() { + return { + 'cache': 'yes', + 'demuxer-max-bytes': (Pref.bufferSize * 0x200000).toStringAsFixed(0), + 'demuxer-max-back-bytes': '0', + }; + } + // 配置播放器 Future _createVideoController( DataSource dataSource, @@ -851,6 +869,16 @@ class PlPlayerController with BlockConfigMixin { final Map extras = {}; + if (dataSource is FileSource) { + extras['cache'] = 'no'; + } else { + if (isLive) { + extras.addAll(liveBuffer); + } else { + extras.addAll(buffer); + } + } + String video = dataSource.videoSource; if (dataSource.audioSource case final audio? when (audio.isNotEmpty)) { if (onlyPlayAudio.value) { @@ -900,11 +928,8 @@ class PlPlayerController with BlockConfigMixin { if (dataSource is FileSource) { return null; } - if (_videoPlayerController?.current.isNotEmpty ?? false) { - return _videoPlayerController!.open( - _videoPlayerController!.current.last.copyWith(start: position), - play: true, - ); + if (_videoPlayerController case final ctr? when (ctr.current.isNotEmpty)) { + return ctr.open(ctr.current.last.copyWith(start: position), play: true); } return null; } diff --git a/lib/utils/filtering_text.dart b/lib/utils/filtering_text.dart new file mode 100644 index 000000000..649732b81 --- /dev/null +++ b/lib/utils/filtering_text.dart @@ -0,0 +1,7 @@ +import 'package:flutter/services.dart'; + +abstract final class FilteringText { + static final decimal = [ + FilteringTextInputFormatter.allow(RegExp(r'[\d\.]+')), + ]; +} diff --git a/lib/utils/storage_key.dart b/lib/utils/storage_key.dart index 37182cbe4..7c1f935fa 100644 --- a/lib/utils/storage_key.dart +++ b/lib/utils/storage_key.dart @@ -14,7 +14,8 @@ abstract final class SettingBoxKey { defaultPicQa = 'defaultPicQa', enableHA = 'enableHA', audioOutput = 'audioOutput', - expandBuffer = 'expandBuffer', + bufferSize = 'bufferSize', + bufferSec = 'bufferSec', hardwareDecoding = 'hardwareDecoding', videoSync = 'videoSync', autosync = 'autosync', diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index 6acb9e7da..60549e2cc 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -797,8 +797,11 @@ abstract final class Pref { static bool get enableLongShowControl => _setting.get(SettingBoxKey.enableLongShowControl, defaultValue: false); - static bool get expandBuffer => - _setting.get(SettingBoxKey.expandBuffer, defaultValue: false); + static double get bufferSize => + _setting.get(SettingBoxKey.bufferSize, defaultValue: 4.0); + + static double get bufferSec => + _setting.get(SettingBoxKey.bufferSec, defaultValue: 16.0); static String get audioOutput => _setting.get( SettingBoxKey.audioOutput, diff --git a/pubspec.lock b/pubspec.lock index b94f3cd1f..51efcf4fb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1115,7 +1115,7 @@ packages: description: path: media_kit ref: "version_1.2.5" - resolved-ref: e6c3481025959a23c259aa6072a28cebaa1c0fcc + resolved-ref: deac6b62569584b6a5e28e6c60c187a0a7281b3a url: "https://github.com/My-Responsitories/media-kit.git" source: git version: "1.1.11" @@ -1124,7 +1124,7 @@ packages: description: path: "libs/android/media_kit_libs_android_video" ref: "version_1.2.5" - resolved-ref: e6c3481025959a23c259aa6072a28cebaa1c0fcc + resolved-ref: deac6b62569584b6a5e28e6c60c187a0a7281b3a url: "https://github.com/My-Responsitories/media-kit.git" source: git version: "1.3.7" @@ -1133,7 +1133,7 @@ packages: description: path: "libs/ios/media_kit_libs_ios_video" ref: "version_1.2.5" - resolved-ref: e6c3481025959a23c259aa6072a28cebaa1c0fcc + resolved-ref: deac6b62569584b6a5e28e6c60c187a0a7281b3a url: "https://github.com/My-Responsitories/media-kit.git" source: git version: "1.1.4" @@ -1158,7 +1158,7 @@ packages: description: path: "libs/universal/media_kit_libs_video" ref: "version_1.2.5" - resolved-ref: e6c3481025959a23c259aa6072a28cebaa1c0fcc + resolved-ref: deac6b62569584b6a5e28e6c60c187a0a7281b3a url: "https://github.com/My-Responsitories/media-kit.git" source: git version: "1.0.5" @@ -1167,7 +1167,7 @@ packages: description: path: "libs/windows/media_kit_libs_windows_video" ref: "version_1.2.5" - resolved-ref: e6c3481025959a23c259aa6072a28cebaa1c0fcc + resolved-ref: deac6b62569584b6a5e28e6c60c187a0a7281b3a url: "https://github.com/My-Responsitories/media-kit.git" source: git version: "1.0.10" @@ -1176,7 +1176,7 @@ packages: description: path: media_kit_native_event_loop ref: "version_1.2.5" - resolved-ref: e6c3481025959a23c259aa6072a28cebaa1c0fcc + resolved-ref: deac6b62569584b6a5e28e6c60c187a0a7281b3a url: "https://github.com/My-Responsitories/media-kit.git" source: git version: "1.0.9" @@ -1185,7 +1185,7 @@ packages: description: path: media_kit_video ref: "version_1.2.5" - resolved-ref: e6c3481025959a23c259aa6072a28cebaa1c0fcc + resolved-ref: deac6b62569584b6a5e28e6c60c187a0a7281b3a url: "https://github.com/My-Responsitories/media-kit.git" source: git version: "1.2.5" diff --git a/pubspec.yaml b/pubspec.yaml index 9e66d5eb8..2d4c202ed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -184,7 +184,6 @@ dependency_overrides: url: https://github.com/bggRGjQaUbCoE/flutter_inappwebview.git path: flutter_inappwebview_windows ref: v6.1.5 - flutter_volume_controller: ^2.0.0 media_kit: git: url: https://github.com/My-Responsitories/media-kit.git