Flutter视频滤镜处理插件flutter_gpu_video_filters的使用
Flutter视频滤镜处理插件flutter_gpu_video_filters的使用
介绍
flutter_gpu_video_filters
是一个用于在 Flutter 应用中应用 OpenGL 滤镜到视频的插件。它支持多种滤镜效果,并且可以轻松地将这些效果应用于视频文件或实时视频流。
使用方法
如何生成和使用多个滤镜
详细说明请参阅 如何生成和使用多个滤镜。
如何添加自定义滤镜
详细说明请参阅 如何添加自定义滤镜。
导出和保存视频
以下是一个示例代码,展示了如何导出并保存带有滤镜效果的视频:
import 'package:flutter_gpu_video_filters/flutter_gpu_video_filters.dart';
Future<void> exportVideo() async {
final inputSource = AssetInputSource('demo.mp4');
final output = File('result.mp4');
final configuration = GPUGrayScaleConfiguration();
final processStream = configuration.exportVideoFile(VideoExportConfig(inputSource, output));
await for (final progress in processStream) {
debugPrint('Exporting file ${(progress * 100).toInt()}%');
}
}
GPUVideoNativePreview 示例
以下是一个示例代码,展示了如何在 Flutter 应用中预览带有滤镜效果的视频:
import 'package:flutter_gpu_video_filters/flutter_gpu_video_filters.dart';
import 'package:flutter/material.dart';
class PreviewPage extends StatefulWidget {
const PreviewPage({Key? key}) : super(key: key);
@override
State<PreviewPage> createState() => _PreviewPageState();
}
class _PreviewPageState extends State<PreviewPage> {
late GPUVideoPreviewController configuration;
late final GPUGrayScaleConfiguration controller;
late final GPUVideoPreviewParams previewParams;
bool paramsReady = false;
static const _assetPath = 'videos/demo.mp4';
@override
void initState() {
super.initState();
_prepare().whenComplete(() {
setState(() {});
});
}
Future<void> _prepare() async {
configuration = GPUGrayScaleConfiguration();
previewParams = await GPUVideoPreviewParams.create(configuration);
paramsReady = true;
}
@override
void dispose() {
controller.dispose();
configuration.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return paramsReady
? GPUVideoNativePreview(
params: previewParams,
configuration: configuration,
onViewCreated: (controller, outputSizeStream) async {
this.controller = controller;
await this.controller.setVideoAsset(_assetPath);
await for (final size in outputSizeStream) {
setState(() {});
}
},
)
: const Offstage();
}
}
额外信息
GPUImage for Android 的支持状态
以下表格列出了 GPUImage for Android
中各种滤镜的支持状态:
状态 | 名称 | 显示名称 |
---|---|---|
✅ | GPU3x3ConvolutionConfiguration | 3x3 Convolution |
✅ | GPUAddBlendConfiguration | Add Blend |
✅ | GPUAlphaBlendConfiguration | Alpha Blend |
❌ | GPUBilateralConfiguration | Bilateral |
❌ | GPUBoxBlurConfiguration | Box Blur |
✅ | GPUBrightnessConfiguration | Brightness |
✅ | GPUBulgeDistortionConfiguration | Bulge Distortion Configuration |
✅ | GPUCGAColorspaceConfiguration | CGA Colorspace |
✅ | GPUChromaKeyBlendConfiguration | Chroma Key Blend |
✅ | GPUColorBalanceConfiguration | Color Balance |
✅ | GPUColorBlendConfiguration | Color Blend |
✅ | GPUColorBurnBlendConfiguration | Color Burn Blend |
✅ | GPUColorDodgeBlendConfiguration | Color Dodge Blend |
✅ | GPUColorInvertConfiguration | Color Invert |
✅ | GPUColorMatrixConfiguration | Color Matrix |
✅ | GPUContrastConfiguration | Contrast |
✅ | GPUCrosshatchConfiguration | Crosshatch |
✅ | GPUDarkenBlendConfiguration | Darken Blend |
✅ | GPUDifferenceBlendConfiguration | Difference Blend |
✅ | GPUDirectionalSobelEdgeDetectionConfiguration | Directional Sobel Edge Detection |
✅ | GPUDissolveBlendConfiguration | Dissolve Blend |
✅ | GPUDivideBlendConfiguration | Divide Blend |
✅ | GPUEmbossConfiguration | Emboss |
✅ | GPUExposureConfiguration | Exposure |
✅ | GPUFalseColorConfiguration | False Color |
✅ | GPUGammaConfiguration | Gamma |
❌ | GPUGaussianBlurConfiguration | Gaussian Blur |
✅ | GPUGlassSphereConfiguration | Glass Sphere |
✅ | GPUGrayScaleConfiguration | Gray Scale |
✅ | GPUHALDLookupTableConfiguration | HALD Lookup Table |
✅ | GPUHalftoneConfiguration | Halftone |
✅ | GPUHardLightBlendConfiguration | Hard Light Blend |
✅ | GPUHazeConfiguration | Haze |
✅ | GPUHighlightShadowConfiguration | Highlight Shadow |
✅ | GPUHueBlendConfiguration | Hue Blend |
✅ | GPUHueConfiguration | Hue |
✅ | GPUInvertConfiguration | Invert |
✅ | GPUKuwaharaConfiguration | Kuwahara |
✅ | GPULaplacianConfiguration | Laplacian |
✅ | GPULevelsConfiguration | Levels |
✅ | GPULightenBlendConfiguration | Lighten Blend |
✅ | GPULinearBurnBlendConfiguration | Linear Burn Blend |
✅ | GPULuminanceThresholdConfiguration | Luminance Threshold |
✅ | GPULuminanceConfiguration | Luminance |
✅ | GPULuminosityBlendConfiguration | Luminosity Blend |
✅ | GPUMonochromeConfiguration | Monochrome |
✅ | GPUMultiplyBlendConfiguration | Multiply Blend |
✅ | GPUNonMaximumSuppressionConfiguration | Non Maximum Suppression |
✅ | GPUNormalBlendConfiguration | Normal Blend |
‽ | GPUOpacityConfiguration | Opacity |
✅ | GPUOverlayBlendConfiguration | Overlay Blend |
✅ | GPUOverlayConfiguration | Overlay |
✅ | GPUPixelationConfiguration | Pixelation |
✅ | GPUPosterizeConfiguration | Posterize |
✅ | GPURGBConfiguration | RGB |
✅ | GPUSaturationBlendConfiguration | Saturation Blend |
✅ | GPUSaturationConfiguration | Saturation |
✅ | GPUScreenBlendConfiguration | Screen Blend |
✅ | GPUSepiaToneConfiguration | Sepia Tone |
✅ | GPUSepiaConfiguration | Sepia |
✅ | GPUSharpenConfiguration | Sharpen |
✅ | GPUSobelThresholdConfiguration | Sobel Threshold |
✅ | GPUSoftLightBlendConfiguration | Soft Light Blend |
✅ | GPUSolarizeConfiguration | Solarize |
✅ | GPUSourceOverBlendConfiguration | Source Over Blend |
✅ | GPUSphereRefractionConfiguration | Sphere Refraction |
✅ | GPUSquareLookupTableConfiguration | Square Lookup Table |
✅ | GPUSubtractBlendConfiguration | Subtract Blend |
✅ | GPUSwirlConfiguration | Swirl |
✅ | GPUToneCurveConfiguration | Tone Curve |
✅ | GPUToonConfiguration | Toon |
✅ | GPUVibranceConfiguration | Vibrance |
✅ | GPUVignetteConfiguration | Vignette |
✅ | GPUWatermarkConfiguration | Watermark |
✅ | GPUWeakPixelInclusionConfiguration | Weak Pixel Inclusion |
✅ | GPUWhiteBalanceConfiguration | WhiteBalance |
✅ | GPUZoomBlurConfiguration | Zoom Blur |
示例
- 大 Flutter 滤镜演示 - 一个展示如何使用滤镜的大示例。
维护者
完整示例代码
以下是 example/lib/main.dart
文件的完整示例代码:
import 'dart:io' show File;
import 'package:gallery_saver/gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/material.dart' hide Rect;
import 'package:flutter_gpu_video_filters/flutter_gpu_video_filters.dart';
import 'package:flutter_gpu_filters_interface/flutter_gpu_filters_interface.dart';
import 'approved_filters.dart';
import 'filters.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Filters Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const ListPage(),
);
}
}
class ListPage extends StatelessWidget {
const ListPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Filters'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: CustomScrollView(
slivers: [
SliverFixedExtentList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final item = kFailedFilters[index];
return Card(
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return FilterPage2(
configuration: item.configuration,
);
},
),
);
},
title: Text(item.name),
trailing: Icon(
Icons.arrow_forward,
color: Theme.of(context).colorScheme.error,
),
),
);
},
childCount: kFailedFilters.length,
),
itemExtent: 64,
),
SliverFixedExtentList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final item = kFilters[index];
return Card(
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return FilterPage2(
configuration: item.configuration,
);
},
),
);
},
title: Text(item.name),
trailing: Icon(
Icons.arrow_forward,
color: Theme.of(context).primaryColor,
),
),
);
},
childCount: kFilters.length,
),
itemExtent: 64,
),
],
),
),
);
}
}
class FilterPage extends StatefulWidget {
final GPUFilterConfiguration configuration;
const FilterPage({super.key, required this.configuration});
@override
State<FilterPage> createState() => _FilterPageState();
}
class _FilterPageState extends State<FilterPage> {
late final VideoPreviewController controller;
late final GPUVideoPreviewParams previewParams;
bool previewParamsReady = false;
static const _videoAsset = 'videos/demo.mp4';
@override
void initState() {
super.initState();
_prepare().whenComplete(() => setState(() {}));
}
@override
void dispose() {
controller.dispose();
widget.configuration.dispose();
super.dispose();
}
Future<void> _prepare() async {
await widget.configuration.prepare();
previewParams = await GPUVideoPreviewParams.create(widget.configuration);
previewParamsReady = true;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Preview'),
),
floatingActionButton: FloatingActionButton(
heroTag: null,
onPressed: () {
_exportVideo().catchError((e) => ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(e.toString()))));
},
tooltip: 'Export video',
child: const Icon(Icons.save),
),
body: Stack(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: previewParamsReady
? GPUVideoSurfacePreview(
configuration: widget.configuration,
onViewCreated: (controller, outputSizeStream) async {
this.controller = controller;
await controller
.setVideoSource(AssetInputSource(_videoAsset));
await widget.configuration.update();
await for (final _ in outputSizeStream) {
setState(() {});
}
},
)
: const Center(
child: CircularProgressIndicator(),
),
),
),
Row(
children: [
TextButton(
onPressed: () {
controller.pause();
},
child: const Text('Pause')),
TextButton(
onPressed: () {
controller.play();
},
child: const Text('Play')),
],
)
],
),
);
}
File? latestFile;
Future<void> _exportVideo() async {
const asset = _videoAsset;
final root = await getTemporaryDirectory();
final output = File(
'${root.path}/${DateTime.now().millisecondsSinceEpoch}.${asset.split('.').last}',
);
final watch = Stopwatch();
watch.start();
final processStream = widget.configuration.exportVideoFile(
VideoExportConfig(
latestFile == null
? AssetInputSource(asset)
: FileInputSource(latestFile!),
output,
),
);
await for (final progress in processStream) {
debugPrint('_exportVideo: Exporting file ${(progress * 100).toInt()}%');
}
debugPrint(
'_exportVideo: Exporting file took ${watch.elapsedMilliseconds} milliseconds');
await GallerySaver.saveVideo(output.absolute.path);
latestFile = output;
debugPrint('_exportVideo: Exported: ${output.absolute}');
}
}
class FilterPage2 extends StatefulWidget {
final GPUFilterConfiguration configuration;
const FilterPage2({super.key, required this.configuration});
@override
State<FilterPage2> createState() => _FilterPageState2();
}
class _FilterPageState2 extends State<FilterPage2> {
late final VideoPreviewController controller;
bool previewParamsReady = false;
static const _videoAsset = 'videos/demo.mp4';
@override
void initState() {
super.initState();
_prepare().whenComplete(() => setState(() {}));
}
@override
void dispose() {
controller.dispose();
widget.configuration.dispose();
super.dispose();
}
Future<void> _prepare() async {
await widget.configuration.prepare();
controller = await GPUVideoPreviewController.initialize();
await controller.connect(widget.configuration);
await controller.setVideoSource(AssetInputSource(_videoAsset));
previewParamsReady = true;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Preview'),
),
floatingActionButton: FloatingActionButton(
heroTag: null,
onPressed: () {
_exportVideo().catchError((e) => ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(e.toString()))));
},
tooltip: 'Export video',
child: const Icon(Icons.save),
),
body: Stack(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: previewParamsReady
? VideoPreview(
controller: controller,
)
: const Center(
child: CircularProgressIndicator(),
),
),
),
Row(
children: [
TextButton(
onPressed: () {
controller.pause();
},
child: const Text('Pause')),
TextButton(
onPressed: () {
controller.play();
},
child: const Text('Play')),
],
)
],
),
);
}
File? latestFile;
Future<void> _exportVideo() async {
const asset = _videoAsset;
final root = await getTemporaryDirectory();
final output = File(
'${root.path}/${DateTime.now().millisecondsSinceEpoch}.${asset.split('.').last}',
);
final watch = Stopwatch();
watch.start();
final processStream = widget.configuration.exportVideoFile(
VideoExportConfig(
latestFile == null
? AssetInputSource(asset)
: FileInputSource(latestFile!),
output,
),
);
await for (final progress in processStream) {
debugPrint('_exportVideo: Exporting file ${(progress * 100).toInt()}%');
}
debugPrint(
'_exportVideo: Exporting file took ${watch.elapsedMilliseconds} milliseconds');
await GallerySaver.saveVideo(output.absolute.path);
latestFile = output;
debugPrint('_exportVideo: Exported: ${output.absolute}');
}
}
希望这些内容对你有所帮助!如果有任何问题或需要进一步的帮助,请随时提问。
更多关于Flutter视频滤镜处理插件flutter_gpu_video_filters的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter视频滤镜处理插件flutter_gpu_video_filters的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 flutter_gpu_video_filters
插件来处理视频滤镜的示例代码。这个插件允许你在 Flutter 应用中应用 GPU 加速的视频滤镜。
首先,确保你已经在 pubspec.yaml
文件中添加了 flutter_gpu_video_filters
依赖:
dependencies:
flutter:
sdk: flutter
flutter_gpu_video_filters: ^0.10.0 # 请检查最新版本号
然后运行 flutter pub get
来获取依赖。
以下是一个简单的 Flutter 应用示例,它展示了如何使用 flutter_gpu_video_filters
插件来应用视频滤镜:
import 'package:flutter/material.dart';
import 'package:flutter_gpu_video_filters/flutter_gpu_video_filters.dart';
import 'package:video_player/video_player.dart';
import 'dart:typed_data';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: VideoFilterPage(),
);
}
}
class VideoFilterPage extends StatefulWidget {
@override
_VideoFilterPageState createState() => _VideoFilterPageState();
}
class _VideoFilterPageState extends State<VideoFilterPage> {
VideoPlayerController _controller;
TextureVideoFilter _filter;
@override
void initState() {
super.initState();
// 初始化视频控制器
_controller = VideoPlayerController.network(
'https://www.example.com/your-video-url.mp4',
)..initialize().then((_) {
// 初始化完成后开始播放视频
setState(() {});
_controller.play();
// 初始化视频滤镜
_filter = TextureVideoFilter(
size: Size(_controller.value.size.width.toDouble(), _controller.value.size.height.toDouble()),
filter: VideoFilter.sepia, // 使用棕褐色滤镜作为示例
)..initialize().then((_) {
// 将视频帧传递给滤镜处理
_controller.addListener(() {
if (_controller.value.isPlaying && _controller.value.hasInitialized && _controller.value.isBuffered) {
_filter.setTextureId(_controller.textureId);
}
});
});
});
}
@override
void dispose() {
_controller.dispose();
_filter.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Video Filter Example'),
),
body: Center(
child: _controller.value.isInitialized
? Container(
width: _controller.value.size.width,
height: _controller.value.size.height,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
// 显示原始视频帧
SizedBox(
width: _controller.value.size.width,
height: _controller.value.size.height,
child: VideoPlayer(_controller),
),
// 显示经过滤镜处理的视频帧
if (_filter.isInitialized)
Texture(
id: _filter.textureId,
),
],
),
)
: CircularProgressIndicator(),
),
);
}
}
说明
- 依赖管理:在
pubspec.yaml
文件中添加flutter_gpu_video_filters
和video_player
依赖。 - 视频控制器:使用
VideoPlayerController
来加载和控制视频。 - 视频滤镜:使用
TextureVideoFilter
来应用滤镜。这里以棕褐色滤镜(VideoFilter.sepia
)为例。 - 视频显示:使用
VideoPlayer
小部件显示原始视频帧,同时使用Texture
小部件显示经过滤镜处理的视频帧。
注意事项
- 确保视频 URL 是有效的,并且服务器允许跨域访问。
- 在实际开发中,你可能需要根据具体需求调整滤镜类型和参数。
flutter_gpu_video_filters
插件可能会随着 Flutter 生态的发展而更新,因此请参考最新的官方文档和示例代码。
希望这个示例代码能帮助你快速上手 flutter_gpu_video_filters
插件的使用!