11import 'dart:async' ;
22import 'dart:io' ;
33
4+ import 'package:file_picker/file_picker.dart' ;
45import 'package:fluent_ui/fluent_ui.dart' ;
56import 'package:flutter/services.dart' ;
7+ import 'package:flutter_i18n/flutter_i18n.dart' ;
68import 'package:get/get.dart' ;
79import 'package:media_kit/media_kit.dart' ;
810import 'package:media_kit_video/media_kit_video.dart' ;
911import 'package:miru_app/models/index.dart' ;
1012import 'package:miru_app/pages/home/controller.dart' ;
13+ import 'package:miru_app/router/router.dart' ;
1114import 'package:miru_app/utils/database.dart' ;
1215import 'package:miru_app/utils/extension_runtime.dart' ;
1316import 'package:miru_app/utils/i18n.dart' ;
@@ -38,6 +41,9 @@ class VideoPlayerController extends GetxController {
3841 final isOpenSidebar = false .obs;
3942 final isFullScreen = false .obs;
4043 late final index = playIndex.obs;
44+ final List <ExtensionBangumiWatchSubtitle > subtitles =
45+ < ExtensionBangumiWatchSubtitle > [].obs;
46+ final selectedSubtitle = 0. obs;
4147
4248 // 是否已经自动跳转到上次播放进度
4349 bool _isAutoSeekPosition = false ;
@@ -55,14 +61,69 @@ class VideoPlayerController extends GetxController {
5561 SystemChrome .setEnabledSystemUIMode (SystemUiMode .immersiveSticky);
5662 }
5763 play ();
64+
65+ // 切换剧集
5866 ever (index, (callback) {
5967 play ();
6068 });
69+
70+ // 显示剧集列表
6171 ever (showPlayList, (callback) {
6272 if (! showPlayList.value) {
6373 isOpenSidebar.value = false ;
6474 }
6575 });
76+
77+ // 切换字幕
78+ ever (selectedSubtitle, (callback) {
79+ if (callback == - 1 ) {
80+ player.setSubtitleTrack (SubtitleTrack .no ());
81+ return ;
82+ }
83+ if (callback == - 2 ) {
84+ // 选择文件 srt 或者 vtt
85+ FilePicker .platform.pickFiles (
86+ type: FileType .custom,
87+ allowedExtensions: ['srt' , 'vtt' ],
88+ ).then ((value) {
89+ if (value == null ) {
90+ selectedSubtitle.value = - 1 ;
91+ return ;
92+ }
93+
94+ // 读取文件
95+ final data = File (value.files.first.path! ).readAsStringSync ();
96+ player.setSubtitleTrack (SubtitleTrack .data (data));
97+ sendMessage (
98+ Message (
99+ Text (
100+ FlutterI18n .translate (
101+ cuurentContext,
102+ "video.subtitle-change" ,
103+ translationParams: {"title" : value.files.first.name},
104+ ),
105+ ),
106+ ),
107+ );
108+ });
109+ return ;
110+ }
111+ player.setSubtitleTrack (
112+ SubtitleTrack .uri (subtitles[callback].url),
113+ );
114+ sendMessage (
115+ Message (
116+ Text (
117+ FlutterI18n .translate (
118+ cuurentContext,
119+ "video.subtitle-change" ,
120+ translationParams: {"title" : subtitles[callback].title},
121+ ),
122+ ),
123+ ),
124+ );
125+ });
126+
66127 // 自动切换下一集
67128 player.stream.completed.listen ((event) {
68129 if (index.value == playList.length - 1 && event) {
@@ -84,6 +145,7 @@ class VideoPlayerController extends GetxController {
84145 runtime.extension .package,
85146 detailUrl,
86147 );
148+
87149 if (history != null &&
88150 history.progress.isNotEmpty &&
89151 history.episodeId == index.value &&
@@ -104,10 +166,12 @@ class VideoPlayerController extends GetxController {
104166
105167 play () async {
106168 try {
169+ subtitles.clear ();
170+ selectedSubtitle.value = - 1 ;
107171 final playUrl = playList[index.value].url;
108- final m3u8Url =
109- ( await runtime. watch (playUrl) as ExtensionBangumiWatch ) .url;
110- player. open ( Media (m3u8Url) );
172+ final watchData = await runtime. watch (playUrl) as ExtensionBangumiWatch ;
173+ player. open ( Media (watchData .url)) ;
174+ subtitles. addAll (watchData.subtitles ?? [] );
111175 } catch (e) {
112176 debugPrint (e.toString ());
113177 sendMessage (
@@ -203,6 +267,5 @@ class VideoPlayerController extends GetxController {
203267class Message {
204268 final Widget child;
205269 final Duration time;
206-
207270 Message (this .child, {this .time = const Duration (seconds: 3 )});
208271}
0 commit comments