NestJS控制器中使用FFmpeg提取视频音频时提示文件不存在但文件实际存在的问题排查
看起来你在NestJS里用FFmpeg提取音频时遇到了经典的路径坑——明明确认文件位置正确,却始终提示文件不存在。我帮你梳理几个关键排查点,一步步定位问题:
1. 先搞清楚NestJS进程的当前工作目录
Node.js进程的**当前工作目录(cwd)**不一定是你的项目根目录,这是相对路径出错的最常见原因。你可以在控制器代码里先打印当前路径,确认解析起点:
console.log('当前工作目录:', process.cwd());
举个例子,如果你的项目结构是:
your-project/ ├── src/ │ └── controllers/ │ └── audio.controller.ts └── uploads/ └── 0.777341078548575.mp4
如果当前工作目录是your-project/src/controllers,那../../uploads/0.777341078548575.mp4才是正确的相对路径;但如果cwd是your-project,直接用./uploads/0.777341078548575.mp4就够了。先打印cwd,再对应调整路径。
2. 用绝对路径彻底规避相对路径问题
最稳妥的方式是构建绝对路径,完全不受工作目录变化的影响。你可以用Node.js的path.join()结合process.cwd()或__dirname来生成准确路径:
import { join } from 'path'; // 假设uploads文件夹在项目根目录下 const inputPath = join(process.cwd(), 'uploads', '0.777341078548575.mp4'); console.log('完整输入路径:', inputPath); // 先打印确认路径是否和你预期的一致 try { let process = new ffmpeg(inputPath) // 后续提取音频的逻辑不变 } catch (e) { console.log("CATCHED ERROR", e) }
3. 提前验证文件是否存在
在调用FFmpeg之前,先用Node.js的fs.existsSync()检查文件是否真的存在,快速区分是路径问题还是FFmpeg本身的问题:
import { existsSync } from 'fs'; const inputPath = join(process.cwd(), 'uploads', '0.777341078548575.mp4'); console.log('文件是否存在:', existsSync(inputPath)); // 如果输出false,说明路径肯定错了,先修正路径;如果是true,再往下排查
4. 检查文件权限
如果路径正确但文件仍“不存在”,可能是FFmpeg进程没有读取该文件的权限。在Linux/macOS下,你可以用终端命令查看权限:
ls -l uploads/0.777341078548575.mp4
确保运行NestJS的用户(比如node用户)有读权限。如果权限不足,执行以下命令添加读权限:
chmod +r uploads/0.777341078548575.mp4
5. 确认FFmpeg库的配置
如果你用的是fluent-ffmpeg库,还要确保它能找到FFmpeg的二进制文件。有时候系统没装FFmpeg,或者二进制路径没配置对,也会抛出误导性的“文件不存在”错误。
先在终端里确认FFmpeg已安装:
ffmpeg -version
如果能正常输出版本信息,再在代码里指定二进制路径(根据你的系统调整):
import ffmpeg from 'fluent-ffmpeg'; // Linux/macOS示例 ffmpeg.setFfmpegPath('/usr/bin/ffmpeg'); // Windows示例:ffmpeg.setFfmpegPath('C:\\ffmpeg\\bin\\ffmpeg.exe');
修正后的完整代码示例
把上面的排查点整合起来,代码大概是这样:
import { join } from 'path'; import { existsSync } from 'fs'; import ffmpeg from 'fluent-ffmpeg'; // 可选:指定FFmpeg二进制路径(根据你的系统调整) ffmpeg.setFfmpegPath('/usr/bin/ffmpeg'); try { const inputPath = join(process.cwd(), 'uploads', '0.777341078548575.mp4'); console.log('输入路径:', inputPath); console.log('文件存在:', existsSync(inputPath)); let process = new ffmpeg(inputPath) process.then(function (video) { // 同样用绝对路径指定输出文件 const outputPath = join(process.cwd(), 'uploads', 'audio', 'test', '007.mp3'); video.fnExtractSoundToMP3( outputPath, function (error, file) { if (!error) { console.log('音频文件已生成: ' + file); } else { console.log('提取音频出错:', error); } } ) }, function (err) { console.log('FFmpeg初始化错误: ' + err) }) } catch (e) { console.log("捕获到错误", e) }
先运行这段代码,看打印的路径和文件存在状态,一步步排查就能解决问题了。
内容的提问来源于stack exchange,提问作者bluepuper

