Files
PiliPlus/lib/pages/setting/models/video_settings.dart
bggRGjQaUbCoE 95f1d1485d tweak
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-08-11 13:56:57 +08:00

382 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
import 'package:PiliPlus/models/common/settings_type.dart';
import 'package:PiliPlus/models/common/video/audio_quality.dart';
import 'package:PiliPlus/models/common/video/cdn_type.dart';
import 'package:PiliPlus/models/common/video/live_quality.dart';
import 'package:PiliPlus/models/common/video/video_decode_type.dart';
import 'package:PiliPlus/models/common/video/video_quality.dart';
import 'package:PiliPlus/pages/setting/models/model.dart';
import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_key.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:PiliPlus/utils/video_utils.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
List<SettingsModel> get videoSettings => [
const SettingsModel(
settingsType: SettingsType.sw1tch,
title: '开启硬解',
subtitle: '以较低功耗播放视频,若异常卡死请关闭',
leading: Icon(Icons.flash_on_outlined),
setKey: SettingBoxKey.enableHA,
defaultVal: true,
),
const SettingsModel(
settingsType: SettingsType.sw1tch,
title: '免登录1080P',
subtitle: '免登录查看1080P视频',
leading: Icon(Icons.hd_outlined),
setKey: SettingBoxKey.p1080,
defaultVal: true,
),
SettingsModel(
settingsType: SettingsType.normal,
title: 'B站定向流量支持',
subtitle: '若套餐含B站定向流量则会自动使用。可查阅运营商的流量记录确认。',
leading: const Icon(Icons.perm_data_setting_outlined),
getTrailing: () => Transform.scale(
alignment: Alignment.centerRight,
scale: 0.8,
child: Switch(
thumbIcon: WidgetStateProperty.resolveWith<Icon?>((
Set<WidgetState> states,
) {
if (states.isNotEmpty && states.first == WidgetState.selected) {
return const Icon(Icons.lock_outline_rounded);
}
return null;
}),
value: true,
onChanged: (_) {},
),
),
),
SettingsModel(
settingsType: SettingsType.normal,
title: 'CDN 设置',
leading: const Icon(MdiIcons.cloudPlusOutline),
getSubtitle: () =>
'当前使用:${CDNService.fromCode(VideoUtils.cdnService).desc},部分 CDN 可能失效,如无法播放请尝试切换',
onTap: (setState) async {
String? result = await showDialog(
context: Get.context!,
builder: (context) {
return const CdnSelectDialog();
},
);
if (result != null) {
VideoUtils.cdnService = result;
await GStorage.setting.put(SettingBoxKey.CDNService, result);
setState();
}
},
),
const SettingsModel(
settingsType: SettingsType.sw1tch,
title: 'CDN 测速',
leading: Icon(Icons.speed),
subtitle: '测速通过模拟加载视频实现,注意流量消耗,结果仅供参考',
setKey: SettingBoxKey.cdnSpeedTest,
defaultVal: true,
),
SettingsModel(
settingsType: SettingsType.sw1tch,
title: '音频不跟随 CDN 设置',
subtitle: '直接采用备用 URL可解决部分视频无声',
leading: const Icon(MdiIcons.musicNotePlus),
setKey: SettingBoxKey.disableAudioCDN,
defaultVal: true,
onChanged: (value) {
VideoUtils.disableAudioCDN = value;
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '默认画质',
leading: const Icon(Icons.video_settings_outlined),
getSubtitle: () =>
'当前画质:${VideoQuality.fromCode(Pref.defaultVideoQa).desc}',
onTap: (setState) async {
int? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<int>(
title: '默认画质',
value: Pref.defaultVideoQa,
values: VideoQuality.values.reversed
.map((e) => (e.code, e.desc))
.toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(SettingBoxKey.defaultVideoQa, result);
setState();
}
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '蜂窝网络画质',
leading: const Icon(Icons.video_settings_outlined),
getSubtitle: () =>
'当前画质:${VideoQuality.fromCode(Pref.defaultVideoQaCellular).desc}',
onTap: (setState) async {
int? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<int>(
title: '蜂窝网络画质',
value: Pref.defaultVideoQaCellular,
values: VideoQuality.values.reversed
.map((e) => (e.code, e.desc))
.toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(
SettingBoxKey.defaultVideoQaCellular,
result,
);
setState();
}
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '默认音质',
leading: const Icon(Icons.music_video_outlined),
getSubtitle: () =>
'当前音质:${AudioQuality.fromCode(Pref.defaultAudioQa).desc}',
onTap: (setState) async {
int? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<int>(
title: '默认音质',
value: Pref.defaultAudioQa,
values: AudioQuality.values.reversed
.map((e) => (e.code, e.desc))
.toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(SettingBoxKey.defaultAudioQa, result);
setState();
}
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '蜂窝网络音质',
leading: const Icon(Icons.music_video_outlined),
getSubtitle: () =>
'当前音质:${AudioQuality.fromCode(Pref.defaultAudioQaCellular).desc}',
onTap: (setState) async {
int? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<int>(
title: '蜂窝网络音质',
value: Pref.defaultAudioQaCellular,
values: AudioQuality.values.reversed
.map((e) => (e.code, e.desc))
.toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(
SettingBoxKey.defaultAudioQaCellular,
result,
);
setState();
}
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '直播默认画质',
leading: const Icon(Icons.video_settings_outlined),
getSubtitle: () =>
'当前画质:${LiveQualityExt.fromCode(Pref.liveQuality)!.description}',
onTap: (setState) async {
int? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<int>(
title: '直播默认画质',
value: Pref.liveQuality,
values: LiveQuality.values
.map((e) => (e.code, e.description))
.toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(SettingBoxKey.liveQuality, result);
setState();
}
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '蜂窝网络直播默认画质',
leading: const Icon(Icons.video_settings_outlined),
getSubtitle: () =>
'当前画质:${LiveQualityExt.fromCode(Pref.liveQualityCellular)!.description}',
onTap: (setState) async {
int? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<int>(
title: '直播默认画质',
value: Pref.liveQualityCellular,
values: LiveQuality.values
.map((e) => (e.code, e.description))
.toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(SettingBoxKey.liveQualityCellular, result);
setState();
}
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '首选解码格式',
leading: const Icon(Icons.movie_creation_outlined),
getSubtitle: () =>
'首选解码格式:${VideoDecodeFormatTypeExt.fromCode(Pref.defaultDecode)!.description},请根据设备支持情况与需求调整',
onTap: (setState) async {
String? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<String>(
title: '默认解码格式',
value: Pref.defaultDecode,
values: VideoDecodeFormatType.values
.map((e) => (e.code, e.description))
.toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(SettingBoxKey.defaultDecode, result);
setState();
}
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '次选解码格式',
getSubtitle: () =>
'非杜比视频次选:${VideoDecodeFormatTypeExt.fromCode(Pref.secondDecode)!.description},仍无则选择首个提供的解码格式',
leading: const Icon(Icons.swap_horizontal_circle_outlined),
onTap: (setState) async {
String? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<String>(
title: '次选解码格式',
value: Pref.secondDecode,
values: VideoDecodeFormatType.values
.map((e) => (e.code, e.description))
.toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(SettingBoxKey.secondDecode, result);
setState();
}
},
),
if (Platform.isAndroid)
const SettingsModel(
settingsType: SettingsType.sw1tch,
title: '优先使用 OpenSL ES 输出音频',
leading: Icon(Icons.speaker_outlined),
subtitle: '关闭则优先使用AudioTrack输出音频此项即mpv的--ao若遇系统音效丢失、无声、音画不同步等问题请尝试关闭。',
setKey: SettingBoxKey.useOpenSLES,
defaultVal: true,
),
const SettingsModel(
settingsType: SettingsType.sw1tch,
title: '扩大缓冲区',
leading: Icon(Icons.storage_outlined),
subtitle: '默认缓冲区为视频4MB/直播16MB开启后为32MB/64MB加载时间变长',
setKey: SettingBoxKey.expandBuffer,
defaultVal: false,
),
//video-sync
SettingsModel(
settingsType: SettingsType.normal,
title: '视频同步',
leading: const Icon(Icons.view_timeline_outlined),
getSubtitle: () => '当前:${Pref.videoSync}此项即mpv的--video-sync',
onTap: (setState) async {
String? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<String>(
title: '视频同步',
value: Pref.videoSync,
values: const [
'audio',
'display-resample',
'display-resample-vdrop',
'display-resample-desync',
'display-tempo',
'display-vdrop',
'display-adrop',
'display-desync',
'desync',
].map((e) => (e, e)).toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(SettingBoxKey.videoSync, result);
setState();
}
},
),
SettingsModel(
settingsType: SettingsType.normal,
title: '硬解模式',
leading: const Icon(Icons.memory_outlined),
getSubtitle: () => '当前:${Pref.hardwareDecoding}此项即mpv的--hwdec',
onTap: (setState) async {
String? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<String>(
title: '硬解模式',
value: Pref.hardwareDecoding,
values: const [
'auto',
'auto-copy',
'auto-safe',
'no',
'yes',
].map((e) => (e, e)).toList(),
);
},
);
if (result != null) {
await GStorage.setting.put(SettingBoxKey.hardwareDecoding, result);
setState();
}
},
),
];