You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 02:36:02