Skip to content

Commit

Permalink
enable media-kit & add player error dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
Predidit committed Dec 17, 2024
1 parent 565a493 commit 801a596
Show file tree
Hide file tree
Showing 15 changed files with 307 additions and 152 deletions.
4 changes: 2 additions & 2 deletions lib/bean/anime/anime_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class _AnimeInfoCardState extends State<AnimeInfoCard> {
SmartDialog.dismiss();
if (widget.info.progress != 1) {
SmartDialog.showToast(i18n.toast.historyToast(episode: widget.info.progress ?? 1),
displayType: SmartToastType.last);
displayType: SmartToastType.onlyRefresh);
}
videoController.link = widget.info.link!;
videoController.offset = history?.offset ?? 0;
Expand Down Expand Up @@ -213,7 +213,7 @@ class _AnimeInfoCardState extends State<AnimeInfoCard> {
});
SmartDialog.showToast(
follow ? i18n.toast.favoriteToast : i18n.toast.dismissFavorite,
displayType: SmartToastType.last);
displayType: SmartToastType.onlyRefresh);
}
},
splashColor: Theme.of(context)
Expand Down
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import 'package:oneanime/utils/storage.dart';
import 'package:flutter/services.dart';
import 'package:oneanime/utils/utils.dart';
import 'package:oneanime/pages/error/error.dart';
import 'package:media_kit/media_kit.dart';
import 'package:oneanime/i18n/strings.g.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
MediaKit.ensureInitialized();
LocaleSettings.useDeviceLocale();
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
await windowManager.ensureInitialized();
Expand Down
23 changes: 0 additions & 23 deletions lib/pages/init_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'dart:ffi';

import 'package:flutter/material.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:fvp/fvp.dart' as fvp;
import 'package:hive/hive.dart';
import 'package:oneanime/pages/my/my_controller.dart';
import 'package:oneanime/utils/storage.dart';
Expand Down Expand Up @@ -37,28 +36,6 @@ class _InitPageState extends State<InitPage> {
if (autoUpdate) {
update();
}

/// mdk初始化
HAenable = setting.get(SettingBoxKey.HAenable, defaultValue: true);
if (HAenable) {
fvp.registerWith(options: {
'player': {
'avio.reconnect': '1',
'avio.reconnect_delay_max': '7',
'buffer': '2000+150000',
},
});
} else {
fvp.registerWith(options: {
'video.decoders': ['FFmpeg'],
'player': {
'avio.reconnect': '1',
'avio.reconnect_delay_max': '7',
'buffer': '2000+150000',
},
});
}

_checkStatements();
}

Expand Down
89 changes: 57 additions & 32 deletions lib/pages/player/player_controller.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'dart:io';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:mobx/mobx.dart';
import 'package:video_player/video_player.dart';
import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart';
import 'package:oneanime/utils/constans.dart';
import 'package:flutter/foundation.dart';
Expand All @@ -16,7 +19,8 @@ abstract class _PlayerController with Store {
String videoCookie = '';
bool playResume = false;
Box setting = GStorage.setting;
late VideoPlayerController mediaPlayer;
late Player mediaPlayer;
late VideoController videoController;
late DanmakuController danmakuController;

// 当前播放器状态
Expand All @@ -34,14 +38,7 @@ abstract class _PlayerController with Store {
debugPrint('未找到已经存在的 player');
}
debugPrint('VideoURL开始初始化');
mediaPlayer = await createVideoController();
bool aotoPlay = setting.get(SettingBoxKey.autoPlay, defaultValue: true);
if (offset != 0 && playResume) {
await mediaPlayer.seekTo(Duration(seconds: offset));
}
if (aotoPlay) {
await mediaPlayer.play();
}
mediaPlayer = await createVideoController(offset: offset);
danmakuController.clear();
debugPrint('VideoURL初始化完成');
dataStatus = 'loaded';
Expand All @@ -56,58 +53,86 @@ abstract class _PlayerController with Store {
}
}

