Flutter 视频编辑器
一个允许编辑(修剪、裁剪、旋转和缩放)视频并选择封面的视频编辑器,具有非常灵活的UI设计。
该库提供了一些工具来执行导出,但不处理导出过程。
这个库完全用Dart编写,但使用了外部包如video_thumbnail,这使得它目前只在iOS和Android平台上可用(网页支持正在进行中)。
注意 如果你使用的版本在1.2.3到2.4.0之间,你的项目可能受GPL许可证约束。
Android | iOS | |
---|---|---|
支持 | SDK 16+ | 11.0+ |
📖 安装
以下步骤将帮助你将此库作为依赖项添加到你的Flutter项目中。
- 运行
flutter pub add video_editor
,或手动将video_editor添加到pubspec.yaml
文件中。
dependencies:
video_editor: ^2.4.0
- 在代码中导入包:
import 'package:video_editor/video_editor.dart';
📸 截图
在iPhone 11 Pro上运行的示例应用 | 自定义示例,浅色模式 |
---|---|
👀 使用方法
final VideoEditorController _controller = VideoEditorController.file(
File('/path/to/video.mp4'),
minDuration: const Duration(seconds: 1),
maxDuration: const Duration(seconds: 10),
);
@override
void initState() {
super.initState();
_controller.initialize().then((_) => setState(() {}));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
/// 基本导出视频功能
Future<void> exportVideo() async {
final config = VideoFFmpegVideoEditorConfig(_controller);
// 返回生成的命令和输出路径
final FFmpegVideoEditorExecute execute = await config.getExecuteConfig();
// ... 自行处理视频导出,使用ffmpeg_kit_flutter、你自己的视频服务器等...
}
/// 将视频导出为GIF图像
Future<void> exportGif() async {
final gifConfig = VideoFFmpegVideoEditorConfig(
_controller,
format: VideoExportFormat.gif,
);
// 返回生成的命令和输出路径
final FFmpegVideoEditorExecute gifExecute = await gifConfig.getExecuteConfig();
// ...
}
/// 导出视频,使用自定义命令(超快预设 + 水平翻转)
Future<void> exportMirroredVideo() async {
final mirrorConfig = VideoFFmpegVideoEditorConfig(
_controller,
name: 'mirror-video'
commandBuilder: (VideoFFmpegVideoEditorConfig config, String videoPath, String outputPath) {
final List<String> filters = config.getExportFilters();
filters.add('hflip'); // 添加水平翻转
return '-i $videoPath ${config.filtersCmd(filters)} -preset ultrafast $outputPath';
},
);
// 返回生成的命令和输出路径
final FFmpegVideoEditorExecute mirrorExecute = await mirrorConfig.getExecuteConfig();
// ...
}
更多详情请查看示例。
VideoEditorController
函数 | 描述 |
---|---|
initialize(double? aspectRatio) | 初始化controller 参数、视频、修剪和封面,调用cropAspectRatio |
rotate90Degrees(RotateDirection) | 按提供的方向将视频旋转90度 |
setPreferredRatioFromCrop | 将宽高比更新为当前裁剪区域比例 |
cropAspectRatio(double?) | 更新宽高比 + 将裁剪区域更新到视频尺寸的中心 |
updateCrop(Offset, Offset) | 更新控制器的裁剪最小值和最大值 |
applyCacheCrop | 使用缓存值更新控制器的裁剪最小值和最大值 |
updateTrim(double, double) | 更新控制器的修剪最小值和最大值 |
获取器 | 描述 |
-------------------------------- | --------------------------------- |
Duration startTrim | 裁剪区域的起始值 |
Duration endTrim | 裁剪区域的结束值 |
Duration trimmedDuration | 所选裁剪区域的持续时间 |
bool isTrimmed | 当裁剪值不是默认视频时长时设为true |
bool isTrimming | 当startTrim或endTrim正在变化时设为true |
Duration maxDuration | 裁剪区域可能的最大持续时间 |
Duration minDuration | 裁剪区域可能的最小持续时间 |
Offset minCrop | 裁剪区域的左上角位置(介于0.0 和1.0 之间) |
Offset maxCrop | 裁剪区域的右下角位置(介于0.0 和1.0 之间) |
Size croppedArea | 裁剪区域的实际大小 |
double? preferredCropAspectRatio | 选定的首选裁剪宽高比 |
bool isRotated | 当旋转角度不为0 时设为true |
int rotation | 设置的旋转角度0 、90 、180 和270 |
int cacheRotation | 编辑器中应用的所有旋转角度之和 |
CoverData? selectedCoverVal | 用于导出最终封面的选定封面缩略图 |
int coverThumbnailsQuality = 10 | coverThumbnailsQuality 参数指定生成的封面缩略图质量,范围从0到100(更多信息) |
int trimThumbnailsQuality = 10 | trimThumbnailsQuality 参数指定生成的裁剪滑块缩略图质量,范围从0到100(更多信息) |
小部件
点击展开小部件文档
裁剪
1. CropGridViewer
此小部件用于在视频上启用裁剪操作(CropGridViewer.edit),或仅预览裁剪结果(CropGridViewer.preview)。
参数 | 描述 |
---|---|
required VideoEditorController controller | controller 参数是必需的,以便控制器设置的每个更改都会在裁剪视图中传播 |
EdgeInsets margin | 用于缩进裁剪视图的空间量,在预览模式下不使用 |
bool rotateCropArea | 当裁剪视图旋转时保持preferredCropAspectRatio |
修剪器
1. TrimSlider
显示包含视频缩略图的修剪器,具有旋转和裁剪参数。
参数 | 描述 |
---|---|
required VideoEditorController controller | controller 参数是必需的,以便控制器设置的每个更改都会在修剪滑块视图中传播 |
double height = 0.0 | height 参数指定生成的缩略图的高度 |
double horizontalMargin = 0.0 | horizontalMargin 参数指定滑块周围的水平空间。当修剪可以拖动时(controller.maxDuration < controller.videoDuration )很重要 |
Widget? child | child 参数可以指定在此小部件下方显示的小部件(例如:TrimTimeline) |
bool hasHaptic = true | hasHaptic 参数指定当修剪触及边缘(左或右)时是否可以触发触觉反馈 |
double maxViewportRatioo = 2.5 | maxViewportRatio 参数指定视图比例的上限 |
ScrollController? scrollController | scrollController 参数指定用于修剪滑块视图的滚动控制器 |
2. TrimTimeline
显示视频时间线。
参数 | 描述 |
---|---|
required VideoEditorController controller | controller 参数是必需的,因为根据controller.maxDuration ,生成的时间线会有所不同 |
double quantity = 8 | 时间线中预期显示的元素quantity |
EdgeInsets padding = EdgeInsets.zero | padding 参数指定时间线周围的空间 |
String localSeconds = 's' | 用于表示秒数的字符串,显示在每个时间线元素旁边 |
TextStyle? textStyle | 用于设置时间线文本样式的TextStyle |
封面
1. CoverSelection
显示一些生成的封面,具有旋转和裁剪参数,用于更新所选封面。
参数 | 描述 |
---|---|
required VideoEditorController controller | controller 参数是必需的,以便控制器设置的每个更改都会在封面选择视图中传播 |
double size = 0.0 | size 参数指定生成的缩略图的最大尺寸 |
double horizontalMargin = 0.0 | 当裁剪视图外有边距时,需要指定horizontalMargin 参数,以便在发生更改时可以正确计算新布局 |
int quantity = 5 | quantity 参数指定要生成的缩略图数量 |
Wrap? wrap | 用于自定义缩略图包装器的wrap 小部件 |
Function? selectedCoverBuilder | 返回所选封面应如何显示 |
2. CoverViewer
显示带有旋转和裁剪参数的所选封面。
参数 | 描述 |
---|---|
required VideoEditorController controller | controller 参数是必需的,以便控制器设置的每个更改都会在封面视图中传播裁剪参数 |
String noCoverText = 'No selection' | noCoverText 参数指定当selectedCover为null 时显示的文本 |
样式
点击展开样式文档
1. CropStyle
您可以创建自己的CropStyle类来自定义CropGridViewer的外观。
参数 | 描述 |
---|---|
Color croppingBackground = Colors.black.withOpacity(0.48) | croppingBackground 参数指定裁剪时裁剪区域外的绘制区域颜色 |
Color background = Colors.black | background 参数指定非裁剪时裁剪区域外的绘制区域颜色 |
double gridLineWidth = 1 | gridLineWidth 参数指定裁剪线的宽度 |
Color gridLineColor = Colors.white | gridLineColor 参数指定裁剪线的颜色 |
int gridSize = 3 | gridSize 参数指定裁剪视图中列和行的数量 |
Color boundariesColor = Colors.white | boundariesColor 参数指定裁剪区域角落的颜色 |
Color selectedBoundariesColor = kDefaultSelectedColor | selectedBoundariesColor 参数指定选中的裁剪区域角落的颜色 |
double boundariesLength = 20 | boundariesLength 参数指定裁剪区域角落的长度 |
double boundariesWidth = 5 | boundariesWidth 参数指定裁剪区域角落的宽度 |
2. TrimStyle
你可以创建自己的 TrimStyle 类来自定义 TrimSlider 的外观。
参数 | 描述 |
---|---|
Color background = Colors.black.withOpacity(0.6) | background 参数指定修剪区域外的绘制区域颜色 |
Color positionLineColor = Colors.red | positionLineColor 参数指定显示视频位置的线条颜色 |
double positionLineWidth = 2 | positionLineWidth 参数指定显示视频位置的线条宽度 |
Color lineColor = Colors.white | lineColor 参数指定修剪区域周围边框的颜色 |
Color onTrimmingColor = kDefaultSelectedColor | onTrimmingColor 参数指定修剪过程中修剪区域周围边框的颜色 |
Color onTrimmedColor = kDefaultSelectedColor | onTrimmedColor 参数指定修剪参数不为默认值时修剪区域周围边框的颜色 |
double lineWidth = 2 | lineWidth 参数指定修剪区域周围边框的宽度 |
TrimSliderEdgesType borderRadius = 5 | borderRadius 参数指定修剪器周围的边框半径 |
double edgesType = TrimSliderEdgesType.bar | edgesType 参数指定应用于修剪器边缘(左右)的样式 |
double edgesSize | edgesSize 参数指定图标后面边缘的大小 |
Color iconColor = Colors.black | iconColor 参数指定修剪区域边缘图标的颜色 |
double iconSize = 25 | iconSize 参数指定修剪区域边缘图标的大小 |
IconData? leftIcon = Icons.arrow_left | leftIcon 参数指定修剪区域左边缘显示的图标 |
IconData? rightIcon = Icons.arrow_right | rightIcon 参数指定修剪区域右边缘显示的图标 |
3. CoverStyle
你可以创建自己的 CoverStyle 类来自定义 CoverSelection 的外观。
参数 | 描述 |
---|---|
Color selectedBorderColor = Colors.white | selectedBorderColor 参数指定所选封面缩略图周围边框的颜色 |
double borderWidth = 2 | borderWidth 参数指定每个封面缩略图周围边框的宽度 |
double borderRadius = 5.0 | borderRadius 参数指定每个封面缩略图的边框半径 |
导出
1. FFmpegVideoEditorConfig
参数 | 描述 |
---|---|
String? name | name 参数指定生成文件的文件名 |
String? outputDirectory | outputDirectory 参数指定文件应该生成的位置,默认为临时目录 |
double scale = 1 | scale 参数用于增加或减少生成文件的尺寸 |
bool isFiltersEnabled = true | isFiltersEnabled 参数指定是否应用编辑器参数 |
2. VideoFFmpegVideoEditorConfig
包含所有 FFmpegVideoEditorConfig 参数。
参数 | 描述 |
---|---|
VideoExportFormat format = VideoExportFormat.mp4 | format 参数指定生成视频的扩展名 |
String Function? commandBuilder | commandBuilder 参数可用于生成带有自定义选项的命令 |
3. CoverFFmpegVideoEditorConfig
包含所有 FFmpegVideoEditorConfig 参数。
参数 | 描述 |
---|---|
CoverExportFormat format = CoverExportFormat.jpg | format 参数指定生成封面的扩展名 |
int quality = 100 | quality 参数指定生成缩略图的质量,范围从 0 到 100(更多信息) |
String Function? commandBuilder | commandBuilder 参数可用于生成带有自定义选项的命令 |
💭 常见问题
1. 为什么从这个包中移除了 FFmpeg?
从 3.0.0 版本开始,video_editor 包不再包含 ffmpeg_kit_flutter。
- 在这个包中包含 ffmpeg_kit_flutter 二进制文件导致了许多用户在同一项目中意图使用不同 FFmpeg 实例时遇到的问题(#37、#129、#153)。
- 此外,我注意到 video_editor 包可能从 1.2.3 版本开始就被错误许可,并可能受 GPL v3.0 许可的约束,因为它开始使用 ffmpeg_kit_flutter_min_kit 二进制文件。
- 最后,FFmpeg 包相当大,显著增加了应用程序的大小,这对于希望以不同方式处理导出的开发者来说并不理想。
✨ 致谢
非常感谢 seel-channel,他是这个库的原始创建者。