feat: 视频解码格式

This commit is contained in:
guozhigq
2023-08-10 11:50:45 +08:00
parent d5943d88b0
commit 7528526252
3 changed files with 150 additions and 24 deletions

View File

@ -89,3 +89,38 @@ extension AudioQualityDesc on AudioQuality {
];
get description => _descList[index];
}
enum VideoDecodeFormats {
AV1,
HEVC,
AVC,
}
extension VideoDecodeFormatsDesc on VideoDecodeFormats {
static final List<String> _descList = [
'AV1',
'HEVC',
'AVC',
];
get description => _descList[index];
}
extension VideoDecodeFormatsCode on VideoDecodeFormats {
static final List<String> _codeList = [
'av01',
'hev1',
'avc1',
];
get code => _codeList[index];
static VideoDecodeFormats? fromString(String val) {
var result = VideoDecodeFormats.values.first;
for (var i in _codeList) {
if (val.startsWith(i)) {
result = VideoDecodeFormats.values[_codeList.indexOf(i)];
break;
}
}
return result;
}
}

View File

@ -32,6 +32,8 @@ class VideoDetailController extends GetxController
late VideoQuality currentVideoQa;
// 当前音质
late AudioQuality currentAudioQa;
// 当前解码格式
late VideoDecodeFormats currentDecodeFormats;
// 是否预渲染 骨架屏
bool preRender = false;
@ -114,9 +116,11 @@ class VideoDetailController extends GetxController
/// 暂不匹配解码规则
/// 根据currentVideoQa 重新设置videoUrl
VideoItem firstVideo =
data.dash!.video!.firstWhere((i) => i.id == currentVideoQa.code);
/// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl
List<VideoItem> videoList =
data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList();
VideoItem firstVideo = videoList
.firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code));
// String videoUrl = firstVideo.baseUrl!;
/// 根据currentAudioQa 重新设置audioUrl
@ -176,6 +180,13 @@ class VideoDetailController extends GetxController
if (firstAudio.id != null) {
currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!;
}
/// 优先顺序 设置中指定解码格式 -> 当前可选的首个解码格式
List<FormatItem> supportFormats = data.supportFormats!;
List supportDecodeFormats = supportFormats.first.codecs!;
currentDecodeFormats =
VideoDecodeFormatsCode.fromString(supportDecodeFormats.first)!;
await playerInit(
firstVideo,
audioUrl,

View File

@ -28,6 +28,7 @@ class _HeaderControlState extends State<HeaderControl> {
late PlayUrlModel videoInfo;
List<PlaySpeed> playSpeed = PlaySpeed.values;
TextStyle subTitleStyle = const TextStyle(fontSize: 12);
TextStyle titleStyle = const TextStyle(fontSize: 14);
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
@override
@ -81,7 +82,7 @@ class _HeaderControlState extends State<HeaderControl> {
enabled: false,
leading:
const Icon(Icons.network_cell_outlined, size: 20),
title: const Text('省流模式'),
title: Text('省流模式', style: titleStyle),
subtitle: Text('低画质 减少视频缓存', style: subTitleStyle),
trailing: Transform.scale(
scale: 0.75,
@ -99,22 +100,22 @@ class _HeaderControlState extends State<HeaderControl> {
),
),
),
Obx(
() => ListTile(
onTap: () => {Get.back(), showSetSpeedSheet()},
dense: true,
leading: const Icon(Icons.speed_outlined, size: 20),
title: const Text('播放速度'),
subtitle: Text(
'当前倍速 x${widget.controller!.playbackSpeed}',
style: subTitleStyle),
),
),
// Obx(
// () => ListTile(
// onTap: () => {Get.back(), showSetSpeedSheet()},
// dense: true,
// leading: const Icon(Icons.speed_outlined, size: 20),
// title: Text('播放速度', style: titleStyle),
// subtitle: Text(
// '当前倍速 x${widget.controller!.playbackSpeed}',
// style: subTitleStyle),
// ),
// ),
ListTile(
onTap: () => {Get.back(), showSetVideoQa()},
dense: true,
leading: const Icon(Icons.play_circle_outline, size: 20),
title: const Text('选择画质'),
title: Text('选择画质', style: titleStyle),
subtitle: Text(
'当前画质 ${widget.videoDetailCtr!.currentVideoQa.description}',
style: subTitleStyle),
@ -123,24 +124,33 @@ class _HeaderControlState extends State<HeaderControl> {
onTap: () => {Get.back(), showSetAudioQa()},
dense: true,
leading: const Icon(Icons.album_outlined, size: 20),
title: const Text('选择音质'),
title: Text('选择音质', style: titleStyle),
subtitle: Text(
'当前音质 ${widget.videoDetailCtr!.currentAudioQa.description}',
style: subTitleStyle),
),
ListTile(
onTap: () {},
onTap: () => {Get.back(), showSetDecodeFormats()},
dense: true,
enabled: false,
leading: const Icon(Icons.play_circle_outline, size: 20),
title: const Text('播放设置'),
leading: const Icon(Icons.av_timer_outlined, size: 20),
title: Text('解码格式', style: titleStyle),
subtitle: Text(
'当前解码格式 ${widget.videoDetailCtr!.currentDecodeFormats.description}',
style: subTitleStyle),
),
// ListTile(
// onTap: () {},
// dense: true,
// enabled: false,
// leading: const Icon(Icons.play_circle_outline, size: 20),
// title: Text('播放设置', style: titleStyle),
// ),
ListTile(
onTap: () {},
dense: true,
enabled: false,
leading: const Icon(Icons.subtitles_outlined, size: 20),
title: const Text('弹幕设置'),
title: Text('弹幕设置', style: titleStyle),
),
],
),
@ -250,7 +260,7 @@ class _HeaderControlState extends State<HeaderControl> {
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('选择画质'),
Text('选择画质', style: titleStyle),
const SizedBox(width: 4),
Icon(
Icons.info_outline,
@ -329,7 +339,9 @@ class _HeaderControlState extends State<HeaderControl> {
margin: const EdgeInsets.all(12),
child: Column(
children: [
const SizedBox(height: 45, child: Center(child: Text('选择音质'))),
SizedBox(
height: 45,
child: Center(child: Text('选择音质', style: titleStyle))),
Expanded(
child: Material(
child: ListView(
@ -370,6 +382,74 @@ class _HeaderControlState extends State<HeaderControl> {
);
}
// 选择解码格式
void showSetDecodeFormats() {
// 当前选中的解码格式
VideoDecodeFormats currentDecodeFormats =
widget.videoDetailCtr!.currentDecodeFormats;
// 当前视频可用的解码格式
List<FormatItem> videoFormat = videoInfo.supportFormats!;
List list = videoFormat.first.codecs!;
showModalBottomSheet(
context: context,
elevation: 0,
backgroundColor: Colors.transparent,
builder: (BuildContext context) {
return Container(
width: double.infinity,
height: 250,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.background,
borderRadius: const BorderRadius.all(Radius.circular(12)),
),
margin: const EdgeInsets.all(12),
child: Column(
children: [
SizedBox(
height: 45,
child: Center(child: Text('选择解码格式', style: titleStyle))),
Expanded(
child: Material(
child: ListView(
children: [
for (var i in list) ...[
ListTile(
onTap: () {
widget.videoDetailCtr!.currentDecodeFormats =
VideoDecodeFormatsCode.fromString(i)!;
widget.videoDetailCtr!.updatePlayer();
Get.back();
},
dense: true,
contentPadding:
const EdgeInsets.only(left: 20, right: 20),
title: Text(VideoDecodeFormatsCode.fromString(i)!
.description!),
subtitle: Text(
i!,
style: subTitleStyle,
),
trailing: i.startsWith(currentDecodeFormats.code)
? Icon(
Icons.done,
color: Theme.of(context).colorScheme.primary,
)
: const SizedBox(),
),
]
],
),
),
),
],
),
);
},
);
}
@override
Widget build(BuildContext context) {
final _ = widget.controller!;