Future<VideoPlayerController> createVideoController() async {
debugPrint('videoController 配置成功');

Future<Player> createVideoController({int offset = 0}) async {
var httpHeaders = {
'user-agent':
Utils.getRandomUA(),
'user-agent': Utils.getRandomUA(),
'referer': HttpString.baseUrl,
'Cookie': videoCookie,
};
bool hAenable = setting.get(SettingBoxKey.HAenable, defaultValue: true);
bool aotoPlay = setting.get(SettingBoxKey.autoPlay, defaultValue: true);
mediaPlayer = Player(
configuration: const PlayerConfiguration(
bufferSize: 15 * 1024 * 1024,
),
);

var pp = mediaPlayer.platform as NativePlayer;
await pp.setProperty("af", "scaletempo2=max-speed=8");
if (Platform.isAndroid) {
await pp.setProperty("volume-max", "100");
await pp.setProperty("ao", "opensles");
}

mediaPlayer = VideoPlayerController.networkUrl(Uri.parse(videoUrl),
httpHeaders: httpHeaders);
await mediaPlayer.initialize();
await mediaPlayer.setAudioTrack(
AudioTrack.auto(),
);

videoController = VideoController(
mediaPlayer,
configuration: VideoControllerConfiguration(
enableHardwareAcceleration: hAenable,
androidAttachSurfaceAfterVideoParameters: false,
),
);
mediaPlayer.setPlaylistMode(PlaylistMode.none);

// error handle
mediaPlayer.stream.error.listen((event) {
SmartDialog.showToast(
'Player intent error ${event.toString()} $videoUrl', displayType: SmartToastType.onlyRefresh,
);
});

await mediaPlayer.open(
Media(videoUrl,
start: Duration(seconds: offset), httpHeaders: httpHeaders),
play: aotoPlay,
);
return mediaPlayer;
}

Function get setRate {
return mediaPlayer.setPlaybackSpeed;
return mediaPlayer.setRate;
}

bool get playing {
return mediaPlayer.value.isPlaying;
return mediaPlayer.state.playing;
}

bool get buffering {
return mediaPlayer.value.isBuffering;
return mediaPlayer.state.buffering;
}

Duration get position {
return mediaPlayer.value.position;
return mediaPlayer.state.position;
}

Duration get buffer {
if (mediaPlayer.value.buffered.isEmpty) {
return Duration.zero;
}

Duration maxDuration = mediaPlayer.value.buffered[0].end;
return maxDuration;
return mediaPlayer.state.buffer;
}

Duration get duration {
return mediaPlayer.value.duration;
return mediaPlayer.state.duration;
}

bool get completed {
return mediaPlayer.value.isCompleted;
return mediaPlayer.state.completed;
}

Future seek(Duration duration) async {
danmakuController.clear();
await mediaPlayer.seekTo(duration);
await mediaPlayer.seek(duration);
}

Future pause() async {
Expand All @@ -121,7 +146,7 @@ abstract class _PlayerController with Store {
}

Future playOrPause() async {
if (mediaPlayer.value.isPlaying) {
if (mediaPlayer.state.playing) {
pause();
} else {
play();
Expand Down
31 changes: 26 additions & 5 deletions lib/pages/player/player_item.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:oneanime/pages/player/player_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:video_player/video_player.dart';
import 'package:media_kit_video/media_kit_video.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:oneanime/pages/video/video_controller.dart' as videoPage;

Expand Down Expand Up @@ -33,10 +33,31 @@ class _PlayerItemState extends State<PlayerItem> {
Widget build(BuildContext context) {
return Observer(builder: (context) {
return playerController.dataStatus == 'loaded'
? AspectRatio(
aspectRatio: playerController.mediaPlayer.value.aspectRatio,
child: VideoPlayer(
playerController.mediaPlayer,
? Video(
controller: playerController.videoController,
controls: NoVideoControls,
subtitleViewConfiguration: SubtitleViewConfiguration(
style: TextStyle(
color: Colors.pink,
fontSize: 48.0,
background: Paint()..color = Colors.transparent,
decoration: TextDecoration.none,
fontWeight: FontWeight.bold,
shadows: const [
Shadow(
offset: Offset(1.0, 1.0),
blurRadius: 3.0,
color: Color.fromARGB(255, 255, 255, 255),
),
Shadow(
offset: Offset(-1.0, -1.0),
blurRadius: 3.0,
color: Color.fromARGB(125, 255, 255, 255),
),
],
),
textAlign: TextAlign.center,
padding: const EdgeInsets.all(24.0),
),
)
: const Center(child: CircularProgressIndicator());
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/settings/player_settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class _PlayerSettingsPageState extends State<PlayerSettingsPage> {
title: i18n.my.playerSettings.hardwareAcceleration,
setKey: SettingBoxKey.HAenable,
defaultVal: true,
needReboot: true,
needReboot: false,
),
),
InkWell(
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/timeline/timeline_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ class _TimelinePageState extends State<TimelinePage>
listen: false);
Modular.to.pushNamed('/video/');
} else {
SmartDialog.showToast(i18n.toast.animeNotExist, displayType: SmartToastType.last);
SmartDialog.showToast(i18n.toast.animeNotExist, displayType: SmartToastType.onlyRefresh);
}
},
child: Align(
Expand Down
13 changes: 5 additions & 8 deletions lib/pages/video/video_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import 'package:hive/hive.dart';
import 'package:oneanime/bean/appbar/drag_to_move_bar.dart' as dtb;
import 'package:oneanime/utils/storage.dart';
import 'package:oneanime/utils/utils.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:oneanime/i18n/strings.g.dart';

class VideoPage extends StatefulWidget {
Expand Down Expand Up @@ -129,7 +128,7 @@ class _VideoPageState extends State<VideoPage>

void _handleDanmaku() {
if (videoController.danDanmakus.isEmpty) {
SmartDialog.showToast('当前剧集没有找到弹幕的说', displayType: SmartToastType.last);
SmartDialog.showToast('当前剧集没有找到弹幕的说', displayType: SmartToastType.onlyRefresh);
return;
}
danmakuController.clear();
Expand Down Expand Up @@ -158,7 +157,6 @@ class _VideoPageState extends State<VideoPage>
WidgetsBinding.instance.addPostFrameCallback((_) {
FocusScope.of(context).requestFocus(_focusNode);
});
WakelockPlus.enable();
bool alwaysOntop =
setting.get(SettingBoxKey.alwaysOntop, defaultValue: true);
if (alwaysOntop &&
Expand Down Expand Up @@ -202,7 +200,6 @@ class _VideoPageState extends State<VideoPage>
@override
void dispose() {
_focusNode.dispose();
WakelockPlus.disable();
WidgetsBinding.instance.removeObserver(this);
try {
playerTimer!.cancel();
Expand Down Expand Up @@ -887,7 +884,7 @@ class _VideoPageState extends State<VideoPage>
// 自定义顶部组件
Visibility(
visible: showPositioned ||
!playerController.mediaPlayer.value.isPlaying,
!playerController.mediaPlayer.state.playing,
child: Positioned(
top: 0,
left: 0,
Expand Down Expand Up @@ -935,7 +932,7 @@ class _VideoPageState extends State<VideoPage>
videoController.follow
? i18n.toast.favoriteToast
: i18n.toast.dismissFavorite,
displayType: SmartToastType.last);
displayType: SmartToastType.onlyRefresh);
},
splashColor: Theme.of(context)
.colorScheme
Expand All @@ -950,7 +947,7 @@ class _VideoPageState extends State<VideoPage>
// 自定义播放器底部组件
Visibility(
visible: showPositioned ||
!playerController.mediaPlayer.value.isPlaying,
!playerController.mediaPlayer.state.playing,
child: Positioned(
bottom: 0,
left: 0,
Expand Down Expand Up @@ -978,7 +975,7 @@ class _VideoPageState extends State<VideoPage>
if (videoController.episode ==
videoController.token.length) {
SmartDialog.showToast('已经是最新一集',
displayType: SmartToastType.last);
displayType: SmartToastType.onlyRefresh);
return;
}
SmartDialog.showToast(
Expand Down
12 changes: 8 additions & 4 deletions linux/flutter/generated_plugin_registrant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
#include "generated_plugin_registrant.h"

#include <flutter_volume_controller/flutter_volume_controller_plugin.h>
#include <fvp/fvp_plugin.h>
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
#include <media_kit_video/media_kit_video_plugin.h>
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h>
Expand All @@ -16,9 +17,12 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_volume_controller_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterVolumeControllerPlugin");
flutter_volume_controller_plugin_register_with_registrar(flutter_volume_controller_registrar);
g_autoptr(FlPluginRegistrar) fvp_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FvpPlugin");
fvp_plugin_register_with_registrar(fvp_registrar);
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
g_autoptr(FlPluginRegistrar) media_kit_video_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitVideoPlugin");
media_kit_video_plugin_register_with_registrar(media_kit_video_registrar);
g_autoptr(FlPluginRegistrar) screen_retriever_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin");
screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar);
Expand Down
3 changes: 2 additions & 1 deletion linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

list(APPEND FLUTTER_PLUGIN_LIST
flutter_volume_controller
fvp
media_kit_libs_linux
media_kit_video
screen_retriever_linux
url_launcher_linux
window_manager
Expand Down
Loading

0 comments on commit 801a596

Please sign in to comment.