Flutter视频模糊预览插件blurhash_video的使用
Flutter视频模糊预览插件blurhash_video的使用
关于
Blurhash 算法应用于从视频文件中提取的一系列图像。
一个包含7秒视频文件(每秒16帧)的哈希列表大小为6KB(未压缩)!
预览
开始使用
在 pubspec.yaml
文件中添加最新版本的 blurhash_video
插件:
dependencies:
blurhash_video: ^x.x.x
使用方法
示例代码
import 'dart:io';
import 'package:ffmpeg_kit_flutter_full_gpl/ffmpeg_kit.dart';
import 'package:ffmpeg_kit_flutter_full_gpl/return_code.dart';
import 'package:flutter/material.dart';
import 'package:blurhash_video/blurhash_video.dart';
import 'package:file_picker/file_picker.dart';
import 'package:blurhash_dart/blurhash_dart.dart' as dart;
import 'package:image/image.dart';
import 'package:path_provider/path_provider.dart';
import 'package:image_sequence_animator/image_sequence_animator.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(const App());
}
class App extends StatelessWidget {
const App({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: "Blurhash Video Demo",
theme: ThemeData(primarySwatch: Colors.deepOrange),
home: const HomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
[@override](/user/override)
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Directory? _directory;
int _count = 0;
VideoPlayerController? _gblurController;
VideoPlayerController? _sequenceController;
int _hashesSize = 0;
int _gblurSize = 0;
int _sequenceSize = 0;
[@override](/user/override)
void dispose() async {
super.dispose();
_gblurController?.dispose();
_sequenceController?.dispose();
if (_directory?.existsSync() == true) {
await _directory?.delete(recursive: true);
}
}
void _process() async {
// 重置
if (_directory?.existsSync() == true) {
await _directory?.delete(recursive: true);
}
setState(() {
_count = 0;
_directory = null;
});
final temp = await getTemporaryDirectory();
// print(temp.path);
// 清理所有先前生成的缓存目录
// await BlurhashVideo.cleanUp(workingDirectory: temp);
final result = await FilePicker.platform.pickFiles(type: FileType.video);
final path = result?.files.first.path;
if (path == null) return;
final hashes = await BlurhashVideo.generateBlurHashes(
path: path,
workingDirectory: temp,
fps: 24, // 视频帧率默认为24
duration: 7, // 持续时间7秒
resolution: 64, // 像素分辨率
quality: 75, // 质量范围0到100,越大越好
);
// 临时目录用于存储模糊后的图像
final dir = Directory(
"${temp.path}/blurhash_video_demo_${DateTime.now().millisecondsSinceEpoch}");
await dir.create();
// 从每个哈希生成模糊图像
for (var i = 0; i < hashes.length; i++) {
final blurHash = dart.BlurHash.decode(hashes[i]);
final image = blurHash.toImage(64, 36);
await File("${dir.path}/blur${i.toString().padLeft(5, "0")}.png")
.writeAsBytes(encodePng(image));
}
setState(() {
_count = hashes.length;
_directory = dir;
});
// 将哈希保存为txt文件,每行一个哈希
final contents =
hashes.fold<String>("", (content, item) => "$content$item\n");
final hashesFile = File("${dir.path}/hashes.txt");
await hashesFile.writeAsString(contents);
// 文件可以通过bzip压缩,可以减小到原来的三分之一
final hashesSize = await hashesFile.length() ~/ 1024;
setState(() => _hashesSize = hashesSize);
// 使用gaussian模糊滤镜生成mp4视频
final gblurFile = File("${dir.path}/gblur.mp4");
final gblurSession = await FFmpegKit.execute(
"-hide_banner -i $path -s 64x36 -t 7 -vf gblur=sigma=128:steps=4 -lossless 1 -quality 100 -an ${gblurFile.path}");
if (!ReturnCode.isSuccess(await gblurSession.getReturnCode())) {
// print("ffmpeg error gblur: ${await gblurSession.getOutput()}");
_gblurController?.dispose();
_gblurController = null;
} else {
setState(() {
_gblurController = VideoPlayerController.file(gblurFile)
..initialize().then((_) => _gblurController!.play());
});
}
final gblurSize = await gblurFile.length() ~/ 1024;
setState(() => _gblurSize = gblurSize);
// 从模糊的png生成mp4视频
final sequenceFile = File("${dir.path}/blurred.mp4");
final sequenceSession = await FFmpegKit.execute(
"-hide_banner -framerate 24 -i ${dir.path}/blur%05d.png -vf fps=24 -t 7 -pix_fmt yuv420p ${sequenceFile.path}");
if (!ReturnCode.isSuccess(await sequenceSession.getReturnCode())) {
// print("ffmpeg error sequence: ${await sequenceSession.getOutput()}");
_sequenceController?.dispose();
_sequenceController = null;
} else {
setState(() {
_sequenceController = VideoPlayerController.file(sequenceFile)
..initialize().then((_) => _sequenceController!.play());
});
}
final sequenceSize = await sequenceFile.length() ~/ 1024;
setState(() => _sequenceSize = sequenceSize);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Blurhash Video")),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (_directory != null) ...[
// PNG序列
...[
Text("PNG序列: $_hashesSize KB"),
SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width * 0.5625,
child: Transform.scale(
scale: MediaQuery.of(context).size.width / 64,
child: ImageSequenceAnimator(
_directory!.path,
"blur",
0,
5,
"png",
_count.toDouble(),
fps: 24,
isLooping: true,
isBoomerang: false,
isAutoPlay: true,
),
),
)
],
// 从图像序列生成的MP4
if (_sequenceController?.value.isInitialized == true) ...[
Text("MP4模糊哈希: $_sequenceSize KB"),
AspectRatio(
aspectRatio: _sequenceController!.value.aspectRatio,
child: VideoPlayer(_sequenceController!),
),
],
// 使用FFmpeg模糊效果生成的MP4
if (_gblurController?.value.isInitialized == true) ...[
Text("FFmpeg高斯模糊: $_gblurSize KB"),
AspectRatio(
aspectRatio: _gblurController!.value.aspectRatio,
child: VideoPlayer(_gblurController!),
),
]
] else
const Center(
child: Text("选择一个视频",
style:
TextStyle(fontWeight: FontWeight.w500, fontSize: 18))),
],
),
floatingActionButton: FloatingActionButton(
onPressed: _process,
tooltip: "选择文件",
child: const Icon(Icons.file_present_rounded),
),
);
}
}
更多关于Flutter视频模糊预览插件blurhash_video的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter视频模糊预览插件blurhash_video的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用blurhash_video
插件来实现视频模糊预览的示例代码。这个插件允许你在视频播放前显示一个基于Blurhash编码的模糊预览图像,从而提升用户体验。
首先,你需要在你的pubspec.yaml
文件中添加blurhash_video
依赖:
dependencies:
flutter:
sdk: flutter
blurhash_video: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter项目中创建一个视频播放器页面,并使用BlurhashVideo
组件来显示模糊预览。以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'package:blurhash_video/blurhash_video.dart';
import 'package:chewie_flutter/chewie_flutter.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> {
ChewieController? _chewieController;
late String blurHash;
late String videoUrl;
@override
void initState() {
super.initState();
// 示例Blurhash和视频URL
blurHash = "LXYXA:#111,r99v#y+8.2+XmpbZMxf*kM4-j*X8+Xms8Yc*5"; // 替换为你的Blurhash
videoUrl = "https://www.example.com/path/to/your/video.mp4"; // 替换为你的视频URL
// 初始化ChewieController
_chewieController = ChewieController.fromSource(
ChewieSource.network(videoUrl),
aspectRatio: 16 / 9,
autoPlay: false,
looping: false,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Video Player with Blurhash Preview'),
),
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
// 显示Blurhash预览
BlurhashVideo(
blurHash: blurHash,
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
placeholder: Container(
color: Colors.grey.shade200,
),
),
// 视频播放器(初始隐藏,加载视频时显示)
if (_chewieController != null)
Positioned.fill(
child: Chewie(
controller: _chewieController!,
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// 播放视频
if (_chewieController != null) {
_chewieController!.play();
}
},
tooltip: 'Play',
child: Icon(Icons.play_arrow),
),
);
}
@override
void dispose() {
_chewieController?.dispose();
super.dispose();
}
}
在这个示例中,我们使用了Chewie
库来作为视频播放器。BlurhashVideo
组件用于显示基于Blurhash编码的视频模糊预览。当你点击浮动操作按钮(FAB)时,视频将开始播放。
请注意:
- 你需要替换
blurHash
和videoUrl
变量中的占位符值为你的实际Blurhash编码和视频URL。 - 确保你已经添加了
chewie_flutter
依赖,并正确配置了所有必要的依赖项。
这个示例展示了如何在Flutter中结合使用blurhash_video
和chewie_flutter
来实现视频模糊预览和播放功能。