如何在Flutter项目中获取本地视频文件的第一帧? 这是我的代码:
ImagePicker.pickVideo(source: ImageSource.camera).then((File file) {
if (file != null && mounted) {
//I got the video file here, but I want to get the first frame of the video.
}
});
},
答案 0 :(得分:0)
我使用发布的thumbnails实现了这一点。
String thumb = await Thumbnails.getThumbnail(
thumbnailFolder:'[FOLDER PATH TO STORE THUMBNAILS]', // creates the specified path if it doesnt exist
videoFile: '[VIDEO PATH HERE]',
imageType: ThumbFormat.PNG,
quality: 30);
/*
* thumbnailFolder property can be omitted if you dont wish to keep the generated thumbails past each usage
*/
答案 1 :(得分:0)
String thumb = await Thumbnails.getThumbnail(
thumbnailFolder:'[FOLDER PATH TO STORE THUMBNAILS]', // creates the specified path if it doesnt exist
videoFile: '[VIDEO PATH HERE]',
imageType: ThumbFormat.PNG,
quality: 30);
/*
* thumbnailFolder property can be omitted if you dont wish to keep the generated thumbails past each usage
*/
答案 2 :(得分:0)
下面的代码使用video_thumbnail插件,该插件在其文档中显示了对Android和ios的支持
Future genThumbnailFile() async{
final thumbnail = await VideoThumbnail.thumbnailFile(
video:
_video.path,
// thumbnailPath: _tempDir,
imageFormat: ImageFormat.JPEG,
//maxHeightOrWidth: 0,
maxHeight:3,
maxWidth: 2,
quality: 10);
setState(() {
final file = File(thumbnail);
filePath = file.path;
});
}
然后按如下所示在“图像”小部件中使用此filePath变量
filePath != null
? Container(
width:400,
height: 200,
child: Image(image: AssetImage(filePath)))
: Text('No Floatting Button Click')
答案 3 :(得分:0)
使用export_video_frame
,它适用于IOS。
var duration = Duration(seconds: 1);
var image = await ExportVideoFrame.exportImageBySeconds(widget.file, duration, 0);
答案 4 :(得分:0)
这是一个可以用于此的视图示例
import 'dart:io';
import 'package:export_video_frame/export_video_frame.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_compress/video_compress.dart';
import 'package:video_player/video_player.dart';
import 'package:video_thumbnail/video_thumbnail.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String thumbNailImage = '';
late VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.asset('assets/videos/butterfly.mp4')
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {
Future.delayed(Duration.zero, () async {
final byteData =
await rootBundle.load("assets/videos/butterfly.mp4");
Directory tempDir = await getTemporaryDirectory();
File tempVideo = File("${tempDir.path}/assets/videos/butterfly.mp4")
..createSync(recursive: true)
..writeAsBytesSync(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
final thumbnailFile = await VideoCompress.getFileThumbnail(
tempVideo.path,
quality: 50, // default(100)
position:
(_controller.value.duration.inMilliseconds) // default(-1)
);
var duration = _controller.value.duration;
var image = await ExportVideoFrame.exportImageBySeconds(
tempVideo, Duration(seconds: 3), 0);
thumbNailImage = image.path;
// final fileName = await VideoThumbnail.thumbnailFile(
// video: tempVideo.path,
// thumbnailPath: (await getTemporaryDirectory()).path,
// imageFormat: ImageFormat.JPEG,
// timeMs: _controller.value.duration.inMilliseconds,
// maxHeight: MediaQuery.of(context).size.height.toInt(),
// //quality: 100,
// );
//thumbNailImage = fileName!;
print(
"file name = $thumbNailImage video duration = ${_controller.value.duration.inMilliseconds}");
setState(() {});
});
});
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: thumbNailImage != ''
? Image.file(
File(thumbNailImage),
fit: BoxFit.contain,
)
: Container(), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
这些是需要的包
video_player: ^2.1.12
path_provider: ^2.0.2
export_video_frame: ^0.0.6