Flutter中如何将相册多选存入数组的图片通过FFmpeg生成视频
解决Flutter中用multi_image_picker选图后通过FFmpeg生成视频的问题
核心问题分析
你的代码存在几个关键问题:
- 转换函数内重新定义了空的
resultlist,没有使用实际选中的图片数组 Asset对象不是本地文件路径,无法直接传入FFmpeg命令- FFmpeg命令格式错误,多张图片的输入逻辑不符合要求
解决方案步骤
1. 将Asset图片保存到本地路径
先实现一个方法,把选中的Asset保存到本地存储,获取FFmpeg可识别的文件路径:
import 'dart:io'; import 'package:path_provider/path_provider.dart'; import 'package:multi_image_picker/multi_image_picker.dart'; Future<List<String>> saveAssetsToLocal(List<Asset> assets) async { List<String> localPaths = []; for (var asset in assets) { final byteData = await asset.getByteData(); final file = File( '${(await getTemporaryDirectory()).path}/${asset.name}'); await file.writeAsBytes(byteData.buffer.asUint8List()); localPaths.add(file.path); } return localPaths; }
2. 修改视频转换函数,传入选中的图片数组
调整ConvertImageToVideo函数,传入实际选中的图片数组,构造正确的FFmpeg命令:
import 'package:ffmpeg_kit_flutter/ffmpeg_kit.dart'; import 'package:ffmpeg_kit_flutter/return_code.dart'; import 'package:permission_handler/permission_handler.dart'; Future<void> convertImageToVideo(List<Asset> selectedImages) async { const String BASE_PATH = '/storage/emulated/0/Download/'; const String AUDIO_PATH = BASE_PATH + 'audiio.mp3'; const String OUTPUT_PATH = BASE_PATH + 'output02.mp4'; if (await Permission.storage.request().isGranted) { // 将选中的Asset保存到本地 List<String> imagePaths = await saveAssetsToLocal(selectedImages); if (imagePaths.isEmpty) { print("没有选中的图片"); return; } // 构造FFmpeg命令:每张图片展示2秒,自动匹配音频时长 String concatFilter = ""; for (int i = 0; i < imagePaths.length; i++) { concatFilter += "[$i:v]trim=duration=2,setpts=PTS-STARTPTS[v$i];"; } concatFilter += imagePaths.map((e) => "[v${imagePaths.indexOf(e)}]").join(""); concatFilter += "concat=n=${imagePaths.length}:v=1:a=0[v]"; String commandToExecute = "-i ${AUDIO_PATH} " + imagePaths.map((path) => "-i $path").join(" ") + " -filter_complex \"$concatFilter\" " + "-map \"[v]\" -map 0:a -shortest -y $OUTPUT_PATH"; // 执行FFmpeg命令 await FFmpegKit.execute(commandToExecute).then((session) async { final returnCode = await session.getReturnCode(); if (ReturnCode.isSuccess(returnCode)) { print("视频生成成功,返回码:${returnCode.toString()}"); } else if (ReturnCode.isCancel(returnCode)) { print("视频生成被取消,返回码:${returnCode.toString()}"); } else { print("视频生成失败,返回码:${returnCode.toString()}"); // 打印错误日志排查问题 final log = await session.getAllLogs(); log.forEach((log) => print(log.getMessage())); } }); } else if (await Permission.storage.isPermanentlyDenied) { openAppSettings(); } }
3. 调用转换函数
在完成图片选择后,直接传入选中的resultList调用转换函数:
// 假设已通过multi_image_picker获取到选中的resultList convertImageToVideo(resultList);
关键说明
- 可通过修改
trim=duration=2中的2调整单张图片的展示时长(单位:秒) -shortest参数会让视频时长与音频时长保持一致,避免时长不匹配- 若不需要音频,可删除命令中与音频相关的输入和映射参数
- 保存图片的路径可根据需求调整为Download目录,而非临时目录
内容的提问来源于stack exchange,提问作者Ammara
相关产品推荐
相关产品推荐

