Flutter视频裁剪插件video_trimmer_pro的使用
Flutter视频裁剪插件video_trimmer_pro的使用
一个用于裁剪视频的Flutter插件
功能 #
- 可自定义的视频裁剪器。
- 支持两种类型的裁剪预览器,固定长度和滚动。
- 视频播放控制。
- 获取并存储视频文件。
此外,还支持转换为GIF。
注意:版本
3.0.0
及以上使用的是 "Full" 版本的 Flutter FFmpeg。要安装 "LTS" 版本,请使用此包的 "x.x.x-LTS" 版本。
下图展示了 TrimViewer
的结构。它包括顶部的 Duration
(显示开始时间、结束时间和滑块时间),由缩略图组成的 TrimArea
,以及允许你从视频中选择部分的 TrimEditor
。
示例 #
在iPhone 13 Pro设备上运行的示例应用:
使用 #
将 video_trimmer
添加到您的 <strong>pubspec.yaml</strong>
文件中:
对于使用FFmpeg主版本:
dependencies:
video_trimmer: ^3.0.0
对于使用FFmpeg LTS版本:
dependencies:
video_trimmer: ^3.0.0-LTS
Android配置 #
无需额外配置即可在Android平台上使用。您可以直接使用!
iOS配置 #
- 将以下键添加到您的
<strong>Info.plist</strong>
文件中,位于<project root>/ios/Runner/Info.plist
:
<key>NSCameraUsageDescription</key>
<string>Used to demonstrate image picker plugin</string>
<key>NSMicrophoneUsageDescription</key>
<string>Used to capture audio for image picker plugin</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Used to demonstrate image picker plugin</string>
FFmpeg发布 #
该插件支持FFmpeg的主版本和 LTS版本。
主发布版 | LTS发布版 | |
---|---|---|
Android API级别 | 24 | 16 |
Android相机访问 | 是 | - |
Android架构 | arm-v7a-neon arm64-v8a x86 x86-64 |
arm-v7a arm-v7a-neon arm64-v8a x86 x86-64 |
iOS最小SDK版本 | 12.1 | 10 |
iOS架构 | arm64 arm64-simulator arm64-mac-catalyst x86-64 x86-64-mac-catalyst |
armv7 arm64 i386 x86-64 |
功能 #
加载输入视频文件 #
final Trimmer _trimmer = Trimmer();
await _trimmer.loadVideo(videoFile: file);
保存裁剪后的视频 #
返回一个字符串以指示保存操作是否成功。
await _trimmer
.saveTrimmedVideo(startValue: _startValue, endValue: _endValue)
.then((value) {
setState(() {
_value = value;
});
});
视频播放状态 #
返回视频播放状态。如果为 true 则视频正在播放,否则已暂停。
await _trimmer.videoPlaybackControl(
startValue: _startValue,
endValue: _endValue,
);
高级命令 #
如果您需要更多定制化功能,可以使用高级的 FFmpeg 命令。只需使用 ffmpegCommand
属性定义您的FFmpeg命令,并使用 customVideoFormat
设置输出视频格式。
请参阅 官方FFmpeg文档 获取更多信息。
注意:向
customVideoFormat
属性传递错误的视频格式可能会导致崩溃。
// 自定义命令示例
// 这个默认用于创建GIF,所以您不需要使用它。
await _trimmer
.saveTrimmedVideo(
startValue: _startValue,
endValue: _endValue,
ffmpegCommand:
'-vf "fps=10,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0',
customVideoFormat: '.gif')
.then((value) {
setState(() {
_value = value;
});
});
小部件 #
显示视频播放区域 #
VideoViewer(trimmer: _trimmer)
显示视频裁剪区域 #
TrimViewer(
trimmer: _trimmer,
viewerHeight: 50.0,
viewerWidth: MediaQuery.of(context).size.width,
maxVideoLength: const Duration(seconds: 10),
onChangeStart: (value) => _startValue = value,
onChangeEnd: (value) => _endValue = value,
onChangePlaybackState: (value) =>
setState(() => _isPlaying = value),
)
示例 #
在将此示例直接应用于Flutter应用之前,请不要忘记将 <code>video_trimmer</code>
和 <code>file_picker</code>
包添加到您的 <code>pubspec.yaml</code>
文件中。
您可以尝试通过替换新创建的Flutter项目的 <code>main.dart</code>
文件的全部内容来运行此示例。
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:video_trimmer/video_trimmer.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Trimmer',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Video Trimmer"),
),
body: Center(
child: Container(
child: ElevatedButton(
child: Text("LOAD VIDEO"),
onPressed: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.video,
allowCompression: false,
);
if (result != null) {
File file = File(result.files.single.path!);
Navigator.of(context).push(
MaterialPageRoute(builder: (context) {
return TrimmerView(file);
}),
);
}
},
),
),
),
);
}
}
class TrimmerView extends StatefulWidget {
final File file;
TrimmerView(this.file);
@override
_TrimmerViewState createState() => _TrimmerViewState();
}
class _TrimmerViewState extends State<TrimmerView> {
final Trimmer _trimmer = Trimmer();
double _startValue = 0.0;
double _endValue = 0.0;
bool _isPlaying = false;
bool _progressVisibility = false;
Future<String?> _saveVideo() async {
setState(() {
_progressVisibility = true;
});
String? _value;
await _trimmer
.saveTrimmedVideo(startValue: _startValue, endValue: _endValue)
.then((value) {
setState(() {
_progressVisibility = false;
_value = value;
});
});
return _value;
}
void _loadVideo() {
_trimmer.loadVideo(videoFile: widget.file);
}
@override
void initState() {
super.initState();
_loadVideo();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Video Trimmer"),
),
body: Builder(
builder: (context) => Center(
child: Container(
padding: EdgeInsets.only(bottom: 30.0),
color: Colors.black,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Visibility(
visible: _progressVisibility,
child: LinearProgressIndicator(
backgroundColor: Colors.red,
),
),
ElevatedButton(
onPressed: _progressVisibility
? null
: () async {
_saveVideo().then((outputPath) {
print('OUTPUT PATH: $outputPath');
final snackBar = SnackBar(
content: Text('Video Saved successfully'));
ScaffoldMessenger.of(context).showSnackBar(
snackBar,
);
});
},
child: Text("SAVE"),
),
Expanded(
child: VideoViewer(trimmer: _trimmer),
),
Center(
child: TrimViewer(
trimmer: _trimmer,
viewerHeight: 50.0,
viewerWidth: MediaQuery.of(context).size.width,
maxVideoLength: const Duration(seconds: 10),
onChangeStart: (value) => _startValue = value,
onChangeEnd: (value) => _endValue = value,
onChangePlaybackState: (value) =>
setState(() => _isPlaying = value),
),
),
TextButton(
child: _isPlaying
? Icon(
Icons.pause,
size: 80.0,
color: Colors.white,
)
: Icon(
Icons.play_arrow,
size: 80.0,
color: Colors.white,
),
onPressed: () async {
bool playbackState = await _trimmer.videoPlaybackControl(
startValue: _startValue,
endValue: _endValue,
);
setState(() {
_isPlaying = playbackState;
});
},
)
],
),
),
),
),
);
}
}
解决LTS版本问题 #
如果在Android平台上运行时出现错误提示 minSdkVersion
需要为 24
,或者在iOS平台上提示Podfile平台版本应为 11
,首先去 <code>pubspec.lock</code>
文件查看 ffmpeg_kit_flutter
是否带有 -LTS
后缀。这应该可以解决iOS平台上的所有问题。
如果在Android上仍然遇到相同的问题,尝试在 <code><project_directory>/android/app/src/main/AndroidManifest.xml</code>
中添加以下内容:
<manifest xmlns:tools="http://schemas.android.com/tools" ....... >
<uses-sdk tools:overrideLibrary="com.arthenica.ffmpegkit.flutter, com.arthenica.ffmpegkit" />
</manifest>
更多关于Flutter视频裁剪插件video_trimmer_pro的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter视频裁剪插件video_trimmer_pro的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用Flutter视频裁剪插件video_trimmer_pro
的代码案例。这个插件允许用户在Flutter应用中裁剪视频。
首先,你需要在pubspec.yaml
文件中添加video_trimmer_pro
依赖:
dependencies:
flutter:
sdk: flutter
video_trimmer_pro: ^0.3.0 # 请检查最新版本号
然后,运行flutter pub get
来安装依赖。
接下来是一个简单的示例代码,展示如何使用video_trimmer_pro
插件来裁剪视频:
import 'package:flutter/material.dart';
import 'package:video_trimmer_pro/video_trimmer_pro.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: VideoTrimmerScreen(),
);
}
}
class VideoTrimmerScreen extends StatefulWidget {
@override
_VideoTrimmerScreenState createState() => _VideoTrimmerScreenState();
}
class _VideoTrimmerScreenState extends State<VideoTrimmerScreen> {
File? _videoFile;
String? _trimmedVideoPath;
@override
void initState() {
super.initState();
_getVideoFile();
}
Future<void> _getVideoFile() async {
// 获取应用文档目录并创建一个示例视频文件路径(这里你需要替换为你的视频文件路径)
final Directory appDocDir = await getApplicationDocumentsDirectory();
String videoFilePath = '${appDocDir.path}/sample_video.mp4';
// 确保视频文件存在(在实际应用中,你可能需要从网络下载或选择用户设备中的视频)
File videoFile = File(videoFilePath);
if (!await videoFile.exists()) {
// 这里你可以添加代码来下载或复制视频文件到该路径
// 例如,从assets复制或者从网络下载
print('Video file does not exist at $videoFilePath');
} else {
setState(() {
_videoFile = videoFile;
});
}
}
Future<void> _trimVideo(VideoTrimmerController controller) async {
final VideoTrimResult result = await controller.trimVideo();
if (result.status == VideoTrimStatus.completed) {
setState(() {
_trimmedVideoPath = result.outputPath;
});
print('Trimmed video saved at ${result.outputPath}');
} else {
print('Video trimming failed: ${result.message}');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Video Trimmer Example'),
),
body: Center(
child: _videoFile == null
? CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () async {
final VideoTrimmerController controller =
VideoTrimmerController(
videoFile: _videoFile!,
startTime: Duration(seconds: 0), // 你可以设置默认开始时间
endTime: Duration(seconds: 30), // 你可以设置默认结束时间
);
final VideoTrimmerPro videoTrimmerPro = VideoTrimmerPro(
controller: controller,
);
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => videoTrimmerPro,
),
);
_trimVideo(controller);
},
child: Text('Trim Video'),
),
if (_trimmedVideoPath != null)
Text(
'Trimmed Video Path: $_trimmedVideoPath',
style: TextStyle(fontSize: 16),
),
],
),
),
);
}
}
在这个示例中,我们做了以下几步:
- 在
pubspec.yaml
中添加video_trimmer_pro
依赖。 - 创建一个Flutter应用,并在主屏幕
VideoTrimmerScreen
中加载视频文件。 - 使用
getApplicationDocumentsDirectory
获取应用的文档目录,并假设视频文件已经存在该目录中(在实际应用中,你可能需要让用户从设备中选择视频或者从网络下载视频)。 - 创建一个按钮,点击按钮后打开视频裁剪界面。
- 在裁剪完成后,获取裁剪后的视频路径并显示。
请注意,在实际应用中,你需要确保视频文件路径正确,并且处理可能的异常和错误情况。