Skip to content

update:replace video_player->better_player_plus #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 32 additions & 18 deletions example/lib/widgets/preview_asset_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:better_player_plus/better_player_plus.dart';
import 'package:wechat_camera_picker/wechat_camera_picker.dart';

class PreviewAssetWidget extends StatefulWidget {
Expand All @@ -20,7 +20,7 @@ class PreviewAssetWidget extends StatefulWidget {
class _PreviewAssetWidgetState extends State<PreviewAssetWidget> {
bool get _isVideo => widget.asset.type == AssetType.video;
Object? _error;
VideoPlayerController? _playerController;
BetterPlayerController? _playerController;

@override
void initState() {
Expand All @@ -40,21 +40,36 @@ class _PreviewAssetWidgetState extends State<PreviewAssetWidget> {
final String? url = await widget.asset.getMediaUrl();
if (url == null) {
_error = StateError('The media URL of the preview asset is null.');
if (mounted) {
setState(() {});
}
return;
}
final VideoPlayerController controller;
final Uri uri = Uri.parse(url);
if (Platform.isAndroid) {
controller = VideoPlayerController.contentUri(uri);
} else {
controller = VideoPlayerController.networkUrl(uri);
}
_playerController = controller;
try {
await controller.initialize();
controller
..setLooping(true)
..play();
final betterPlayerDataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.network,
url,
videoFormat: BetterPlayerVideoFormat.other,
);
final betterPlayerConfiguration = BetterPlayerConfiguration(
autoPlay: true,
looping: true,
controlsConfiguration: BetterPlayerControlsConfiguration(
showControls: false,
),
errorBuilder: (context, errorMessage) {
return Center(
child: Text(
errorMessage ?? 'Failed to load video',
style: const TextStyle(color: Colors.white),
),
);
},
);
_playerController = BetterPlayerController(
betterPlayerConfiguration,
betterPlayerDataSource: betterPlayerDataSource,
);
} catch (e) {
_error = e;
} finally {
Expand All @@ -69,13 +84,12 @@ class _PreviewAssetWidgetState extends State<PreviewAssetWidget> {
}

Widget _buildVideo(BuildContext context) {
final VideoPlayerController? controller = _playerController;
final BetterPlayerController? controller = _playerController;
if (controller == null) {
return const CircularProgressIndicator();
}
return AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: VideoPlayer(controller),
return BetterPlayer(
controller: controller,
);
}

Expand Down
100 changes: 75 additions & 25 deletions lib/src/states/camera_picker_viewer_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@
import 'dart:async';
import 'dart:io';

import 'package:better_player_plus/better_player_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
import 'package:path/path.dart' as path;
import 'package:video_player/video_player.dart';
import 'package:wechat_picker_library/wechat_picker_library.dart';

import '../constants/config.dart';
import '../internals/singleton.dart';
import '../constants/enums.dart';
import '../constants/type_defs.dart';
import '../internals/methods.dart';
import '../internals/singleton.dart';
import '../widgets/camera_picker.dart';
import '../widgets/camera_picker_viewer.dart';

Expand All @@ -35,11 +36,11 @@ class CameraPickerViewerState extends State<CameraPickerViewer> {

/// Controller for the video player.
/// 视频播放的控制器
late final videoController = VideoPlayerController.file(previewFile);
BetterPlayerController? _controller;

/// Whether the controller is playing.
/// 播放控制器是否在播放
bool get isControllerPlaying => videoController.value.isPlaying;
bool get isControllerPlaying => _controller?.isPlaying() ?? false;

/// Whether the controller has initialized.
/// 控制器是否已初始化
Expand All @@ -64,22 +65,58 @@ class CameraPickerViewerState extends State<CameraPickerViewer> {

@override
void dispose() {
videoController
..removeListener(videoControllerListener)
..pause()
..dispose();
_controller?.removeEventsListener(betterPlayerListener);
_controller?.pause();
_controller?.dispose();
super.dispose();
}

Future<void> initializeVideoPlayerController() async {
try {
final betterPlayerDataSource = BetterPlayerDataSource(
BetterPlayerDataSourceType.file,
previewFile.path,
videoFormat: BetterPlayerVideoFormat.other,
);

// 使用 VideoPlayerController 获取宽高比
final videoController =
VideoPlayerController.file(File(previewFile.path));
await videoController.initialize();
videoController.addListener(videoControllerListener);
hasLoaded = true;
if (pickerConfig.shouldAutoPreviewVideo) {
videoController.play();
videoController.setLooping(true);
double aspectRatio = videoController.value.aspectRatio;
// 检查旋转角度
final orientation = videoController.value.rotationCorrection; // 如果可用
if (orientation == 90 || orientation == 270) {
aspectRatio = 1 / aspectRatio;
}
debugPrint('Error when initializing video controller:2222 $aspectRatio');

videoController.dispose(); // 释放临时控制器
final betterPlayerConfiguration = BetterPlayerConfiguration(
autoPlay: pickerConfig.shouldAutoPreviewVideo,
looping: pickerConfig.shouldAutoPreviewVideo,
aspectRatio: aspectRatio,
controlsConfiguration: BetterPlayerControlsConfiguration(
showControls: false,
),
errorBuilder: (context, errorMessage) {
hasErrorWhenInitializing = true;
safeSetState(() {});
return Center(
child: Text(
Singleton.textDelegate.loadFailed,
style: const TextStyle(inherit: false),
),
);
},
);
_controller = BetterPlayerController(
betterPlayerConfiguration,
betterPlayerDataSource: betterPlayerDataSource,
);

_controller!.addEventsListener(betterPlayerListener);
hasLoaded = true;
} catch (e, s) {
hasErrorWhenInitializing = true;
realDebugPrint('Error when initializing video controller: $e');
Expand All @@ -91,9 +128,19 @@ class CameraPickerViewerState extends State<CameraPickerViewer> {

/// Listener for the video player.
/// 播放器的监听方法
void videoControllerListener() {
if (isControllerPlaying != isPlaying.value) {
isPlaying.value = isControllerPlaying;
void betterPlayerListener(BetterPlayerEvent event) {
if (event.betterPlayerEventType == BetterPlayerEventType.initialized) {
debugPrint(
"_controller?.getAspectRatio(); ${_controller?.getAspectRatio()}");
}
if (event.betterPlayerEventType == BetterPlayerEventType.play) {
if (!isPlaying.value) {
isPlaying.value = true;
}
} else if (event.betterPlayerEventType == BetterPlayerEventType.pause) {
if (isPlaying.value) {
isPlaying.value = false;
}
}
}

Expand All @@ -106,14 +153,18 @@ class CameraPickerViewerState extends State<CameraPickerViewer> {
Future<void> playButtonCallback() async {
try {
if (isPlaying.value) {
videoController.pause();
_controller?.pause();
} else {
if (videoController.value.duration == videoController.value.position) {
videoController.seekTo(Duration.zero);
if (_controller != null &&
_controller!.videoPlayerController!.value.position >=
(_controller!.videoPlayerController!.value?.duration ??
Duration.zero)) {
_controller
?..seekTo(Duration.zero)
..play();
} else {
_controller?.play();
}
videoController
..play()
..setLooping(true);
}
} catch (e, s) {
handleErrorWithHandler(e, s, onError);
Expand Down Expand Up @@ -260,10 +311,9 @@ class CameraPickerViewerState extends State<CameraPickerViewer> {
builder = Stack(
children: <Widget>[
Center(
child: AspectRatio(
aspectRatio: videoController.value.aspectRatio,
child: VideoPlayer(videoController),
),
child: _controller != null
? BetterPlayer(controller: _controller!)
: const SizedBox.shrink(),
),
buildPlayControlButton(context),
],
Expand Down
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ dependencies:
photo_manager_image_provider: ^2.0.0
sensors_plus: '>=4.0.0 <7.0.0'
video_player: ^2.7.0
better_player_plus: ^1.0.8


dev_dependencies:
flutter_lints: any
Expand Down