import 'dart:async'; import 'package:fijkplayer/fijkplayer.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:video_player/video_player.dart'; import 'dart:math'; class CustomVideoPlayer extends StatefulWidget { final String url; const CustomVideoPlayer({super.key, required this.url}); @override State createState() => _CustomVideoPlayerState(); } class _CustomVideoPlayerState extends State { FijkPlayer? player; VideoPlayerController? _controller; Timer? _timer; _CustomVideoPlayerState(); @override void initState() { super.initState(); WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setPreferredOrientations( [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); initVideoPlayer(); // initFijkPlayer(); } void initVideoPlayer() { _controller = VideoPlayerController.networkUrl(Uri.parse(widget.url)) ..initialize().then((_) { // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed. setState(() { _controller!.play(); }); }); } Future initFijkPlayer() async { player = FijkPlayer(); await player!.setDataSource(widget.url, autoPlay: true); bool init = false; player?.addListener(() { if (player!.value.videoRenderStart && !init) { init = true; player!.enterFullScreen(); } }); } void onKey(RawKeyEvent event) { if (event is RawKeyUpEvent) return; RawKeyEventDataAndroid e = event.data as RawKeyEventDataAndroid; switch (e.keyCode) { case 21: int pos = _controller!.value.position.inMilliseconds; _controller!.seekTo(Duration(milliseconds: pos - 30000)); break; case 22: int pos = _controller!.value.position.inMilliseconds; _controller!.seekTo(Duration(milliseconds: pos + 30000)); break; case 62: if (_controller!.value.isPlaying) { _controller!.pause(); } else { _controller!.play(); } break; default: debugPrint("$e"); } } void fijkOnKey(RawKeyEvent event) { if (event is RawKeyUpEvent) return; switch (event.character) { case ' ': if (player?.state == FijkState.paused) { player?.start(); } else { player?.pause(); } break; default: switch ((event.data as RawKeyEventDataAndroid).keyCode) { case 22: // player!.pause().then((value) { int pos = min(player!.value.duration.inMilliseconds, player!.currentPos.inMilliseconds + 30000); player!.seekTo(pos).then((value) { if (_timer != null) { _timer!.cancel(); } _timer = Timer(const Duration(milliseconds: 500), () { player!.start(); _timer = null; }); }); // }); break; } return; } } @override Widget build(BuildContext context) { return Scaffold( // appBar: AppBar( // toolbarHeight: 35, // ), body: player == null ? PopScope( onPopInvoked: (val) { if (!val) { return; } _controller!.pause(); }, child: Center( child: _controller!.value.isInitialized ? AspectRatio( aspectRatio: _controller!.value.aspectRatio, child: RawKeyboardListener( onKey: onKey, autofocus: true, focusNode: FocusNode(), child: VideoPlayer(_controller!), ), ) : Container(), ), ) : Container( alignment: Alignment.center, child: RawKeyboardListener( onKey: fijkOnKey, focusNode: FocusNode(), autofocus: true, child: FijkView( player: player!, panelBuilder: (FijkPlayer player, FijkData data, BuildContext context, Size viewSize, Rect texturePos) { return RawKeyboardListener( onKey: fijkOnKey, focusNode: FocusNode(), autofocus: true, child: PopScope( onPopInvoked: (val) { if (!val) { return; } this.player?.exitFullScreen(); }, child: Stack(children: [ defaultFijkPanelBuilder( player, data, context, viewSize, texturePos), ]), )); }, ), )), ); } @override void dispose() { super.dispose(); SystemChrome.setPreferredOrientations([]); player?.stop().then((value) => player?.dispose()); _controller?.dispose(); } }