I'm trying to convert a file to a list of image file. Ideally with an option to extract a frame every X milliseconds.
Do you know if it possible to do so with flutter using ffmpeg?
Been trying with export_video_frame plugin but it is very slow and not stable.
Try the below snippet:
String command = "-i ${videoFilePath} -r $imagesCount -f image2 ${outputPath}image-%3d.png"
FFmpegKit.execute(command).then((session) async {
final returnCode = await session.getReturnCode();
if (ReturnCode.isSuccess(returnCode)) {
print("Success!!!!");
} else {
print("Failed!!!!");
}
}
);
Replace videoFilePath with the input file path and outputPath with the directory path where you want to save the images. Also, the imagesCount with how many images you want per frame.
Hi everyone i build flutter app to download video .
the app save all video in this path :
/storage/emulated/0/Android/data/com.test.play/files/
and now i work to video downloaded page
how can i read just videos in app path
and display the videos in list ?
You can use file_picker to pick multiple files.
FilePickerResult? result = await FilePicker.platform.pickFiles(allowMultiple: true);
if (result != null) {
List<File> files = result.paths.map((path) => File(path)).toList();
} else {
// User canceled the picker
}
or if you want to pick files with extension filter
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['mp4'],
);
I'm trying to connect an audio file to a static image and render it as video containing only the static image and the audio playback, I looked into several pub libraries like this
but haven't found any documentation on how to implement when I'm looking for, is there a simple way to do this? and if not is it possible to accomplish using dart without writing platform specific stuff?
This is what I ended up doing, I hope it helped someone,
in my case I needed to connect an image to an audio file to create a video that can be shared with the share_plus plugin
You don't really have an alternative to ffmpeg, but you can set it up so it isn't so bad to use:
add this to your pubspec.yaml dependencies
ffmpeg_kit_flutter_min_gpl: ^4.5.0-LTS
import those in the files you want to render the video:
import 'package:ffmpeg_kit_flutter_min_gpl/return_code.dart';
import 'package:ffmpeg_kit_flutter_min_gpl/ffmpeg_kit.dart';
and then the render itself:
await FFmpegKit.executeAsync(
'-y -i $screenshotPath -i $filePath -c:v libx264 -tune stillimage -c:a aac -b:a 192k -pix_fmt yuv420p ${applicationDocumentDirectory.path}/new.mp4',
(session) async {
final state = await session.getState();
final returnCode = await session.getReturnCode();
String output = await session.getOutput();
print(output);
if (ReturnCode.isSuccess(returnCode)) {
// SUCCESS
await Share.shareFiles(
['${applicationDocumentDirectory.path}/new.mp4'],
);
} else if (ReturnCode.isCancel(returnCode)) {
// CANCEL
} else {
// ERROR
}
});
I am using Flutter-FFMPEG a Flutter library based on Mobile FFMPEG. I am creating a video from a list of .bmp images. The video works plays normally in devices media player on android or desktop.
But when I tried to share that video on social media like say Instagram it says file format not supported.
It didn't use to work on WhatsApp but after some googling, I made some changes and it works on WhatsApp and Youtube now but not on Instagram, Linkedin, etc.
void _runFFmpeg() async {
print('Run FFMPEG');
var dir = await getApplicationDocumentsDirectory();
var output = await getExternalStorageDirectory();
String videoSize = '$ImageWidth:$ImageSize';
print("${ImageWidth}x$ImageSize");
var arguments = [
"-y", // replace output file if it already exists
"-i", "${output.path}/frame_%d.bmp",
"-s", '${ImageWidth}x$ImageSize',
"-framerate", "30", // framrate
"-c:v", "libvpx",
'-ab', '128k',
'-ar', '44100',
'-strict', 'experimental',
"-vcodec", "libx264",
"-pixel_format", "yuv420p",
"-preset", "ultrafast",
"-tune", "animation",
"${output.path}/test.mp4"
];
await _flutterFFmpeg.executeWithArguments(arguments).then((rc) {
print('Process done with $rc');
});
The plugin I am using (Flutter-FFMPEG) didn't support libx264
I tried using '-profile:v' to baseline but that gives an error, saying Error setting profile to baseline.
Also, I tried to first make a .webm file and then convert that to mp4. I was also able to use '-profile:v' when converting .webm to mp4 and gave no error but the output video didn't work on Social Media platforms.
fixFFMPEG(int imageWidth, int imageSize) async {
print('Fix FFMPEG');
var output = await getExternalStorageDirectory();
var arguments2 = [
'-y',
// "-s",
// '${imageWidth}:$imageSize',
'-i',
'${output.path}/testNew.mp4',
"-framerate", "30", // framrate
"-vcodec", "h264",
"-c:v", "libx264rgb",
"-c:a", 'acc',
'-ab', '128k',
'-ar', '44100',
'-strict', 'experimental',
// '-c',
// 'copy',
// '-strict',
// '-2',
"-vprofile",
"baseline",
"-level",
"3.0",
"-an",
"-pixel_format", "yuv420p",
// '-vtag',
// 'avc1',
// "-vprofile",
// "baseline",
// "-level",
// "3.0",
// "-brand", "mp42",
'${output.path}/fixedvideo1.mp4'
];
// await _flutterFFmpeg
// .executeWithArguments(arguments2)
// .then((rc) => print("FFmpeg process2 exited with rc $rc"));
}
I am trying to make a simple app in Flutter. A user can either take or pick a video and then upload it. However, I wanted to compress the video for storage purposes on firebase storage, and also trim it to only get the first 30 seconds.
I am facing a very puzzling problem. I am able to compress the video, but with the resultant file, FFmpeg fails to trim it and I get endless logs which result in me having to stop the app and re-run. Alternatively, I am able to trim the video, but with the resultant file, I am unable to compress it getting the error: Failed to open file '/data/user/0/live.roots.roots/app_flutter/TRIMMED.mp4'. (No such file or directory) PlatformException(error, java.io.IOException: Failed to instantiate extractor., null, java.lang.RuntimeException: java.io.IOException: Failed to instantiate extractor.
This is my code below:
//! function that controls file compression and trimming
static Future<File> compressFile(File file) async {
print('[COMPRESSING FILE]');
String mimeStr = lookupMimeType(file.path);
var fileType = mimeStr.split('/');
if (fileType.contains("image")) {
print('[COMPRESSING FILE] - file is image');
String tempPath = (await getTemporaryDirectory()).path;
String targetPath = '$tempPath/${DateTime.now().toIso8601String()}.jpg';
return await compressImageAndGetFile(file, targetPath);
} else {
print('[COMPRESSING FILE] - file is video');
final compressedVideoFile = await compressVideoAndGetFile(file);
print('[VIDEO FILE COMPRESSED]');
return await trimVideoGetFile(compressedVideoFile);
}
}
//! function to compress video
static Future<File> compressVideoAndGetFile(File file) async {
print('[COMPRESSING VIDEO]');
var result = await VideoCompress.compressVideo(
file.absolute.path,
quality: VideoQuality.DefaultQuality,
deleteOrigin: true,
);
print('[COMPRESSED VIDEO TO]: ${result.file.path}');
return result.file;
}
//! function to trim video
static Future<File> trimVideoGetFile(File file) async {
print('[TRIMMING VIDEO]');
Directory appDocumentDir = await getApplicationDocumentsDirectory();
String rawDocumentPath = appDocumentDir.path;
String outputPath = rawDocumentPath + "/TRIMMED.mp4";
final newFile = File(outputPath);
if (await newFile.exists()) {
await newFile.delete();
}
_flutterFFmpeg
.execute(
"-ss 00:00:00 -i ${file.path} -to 00:00:30 -c copy $outputPath")
.then((rt) async {
print('[TRIMMED VIDEO RESULT] : $rt');
if (rt == -1) {
throw Exception("Something went wrong when trimming the video");
}
});
return File(outputPath);
}
Thank you in advance
Video_compress package allows you to trim the duration without the need to FFmpeg.
var result = await VideoCompress.compressVideo(
file.absolute.path,
quality: VideoQuality.DefaultQuality,
deleteOrigin: true,
startTime: 0, // customize start time
duration: 30, // customize the length
);