Flutter多媒体处理插件media_kit_fork的使用
Flutter多媒体处理插件media_kit_fork的使用
介绍
package:media_kit_fork
是一个用于 Flutter 和 Dart 的跨平台视频播放器和音频播放器库。
安装
package:media_kit_fork
被拆分为多个包以提高模块化并减少包的大小。
对于需要视频播放的应用:
dependencies:
media_kit_fork: ^1.1.11 # 主要包。
media_kit_video: ^1.2.5 # 视频渲染。
media_kit_libs_video: ^1.0.5 # 原生视频依赖。
对于需要音频播放的应用:
dependencies:
media_kit_fork: ^1.1.11 # 主要包。
media_kit_libs_audio: ^1.0.5 # 原生音频依赖。
注意:
- 如果需要同时支持视频和音频,应选择视频库。
media_kit_libs_video
和media_kit_libs_audio
包不应混合使用。- 在“发布”模式下的性能显著高于“调试”模式。
- 在 Android 上启用
--split-per-abi
或使用 app bundle(而不是 APK)。
支持的平台
平台 | 视频 | 音频 | 备注 | Demo |
---|---|---|---|---|
Android | ✅ | ✅ | Android 5.0或以上 | 下载 |
iOS | ✅ | ✅ | iOS 9或以上 | 下载 |
macOS | ✅ | ✅ | macOS 10.9或以上 | 下载 |
Windows | ✅ | ✅ | Windows 7或以上 | 下载 |
GNU/Linux | ✅ | ✅ | 任何现代的GNU/Linux发行版 | 下载 |
Web | ✅ | ✅ | 任何现代的网页浏览器 | 访问 |
快速使用示例
// 确保在 pubspec.yaml 中添加以下包:
// * media_kit_fork
// * media_kit_video
// * media_kit_libs_video
import 'package:flutter/material.dart';
import 'package:media_kit_fork/media_kit_fork.dart'; // 提供 [Player], [Media], [Playlist] 等。
import 'package:media_kit_video/media_kit_video.dart'; // 提供 [VideoController] 和 [Video] 等。
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 对 package:media_kit_fork 进行必要的初始化。
MediaKit.ensureInitialized();
runApp(
const MaterialApp(
home: MyScreen(),
),
);
}
class MyScreen extends StatefulWidget {
const MyScreen({Key? key}) : super(key: key);
@override
State<MyScreen> createState() => MyScreenState();
}
class MyScreenState extends State<MyScreen> {
// 创建一个 [Player] 来控制播放。
late final player = Player();
// 创建一个 [VideoController] 来处理来自 [Player] 的视频输出。
late final controller = VideoController(player);
@override
void initState() {
super.initState();
// 播放一个 [Media] 或 [Playlist]。
player.open(Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4'));
}
@override
void dispose() {
player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width * 9.0 / 16.0,
// 使用 [Video] 小部件来显示视频输出。
child: Video(controller: controller),
),
);
}
}
注意: 可能需要添加所需的权限到项目中。
初始化
在使用该包之前必须调用 MediaKit.ensureInitialized
方法:
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 确保将所需包添加到 pubspec.yaml 中:
// * https://github.com/media-kit/media-kit#installation
// * https://pub.dev/packages/media_kit_fork#installation
MediaKit.ensureInitialized();
runApp(const MyApp());
}
该方法也有一些可选参数以自定义全局行为。为处理任何初始化错误,这可以由 try
/catch
包围。
创建一个 Player
Player
实例用于开始并控制媒体源(如 URL 或文件)的播放。
final Player player = Player();
在一般情况下,你可能永远不需要提供构造函数中的 configuration
参数。
final Player player = Player(
configuration: PlayerConfiguration(
// 提供你的选项:
title: '我的 awesome package:media_kit_fork 应用',
ready: () {
print('初始化完成。');
},
),
);
释放 Player
重要的是要释放分配给系统的资源:
await player.dispose();
打开一个 Media 或 Playlist
Playable
可以是一个 Media
或 Playlist
。
Media
: 单个播放源(文件或 URL)。Playlist
: 播放源队列(文件或 URL)。
使用 Player.open
方法加载并开始播放。
Media
final playable = Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4');
await player.open(playable);
Playlist
final playable = Playlist(
[
Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373709-603a7a89-2105-4e1b-a5a5-a6c3567c9a59.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373716-76da0a4e-225a-44e4-9ee7-3e9006dbc3e3.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373718-86ce5e1d-d195-45d5-baa6-ef94041d0b90.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373720-14d69157-1a56-4a78-a2f4-d7a134d7c3e9.mp4'),
],
);
await player.open(playable);
注意:
- 默认情况下,这将自动开始播放
playable
。这可以通过以下方式禁用:
await player.open(
playable,
play: false,
);
- 默认情况下,播放列表将从索引
0
开始。这可以通过以下方式更改:
final playable = Playlist(
[
Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373709-603a7a89-2105-4e1b-a5a5-a6c3567c9a59.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373716-76da0a4e-225a-44e4-9ee7-3e9006dbc3e3.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373718-86ce5e1d-d195-45d5-baa6-ef94041d0b90.mp4'),
Media('https://user-images.githubusercontent.com/28951144/229373720-14d69157-1a56-4a78-a2f4-d7a134d7c3e9.mp4'),
],
// 声明起始位置。
index: 0,
);
await player.open(playable);
播放、暂停或播放/暂停
有三种方法:
await player.play();
await player.pause();
await player.playOrPause();
停止
stop
方法可用于停止当前打开的 Media
或 Playlist
的播放。
await player.stop();
它不会释放分配给系统的资源(不像 dispose
),并且 Player
仍然可用。
查找
向 Player.seek
方法提供最终位置作为 Duration
:
await player.seek(
const Duration(
minutes: 6,
seconds: 9,
),
);
循环或重复
有三个 PlaylistMode
:
PlaylistMode.none
: 到达播放列表末尾后停止播放。PlaylistMode.single
: 不断循环播放播放列表中的当前文件。PlaylistMode.loop
: 循环播放播放列表,并在到达末尾时从头开始重新播放。
await player.setPlaylistMode(PlaylistMode.single);
设置音量、速度或音高
设置音量
这控制音频输出的响度。最大音量为 100.0
。
await player.setVolume(50.0);
设置速度
这控制播放速度。
await player.setRate(1.5);
设置音高
这控制音频输出的音高。
await player.setPitch(1.2);
注意: 这需要在 PlayerConfiguration
中的 pitch
参数为 true
。
处理播放事件
你可以访问或订阅 Player
的状态变化。
事件处理是媒体播放的重要部分,用于在 UI 中显示更改,处理错误,检测播放/暂停、文件结束、位置更新等的发生。
Player.stream.*
: 提供对Player
的状态作为Stream
的访问。Player.state.*
: 直接提供对Player
的状态的访问(用于即时访问)。
一个典型的例子将是:
player.stream.playing.listen(
(bool playing) {
if (playing) {
// 正在播放。
} else {
// 已暂停。
}
},
);
player.stream.position.listen(
(Duration position) {
setState(() {
// 更新 UI。
});
},
);
可用的状态如下:
类型 | 名称 | 描述 |
---|---|---|
Stream<Playlist> |
playlist |
当前打开的媒体源。 |
Stream<bool> |
playing |
是否正在播放。 |
Stream<bool> |
completed |
当前播放的媒体源是否已到达结尾。 |
Stream<Duration> |
position |
当前播放位置。 |
Stream<Duration> |
duration |
当前播放持续时间。 |
Stream<double> |
volume |
当前音量。 |
Stream<double> |
rate |
当前播放速率。 |
Stream<double> |
pitch |
当前音高。 |
Stream<bool> |
buffering |
是否正在缓冲。 |
Stream<Duration> |
buffer |
当前缓冲位置。这表示流已被解码和缓存了多少。 |
Stream<PlaylistMode> |
playlistMode |
当前播放列表模式。 |
Stream<AudioParams> |
audioParams |
当前播放的媒体源的音频参数,例如采样率、通道数等。 |
Stream<VideoParams> |
videoParams |
当前播放的媒体源的视频参数,例如宽度、高度、旋转等。 |
Stream<double?> |
audioBitrate |
当前播放的媒体源的音频比特率。 |
Stream<AudioDevice> |
audioDevice |
当前选择的音频设备。 |
Stream<List<AudioDevice>> |
audioDevices |
当前可用的音频设备。 |
Stream<Track> |
track |
当前选择的视频、音频和字幕轨道。 |
Stream<Tracks> |
tracks |
当前可用的视频、音频和字幕轨道。 |
Stream<int> |
width |
当前播放视频的宽度。 |
Stream<int> |
height |
当前播放视频的高度。 |
Stream<int> |
subtitle |
当前显示的字幕。 |
Stream<PlayerLog> |
log |
内部日志。 |
Stream<String> |
error |
错误消息。这可以用于处理并向用户显示错误。 |
混淆队列
你可能会发现需要像某些音乐播放器一样混淆 Playlist
,你已在 Player
中 open
了。
await player.setShuffle(true);
注意: 这个选项将在下一个 Player.open
调用时重置。
使用 HTTP 头
在 Media
构造函数中声明 httpHeaders
参数。它接受 HTTP 头作为 Map<String, String>
。
final playable = Media(
'https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4',
httpHeaders: {
'Foo': 'Bar',
'Accept': '*/*',
'Range': 'bytes=0-',
},
);
使用 extras
存储媒体的额外数据
extras
参数可以用来以 Map<String, dynamic>
的形式存储 Media
的额外数据。
final playable = Media(
'https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4',
extras: {
'track': '9',
'year': '2012',
'title': 'Courtesy Call',
'artist': 'Thousand Foot Krutch',
'album': 'The End Is Where We Begin',
},
);
修改 Player 的队列
可以在已经播放的 Playlist
中添加或删除(等)一个 Media
:
添加
向队列末尾添加一个新的 Media
:
await player.add(Media('https://user-images.githubusercontent.com/28951144/229373695-22f88f13-d18f-4288-9bf1-c3e078d83722.mp4'));
删除
从队列中删除任何项目:
await player.remove(0);
移动
将队列中的任何项目从一个位置移动到另一个位置:
await player.move(6, 9);
转到队列中的下一曲、上一曲或其他位置
跳转到下一曲
await player.next();
跳转到上一曲
await player.previous();
跳转到其他曲目
await player.jump(5);
选择视频、音频或字幕轨道
媒体源可能包含多个视频、音频或字幕轨道,例如为多种语言。可用的视频、音频或字幕轨道通过 Player
的状态通知。有关相关信息,请参见“处理播放事件”部分。
默认情况下,视频、音频和字幕轨道会自动选择,即 VideoTrack.auto()
、AudioTrack.auto()
和 SubtitleTrack.auto()
。
自动选择
await player.setVideoTrack(VideoTrack.auto());
await player.setAudioTrack(AudioTrack.auto());
await player.setSubtitleTrack(SubtitleTrack.auto());
禁用轨道
这可以用于禁用视频输出、禁用音频输出或停止字幕渲染等。
await player.setVideoTrack(VideoTrack.no());
await player.setAudioTrack(AudioTrack.no());
await player.setSubtitleTrack(SubtitleTrack.no());
选择自定义轨道
- 检索当前可用的轨道:
List<VideoTrack> videos = player.state.tracks.video;
List<AudioTrack> audios = player.state.tracks.audio;
List<SubtitleTrack> subtitles = player.state.tracks.subtitle;
// 作为 [Stream] 获取通知:
player.stream.tracks.listen((event) {
List<VideoTrack> videos = event.video;
List<AudioTrack> audios = event.audio;
List<SubtitleTrack> subtitles = event.subtitle;
});
- 选择轨道:
await player.setVideoTrack(videos[0]);
await player.setAudioTrack(audios[1]);
await player.setSubtitleTrack(subtitles[2]);
- 获取当前选择的轨道的通知:
VideoTrack video = player.state.track.video;
AudioTrack audio = player.state.track.audio;
SubtitleTrack subtitle = player.state.track.subtitle;
// 作为 [Stream] 获取通知:
player.stream.track.listen((event) {
VideoTrack video = event.video;
AudioTrack audio = event.audio;
SubtitleTrack subtitle = event.subtitle;
});
选择音频设备
当前可用的音频设备通过 Player
的状态通知。有关相关信息,请参见“处理播放事件”部分。
默认情况下,音频设备会自动选择,即 AudioDevice.auto()
。
默认选择
await player.setAudioDevice(AudioDevice.auto());
禁用音频输出
await player.setAudioDevice(AudioDevice.no());
选择自定义音频设备
- 检索当前可用的音频设备:
List<AudioDevice> devices = player.state.audioDevices;
// 作为 [Stream] 获取通知:
player.stream.audioDevices.listen((event) {
List<AudioDevice> devices = event;
});
- 选择音频设备:
await player.setAudioDevice(devices[1]);
- 获取当前选择的音频设备的通知:
AudioDevice device = player.state.audioDevice;
// 作为 [Stream] 获取通知:
player.stream.audioDevice.listen((event) {
AudioDevice device = event;
});
显示视频
现有的“TL;DR 示例”应该为你提供更好的想法。
为了在 Flutter UI 中显示视频,你必须:
- 创建
VideoController
- 传递你已经有的
Player
。
- 传递你已经有的
- 创建
Video
小部件- 传递你已经有的
VideoController
。
- 传递你已经有的
代码更容易理解:
class _MyScreenState extends State<MyScreen> {
late final Player player = Player();
late final VideoController controller = VideoController(player);
@override
void dispose() {
player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Video(
controller: controller,
),
);
}
}
视频播放使用硬件加速,即默认使用 GPU。
可以使用 configuration
参数在构造函数中提供附加选项。在一般情况下,你永远不会需要这个。
final VideoController player = VideoController(
player,
configuration: const VideoControllerConfiguration(
// 提供你的选项:
enableHardwareAcceleration: true, // 默认值:true
width: 640, // 默认值:null
height: 480, // 默认值:null
// 注释是最好的了解这些选项的地方:
// https://github.com/media-kit/media-kit/blob/main/media_kit_video/lib/src/video_controller/video_controller.dart
),
);
截图
screenshot
方法获取当前视频帧的快照并返回编码图像字节作为 Uint8List
。
final Uint8List? screenshot = await player.screenshot();
此外,可以指定 format
参数以更改编码格式。支持以下格式:
image/jpeg
: 返回 JPEG 编码的图像。image/png
: 返回 PNG 编码的图像。null
: 返回 BGRA 像素缓冲区。
自定义字幕
可以将 SubtitleViewConfiguration
传递给 Video
小部件以自定义字幕。代码更容易理解:
- 可以提供
TextStyle
、TextAlign
和EdgeInsetsGeometry
。
Video(
controller: controller,
subtitleViewConfiguration: const SubtitleViewConfiguration(
style: TextStyle(
height: 1.4,
fontSize: 24.0,
letterSpacing: 0.0,
wordSpacing: 0.0,
color: Color(0xffffffff),
fontWeight: FontWeight.normal,
backgroundColor: Color(0xaa000000),
),
textAlign: TextAlign.center,
padding: EdgeInsets.all(24.0),
),
);
加载外部字幕轨道
可以使用 SubtitleTrack.uri
构造函数加载带 URI 的外部字幕轨道(例如 SRT、WebVTT 等)。代码更容易理解:
await player.setSubtitleTrack(
SubtitleTrack.uri(
'https://www.iandevlin.com/html5test/webvtt/upc-video-subtitles-en.vtt',
title: 'English',
language: 'en',
),
);
可以使用 SubtitleTrack.data
构造函数加载带数据的外部字幕轨道(例如 SRT、WebVTT 等)。代码更容易理解:
player.setSubtitleTrack(
SubtitleTrack.data(
'''WEBVTT FILE
1
00:00:03.500 --> 00:00:05.000 D:vertical A:start
Everyone wants the most from life
2
00:00:06.000 --> 00:00:09.000 A:start
Like internet experiences that are rich <b>and</b> entertaining
3
00:00:11.000 --> 00:00:14.000 A:end
Phone conversations where people truly <c.highlight>connect</c>
4
00:00:14.500 --> 00:00:18.000
Your favourite TV programmes ready to watch at the touch of a button
5
00:00:19.000 --> 00:00:24.000
Which is why we are bringing TV, internet and phone together in <c.highlight>one</c> super package
6
00:00:24.500 --> 00:00:26.000
<c.highlight>One</c> simple way to get everything
7
00:00:26.500 --> 00:00:27.500 L:12%
UPC
8
00:00:28.000 --> 00:00:30.000 L:75%
Simply for <u>everyone</u>
''',
title: 'English',
language: 'en',
),
);
加载外部音频轨道
可以使用 AudioTrack.uri
构造函数加载带 URI 的外部音频轨道。代码更容易理解:
await player.setAudioTrack(
AudioTrack.uri(
'https://www.iandevlin.com/html5test/webvtt/v/upc-tobymanley.mp4',
title: 'English',
language: 'en',
),
);
视频控件
package:media_kit_fork
提供了高度可定制的预构建视频控件。
除了主题外,布局可以自定义,按钮的位置可以修改,还可以创建自定义按钮。默认情况下还支持必要功能,如全屏、键盘快捷键和基于滑动的控件。
控件 | 图片 |
---|---|
<tt>MaterialDesktopVideoControls</tt> |
|
<tt>MaterialVideoControls</tt> |
Video
小部件提供controls
参数以显示并自定义视频控件。- 默认情况下,使用
<a href="#adaptivevideocontrols"><code>AdaptiveVideoControls</code></a>
。
类型
类型 | 描述 |
---|---|
<a href="#adaptivevideocontrols"><code>AdaptiveVideoControls</code></a> |
根据平台选择 <a href="#materialvideocontrols"><code>MaterialVideoControls</code></a> 、<a href="#cupertinovideocontrols"><code>CupertinoVideoControls</code></a> 等。 |
<a href="#materialvideocontrols"><code>MaterialVideoControls</code></a> |
<a href="https://material.io/" rel="ugc">Material Design</a> 视频控件。 |
<a href="#materialdesktopvideocontrols"><code>MaterialDesktopVideoControls</code></a> |
<a href="https://material.io/" rel="ugc">Material Design</a> 视频控件适用于桌面。 |
<a href="#cupertinovideocontrols"><code>CupertinoVideoControls</code></a> |
<a href="https://developer.apple.com/design/human-interface-guidelines/designing-for-ios" rel="ugc">iOS-style</a> 视频控件。 |
<a href="#novideocontrols"><code>NoVideoControls</code></a> |
禁用视频控件(即仅渲染视频输出)。 |
自定义 | 提供自定义 <code>builder</code> 用于视频控件。 |
选择现有视频控件
修改 controls
参数。有关高级主题化现有视频控件的信息,请参阅“主题化和修改视频控件”部分。
Scaffold(
body: Video(
controller: controller,
// 选择 `[MaterialVideoControls]`。
controls: MaterialVideoControls,
),
);
Scaffold(
body: Video(
controller: controller,
// 选择 `[CupertinoVideoControls]`。
controls: CupertinoVideoControls,
),
);
构建自定义视频控件
将自定义构建器 <code>Widget Function(BuildContext, VideoController)</code>
作为 controls
参数传递。
Scaffold(
body: Video(
controller: controller,
// 提供自定义构建器用于控件。
controls: (state) {
return Center(
child: IconButton(
onPressed: () {
state.widget.controller.player.playOrPause();
},
icon: StreamBuilder(
stream: state.widget.controller.player.stream.playing,
builder: (context, playing) => Icon(
playing.data == true ? Icons.pause : Icons.play_arrow,
),
),
// 不一定需要使用 `[StreamBuilder]` 或使用 `[Player]` 和 `[VideoController]` 从 `[state]`。
// `[StreamSubscription]` 可以在该小部件的 `[initState]` 中制作。
),
);
},
),
);
使用和修改视频控件
<code>AdaptiveVideoControls</code>
- 根据平台选择
<a href="#materialvideocontrols"><code>MaterialVideoControls</code></a>
、<a href="#cupertinovideocontrols"><code>CupertinoVideoControls</code></a>
等。 - 主题化:
- 根据以下部分的主题化特定控件。
<code>MaterialVideoControls</code>
<a href="https://material.io/" rel="ugc">Material Design</a>
视频控件。- 主题化:
- 使用
<code>MaterialVideoControlsTheme</code>
小部件。 <code>Video</code>
小部件(在<code>child</code>
树中)将遵循指定的主题:
- 使用
// 将 `[Video]` 小部件包装在 `[MaterialVideoControlsTheme]` 中。
MaterialVideoControlsTheme(
normal: MaterialVideoControlsThemeData(
// 修改主题选项:
buttonBarButtonSize: 24.0,
buttonBarButtonColor: Colors.white,
// 修改顶部按钮栏:
topButtonBar: [
const Spacer(),
MaterialDesktopCustomButton(
onPressed: () {
debugPrint('Custom "Settings" button pressed.');
},
icon: const Icon(Icons.settings),
),
],
),
fullscreen: const MaterialVideoControlsThemeData(
// 修改主题选项:
displaySeekBar: false,
automaticallyImplySkipNextButton: false,
automaticallyImplySkipPreviousButton: false,
),
child: Scaffold(
body: Video(
controller: controller,
),
),
);
- 相关小部件(可在
<code>primaryButtonBar</code>
、<code>topButtonBar</code>
和<code>bottomButtonBar</code>
中使用):<code>MaterialPlayOrPauseButton</code>
<code>MaterialSkipNextButton</code>
<code>MaterialSkipPreviousButton</code>
<code>MaterialFullscreenButton</code>
<code>MaterialCustomButton</code>
<code>MaterialPositionIndicator</code>
<code>MaterialDesktopVideoControls</code>
<a href="https://material.io/" rel="ugc">Material Design</a>
视频控件适用于桌面。- 主题化:
- 使用
<code>MaterialDesktopVideoControlsTheme</code>
小部件。 <code>Video</code>
小部件(在<code>child</code>
树中)将遵循指定的主题:
- 使用
// 将 `[Video]` 小部件包装在 `[MaterialDesktopVideoControlsTheme]` 中。
MaterialDesktopVideoControlsTheme(
normal: MaterialDesktopVideoControlsThemeData(
// 修改主题选项:
seekBarThumbColor: Colors.blue,
seekBarPositionColor: Colors.blue,
toggleFullscreenOnDoublePress: false,
// 修改顶部按钮栏:
topButtonBar: [
const Spacer(),
MaterialDesktopCustomButton(
onPressed: () {
debugPrint('Custom "Settings" button pressed.');
},
icon: const Icon(Icons.settings),
),
],
// 修改底部按钮栏:
bottomButtonBar: const [
Spacer(),
MaterialDesktopPlayOrPauseButton(),
Spacer(),
],
),
fullscreen: const MaterialDesktopVideoControlsThemeData(),
child: Scaffold(
body: Video(
controller: controller,
),
),
);
- 相关小部件(可在
<code>primaryButtonBar</code>
、<code>topButtonBar</code>
和<code>bottomButtonBar</code>
中使用):<code>MaterialDesktopPlayOrPauseButton</code>
<code>MaterialDesktopSkipNextButton</code>
<code>MaterialDesktopSkipPreviousButton</code>
<code>MaterialDesktopFullscreenButton</code>
<code>MaterialDesktopCustomButton</code>
<code>MaterialDesktopVolumeButton</code>
<code>MaterialDesktopPositionIndicator</code>
- 可以使用
<code>keyboardShortcuts</code>
参数修改键盘快捷键。默认的如下:
快捷键 | 动作 |
---|---|
媒体播放按钮 | 播放 |
媒体暂停按钮 | 暂停 |
媒体播放/暂停按钮 | 播放/暂停 |
媒体下一曲按钮 | 下一首 |
媒体上一曲按钮 | 上一首 |
空格键 | 播放/暂停 |
J | 后退 10秒 |
I | 前进 10秒 |
左箭头键 | 后退 2秒 |
右箭头键 | 前进 2秒 |
上箭头键 | 音量增加 5% |
下箭头键 | 音量减少 5% |
F | 进入/退出全屏 |
Esc | 退出全屏 |
<code>CupertinoVideoControls</code>
<a href="https://developer.apple.com/design/human-interface-guidelines/designing-for-ios" rel="ugc">iOS-style</a>
视频控件。- 主题化:
- 使用
<code>CupertinoVideoControlsTheme</code>
小部件。 <code>Video</code>
小部件(在<code>child</code>
树中)将遵循指定的主题:
- 使用
// 将 `[Video]` 小部件包装在 `[CupertinoVideoControlsTheme]` 中。
CupertinoVideoControlsTheme(
normal: const CupertinoVideoControlsThemeData(
// W.I.P.
),
fullscreen: const CupertinoVideoControlsThemeData(
// W.I.P.
),
child: Scaffold(
body: Video(
controller: controller,
),
),
);
更多关于Flutter多媒体处理插件media_kit_fork的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter多媒体处理插件media_kit_fork的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于media_kit_fork
这个Flutter插件的使用,以下是一个基本的代码案例,展示了如何在Flutter项目中集成和使用该插件进行多媒体处理。请注意,由于media_kit_fork
可能是一个社区维护的分支或特定版本,确保你的pubspec.yaml
文件中正确引用了该插件。
1. 在pubspec.yaml
中添加依赖
首先,你需要在pubspec.yaml
文件中添加media_kit_fork
依赖。请注意,这里假设插件名称确实为media_kit_fork
,如果实际名称不同,请相应调整。
dependencies:
flutter:
sdk: flutter
media_kit_fork: ^x.y.z # 替换为实际的版本号
然后运行flutter pub get
来安装依赖。
2. 导入插件并使用其功能
以下是一个简单的示例,展示了如何使用media_kit_fork
插件来处理音频或视频文件。由于media_kit_fork
的具体API和功能可能因版本而异,这里提供一个假设性的使用案例,具体API调用需参考插件的官方文档。
import 'package:flutter/material.dart';
import 'package:media_kit_fork/media_kit_fork.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _result = '';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Media Kit Fork Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Result: $_result'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _processMedia,
child: Text('Process Media'),
),
],
),
),
),
);
}
Future<void> _processMedia() async {
// 假设有一个本地音频或视频文件路径
String mediaPath = 'path/to/your/media/file.mp4';
try {
// 初始化MediaKitFork
final MediaKitFork mediaKit = MediaKitFork();
// 假设这里有一个方法用于处理媒体文件,如获取媒体信息
MediaInfo info = await mediaKit.getMediaInfo(mediaPath);
// 根据获取的媒体信息更新UI
setState(() {
_result = 'Duration: ${info.duration.inSeconds}s, Width: ${info.width}, Height: ${info.height}';
});
// 其他可能的操作,如转码、剪辑等,这里仅作为示例
// String transcodedPath = await mediaKit.transcode(mediaPath, outputPath: 'path/to/output/file.mp4');
// ...
} catch (e) {
// 处理错误
setState(() {
_result = 'Error: $e';
});
}
}
}
// 假设的MediaInfo类,实际使用时需根据插件文档调整
class MediaInfo {
final Duration duration;
final int width;
final int height;
MediaInfo({required this.duration, required this.width, required this.height});
}
注意事项
- 插件版本与API:上述代码是基于假设的API调用,实际使用时请查阅
media_kit_fork
的官方文档以获取正确的API调用方法和参数。 - 权限处理:处理本地媒体文件可能需要额外的权限,确保在Android和iOS平台上正确配置权限。
- 错误处理:在真实应用中,应添加更详细的错误处理逻辑,以提高应用的健壮性。
希望这个示例能帮助你开始使用media_kit_fork
插件进行多媒体处理。如果有任何进一步的问题或需要更具体的帮助,请查阅插件的官方文档或寻求社区支持。