Flutter提取视频音频后文件路径不存在:上传服务器失败问题
问题:提取视频音频后上传,提示文件路径不存在
我在Flutter中使用image_picker从设备获取视频,再通过ffmpeg_kit_flutter提取音频,但上传音频文件到服务器时,系统提示文件路径不存在。相关代码如下:
转换视频到音频的函数
Future<void> _convertVideoToAudio() async { if (_pickedVideo != null) { bool? permissionGranted = await _requestStoragePermission(); if (permissionGranted != true) { print("Storage permission denied."); return; } String videoPath = _pickedVideo!.path; _outputPath = await getOutputFilePath(); // Get platform-specific path try { // Ensure the output directory exists await Directory(path.dirname(_outputPath)).create(recursive: true); await FFmpegKit.execute( "-i $videoPath -vn -c:a libmp3lame -q:a 2 $_outputPath"); // FFmpeg command print("Video converted to audio successfully!"); _showSuccessDialog(); // Display success dialog try { final String fileName = path.basename(_outputPath); final transcription = await _sendAudioForTranscription(_outputPath, fileName); if (transcription != null) { setState(() { _transcription = transcription; }); } else { setState(() { _transcription = "Transcription failed"; }); } } catch (e) { print('Error in transcription request: $e'); setState(() { _transcription = "Network request failed"; }); } } catch (e) { print("Error converting video: $e"); _showErrorDialog(); // Display error dialog } finally { setState(() { _pickedVideo = null; // Clear selected video }); } } else { print("Please pick a video first."); } }
获取输出路径的函数
Future<String> getOutputFilePath() async { final directory = await getApplicationDocumentsDirectory(); final downloadsDirectory = Directory('${directory.path}/downloads'); if (!(await downloadsDirectory.exists())) { await downloadsDirectory.create(recursive: true); } final String fileName = path .basename(_pickedVideo!.path) .replaceAll('.mp4', '.mp3'); // Replace extension final filePath = '${downloadsDirectory.path}/$fileName'; return filePath; }
问题分析与修复方案
1. FFmpeg执行结果未校验
FFmpegKit.execute不会主动抛出异常,即使命令执行失败,代码仍会继续执行并认为转换成功。必须校验执行结果:
修改转换逻辑:
// 替换原FFmpeg执行代码 final session = await FFmpegKit.execute("-i $videoPath -vn -c:a libmp3lame -q:a 2 $_outputPath"); final returnCode = await session.getReturnCode(); if (!ReturnCode.isSuccess(returnCode)) { final errorLog = await session.getAllLogsAsString(); print("FFmpeg转换失败日志: $errorLog"); throw Exception("音频提取失败"); } // 确认文件存在后再继续 final outputFile = File(_outputPath); if (!await outputFile.exists()) { throw Exception("生成的音频文件不存在"); } print("Video converted to audio successfully!"); _showSuccessDialog();
2. 文件名替换逻辑不可靠
原代码仅替换.mp4后缀,若视频是其他格式(如.mov、.avi),会生成类似video.mov.mp3的错误文件名,导致路径无效。
修改getOutputFilePath中的文件名生成逻辑:
final String fileName = "${path.basenameWithoutExtension(_pickedVideo!.path)}.mp3";
替换原fileName的生成代码,这样无论原视频后缀是什么,都能正确生成.mp3文件名。
3. 冗余的存储权限请求
getApplicationDocumentsDirectory()返回的是应用私有目录,读写该目录不需要申请外部存储权限。可以移除_requestStoragePermission()的调用,避免权限问题干扰。
4. 上传前再次校验文件存在
在调用_sendAudioForTranscription前,再次确认文件存在:
final audioFile = File(_outputPath); if (!await audioFile.exists()) { print("音频文件不存在: $_outputPath"); setState(() { _transcription = "音频文件生成失败"; }); return; } final transcription = await _sendAudioForTranscription(_outputPath, fileName);
内容的提问来源于stack exchange,提问作者Mohammed Bekele
相关产品推荐
相关产品推荐

