Flutter视频播放插件video_player_media_kit的使用
Flutter视频播放插件video_player_media_kit的使用
package:video_player_media_kit
是基于package:media_kit
构建的,为所有平台提供支持(如Android、iOS、macOS、Windows、GNU/Linux和Web),并支持更多的视频/音频格式和编解码器。它允许package:video_player
使用package:media_kit
作为后端。下面将详细介绍如何安装和使用这个插件。
安装
在pubspec.yaml
文件中添加依赖:
dependencies:
video_player_media_kit: ^1.0.5
# 根据需要选择对应的平台库
media_kit_libs_android_video: any
media_kit_libs_ios_video: any
media_kit_libs_macos_video: any
media_kit_libs_windows_video: any
media_kit_libs_linux: any
确保根据你计划支持的平台添加相应的media_kit_libs_***
包。
初始化
在应用程序入口处初始化VideoPlayerMediaKit
:
void main() {
VideoPlayerMediaKit.ensureInitialized(
android: true, // default: false - dependency: media_kit_libs_android_video
iOS: true, // default: false - dependency: media_kit_libs_ios_video
macOS: true, // default: false - dependency: media_kit_libs_macos_video
windows: true, // default: false - dependency: media_kit_libs_windows_video
linux: true, // default: false - dependency: media_kit_libs_linux
);
runApp(MyApp());
}
示例代码
以下是一个完整的示例demo,展示了如何在Flutter应用中使用video_player_media_kit
播放本地和远程视频,并提供了基本的控制功能(如播放、暂停、调整播放速度等)。
主程序入口 (main.dart
)
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:video_player_media_kit/video_player_media_kit.dart';
void main() {
VideoPlayerMediaKit.ensureInitialized(
macOS: true,
windows: true,
linux: true,
);
runApp(
MaterialApp(
home: _App(),
),
);
}
class _App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: const Text('Video player example'),
bottom: const TabBar(
isScrollable: true,
tabs: [
Tab(icon: Icon(Icons.cloud), text: 'Remote'),
Tab(icon: Icon(Icons.insert_drive_file), text: 'Asset'),
Tab(icon: Icon(Icons.list), text: 'List example'),
],
),
),
body: TabBarView(
children: [
_BumbleBeeRemoteVideo(),
_ButterFlyAssetVideo(),
_ButterFlyAssetVideoInList(),
],
),
),
);
}
}
class _ButterFlyAssetVideoInList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children: [
for (var i = 'a'; i != 'h'; i = String.fromCharCode(i.codeUnitAt(0) + 1))
_ExampleCard(title: 'Item $i'),
Card(
child: Column(children: [
Column(
children: [
const ListTile(
leading: Icon(Icons.cake),
title: Text('Video video'),
),
Stack(
alignment: FractionalOffset.bottomRight + const FractionalOffset(-0.1, -0.1),
children: [
_ButterFlyAssetVideo(),
Image.asset('assets/flutter-mark-square-64.png'),
],
),
],
),
]),
),
for (var i = 'h'; i <= 'l'; i = String.fromCharCode(i.codeUnitAt(0) + 1))
_ExampleCard(title: 'Item $i'),
],
);
}
}
class _ExampleCard extends StatelessWidget {
final String title;
_ExampleCard({required this.title});
@override
Widget build(BuildContext context) {
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.airline_seat_flat_angled),
title: Text(title),
),
ButtonBar(
children: [
TextButton(
child: const Text('BUY TICKETS'),
onPressed: () {},
),
TextButton(
child: const Text('SELL TICKETS'),
onPressed: () {},
),
],
),
],
),
);
}
}
class _ButterFlyAssetVideo extends StatefulWidget {
@override
_ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState();
}
class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> {
late VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.asset('assets/Butterfly-209.mp4');
_controller.addListener(() {
setState(() {});
});
_controller.setLooping(true);
_controller.initialize().then((_) => setState(() {}));
_controller.play();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
Container(padding: const EdgeInsets.only(top: 20.0)),
const Text('With assets mp4'),
Container(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
VideoPlayer(_controller),
_ControlsOverlay(controller: _controller),
VideoProgressIndicator(_controller, allowScrubbing: true),
],
),
),
),
],
),
);
}
}
class _BumbleBeeRemoteVideo extends StatefulWidget {
@override
_BumbleBeeRemoteVideoState createState() => _BumbleBeeRemoteVideoState();
}
class _BumbleBeeRemoteVideoState extends State<_BumbleBeeRemoteVideo> {
late VideoPlayerController _controller;
Future<ClosedCaptionFile> _loadCaptions() async {
final String fileContents = await DefaultAssetBundle.of(context)
.loadString('assets/bumble_bee_captions.vtt');
return WebVTTCaptionFile(fileContents);
}
@override
void initState() {
super.initState();
_controller = VideoPlayerController.networkUrl(
Uri.parse('https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'),
closedCaptionFile: _loadCaptions(),
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
);
_controller.addListener(() {
setState(() {});
});
_controller.setLooping(true);
_controller.initialize();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
Container(padding: const EdgeInsets.only(top: 20.0)),
const Text('With remote mp4'),
Container(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
VideoPlayer(_controller),
ClosedCaption(text: _controller.value.caption.text),
_ControlsOverlay(controller: _controller),
VideoProgressIndicator(_controller, allowScrubbing: true),
],
),
),
),
],
),
);
}
}
class _ControlsOverlay extends StatelessWidget {
final VideoPlayerController controller;
const _ControlsOverlay({required this.controller});
static const List<Duration> _exampleCaptionOffsets = <Duration>[
Duration(seconds: -10),
Duration(seconds: -3),
Duration(milliseconds: -850),
Duration(milliseconds: -500),
Duration(milliseconds: -250),
Duration.zero,
Duration(milliseconds: 250),
Duration(seconds: 1, milliseconds: 500),
Duration(seconds: 3),
Duration(seconds: 10),
];
static const List<double> _examplePlaybackRates = <double>[
0.25,
0.5,
1.0,
1.5,
2.0,
3.0,
5.0,
10.0,
];
@override
Widget build(BuildContext context) {
return Stack(
children: [
AnimatedSwitcher(
duration: const Duration(milliseconds: 50),
reverseDuration: const Duration(milliseconds: 200),
child: controller.value.isPlaying
? const SizedBox.shrink()
: Container(
color: Colors.black26,
child: const Center(
child: Icon(
Icons.play_arrow,
color: Colors.white,
size: 100.0,
semanticLabel: 'Play',
),
),
),
),
GestureDetector(
onTap: () {
controller.value.isPlaying ? controller.pause() : controller.play();
},
),
Align(
alignment: Alignment.topLeft,
child: PopupMenuButton<Duration>(
initialValue: controller.value.captionOffset,
tooltip: 'Caption Offset',
onSelected: (Duration delay) {
controller.setCaptionOffset(delay);
},
itemBuilder: (BuildContext context) {
return <PopupMenuItem<Duration>>[
for (final Duration offsetDuration in _exampleCaptionOffsets)
PopupMenuItem<Duration>(
value: offsetDuration,
child: Text('${offsetDuration.inMilliseconds}ms'),
)
];
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
child: Text('${controller.value.captionOffset.inMilliseconds}ms'),
),
),
),
Align(
alignment: Alignment.topRight,
child: PopupMenuButton<double>(
initialValue: controller.value.playbackSpeed,
tooltip: 'Playback speed',
onSelected: (double speed) {
controller.setPlaybackSpeed(speed);
},
itemBuilder: (BuildContext context) {
return <PopupMenuItem<double>>[
for (final double speed in _examplePlaybackRates)
PopupMenuItem<double>(
value: speed,
child: Text('${speed}x'),
)
];
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
child: Text('${controller.value.playbackSpeed}x'),
),
),
),
],
);
}
}
class _PlayerVideoAndPopPage extends StatefulWidget {
@override
_PlayerVideoAndPopPageState createState() => _PlayerVideoAndPopPageState();
}
class _PlayerVideoAndPopPageState extends State<_PlayerVideoAndPopPage> {
late VideoPlayerController _videoPlayerController;
bool startedPlaying = false;
@override
void initState() {
super.initState();
_videoPlayerController = VideoPlayerController.asset('assets/Butterfly-209.mp4');
_videoPlayerController.addListener(() {
if (startedPlaying && !_videoPlayerController.value.isPlaying) {
Navigator.pop(context);
}
});
}
@override
void dispose() {
_videoPlayerController.dispose();
super.dispose();
}
Future<bool> started() async {
await _videoPlayerController.initialize();
await _videoPlayerController.play();
startedPlaying = true;
return true;
}
@override
Widget build(BuildContext context) {
return Material(
child: Center(
child: FutureBuilder<bool>(
future: started(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (snapshot.data ?? false) {
return AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
child: VideoPlayer(_videoPlayerController),
);
} else {
return const Text('waiting for video to load');
}
},
),
),
);
}
}
此示例展示了如何在Flutter应用中使用video_player_media_kit
播放本地和远程视频,并提供了基本的控制功能(如播放、暂停、调整播放速度等)。你可以根据自己的需求进行修改和扩展。
更多关于Flutter视频播放插件video_player_media_kit的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter视频播放插件video_player_media_kit的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用Flutter中的video_player_media_kit
插件来播放视频的示例代码。这个插件主要用于在iOS和Android平台上播放视频,特别是针对iOS上的MediaKit进行优化。
首先,确保你已经在pubspec.yaml
文件中添加了video_player_media_kit
依赖:
dependencies:
flutter:
sdk: flutter
video_player_media_kit: ^x.y.z # 替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来是一个简单的示例,展示如何使用video_player_media_kit
来播放一个本地或网络视频:
import 'package:flutter/material.dart';
import 'package:video_player_media_kit/video_player_media_kit.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: VideoPlayerScreen(),
);
}
}
class VideoPlayerScreen extends StatefulWidget {
@override
_VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
late VideoPlayerController _controller;
@override
void initState() {
super.initState();
// 初始化视频控制器,可以是一个本地视频文件路径或一个网络视频的URL
_controller = VideoPlayerController.network(
'https://www.example.com/path/to/your/video.mp4', // 替换为你的视频URL
)..initialize().then((_) {
// 确保在视频初始化完成后设置状态
setState(() {});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Video Player Demo'),
),
body: Center(
child: _controller.value.isInitialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(
child: CircularProgressIndicator(),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
);
}
}
在这个示例中,我们做了以下几件事:
-
初始化
VideoPlayerController
:- 使用
VideoPlayerController.network
方法来创建一个控制器,用于播放网络视频。如果你需要播放本地视频,可以使用VideoPlayerController.file
方法。
- 使用
-
初始化视频:
- 调用
initialize()
方法来异步初始化视频。在初始化完成后,通过then
方法更新UI状态。
- 调用
-
构建UI:
- 使用
AspectRatio
和VideoPlayer
小部件来显示视频。在视频未初始化完成时,显示一个加载指示器。
- 使用
-
控制播放:
- 使用一个
FloatingActionButton
来控制视频的播放和暂停。
- 使用一个
确保你替换示例中的视频URL为你自己的视频路径。这个插件在iOS上使用MediaKit进行优化,可以提供更好的性能和兼容性。如果你遇到任何问题,请查阅官方文档或插件的GitHub仓库以获取更多信息。