Adobe扩展NodeJS环境下读取FormData文件调用ffmpeg提取音频问题
解决方案:Adobe扩展Node.js环境中用FFmpeg提取视频音频(处理FileInput伪路径问题)
核心问题分析
HTML的input[type=file]在Adobe CEP扩展环境中返回的value是伪路径,无法直接被FFmpeg识别。你需要获取真实的文件内容流或本地真实文件路径来喂给FFmpeg。
方案1:将File对象转为Node.js可读流(无需真实路径)
利用浏览器标准的File API获取文件内容,转成Node.js的Readable流,直接传给FFmpeg:
- 获取用户选择的File对象(不要用
value属性) - 将File转为ArrayBuffer再转成Node.js Buffer
- 基于Buffer创建可读流,传入FFmpeg处理
const { Readable } = require('stream'); const ffmpeg = require('fluent-ffmpeg'); const fileInput = document.getElementById('video-upload'); fileInput.addEventListener('change', async (e) => { const selectedFile = e.target.files[0]; if (!selectedFile) return; // 把File转成Node.js可处理的Buffer const arrayBuffer = await selectedFile.arrayBuffer(); const fileBuffer = Buffer.from(arrayBuffer); // 创建可读流 const fileStream = Readable.from(fileBuffer); // 用FFmpeg提取音频 ffmpeg(fileStream) .outputOptions('-vn') // 禁用视频流,只保留音频 .format('mp3') // 指定输出音频格式 .pipe(process.stdout) // 可替换为写入文件或上传流 .on('end', () => console.log('音频提取完成')) .on('error', (err) => console.error('处理失败:', err)); });
方案2:通过CEP API获取真实本地文件路径
如果你的FFmpeg依赖本地文件路径(比如某些旧版本或特定插件),可以用Adobe CEP的CSInterface调用宿主程序的API获取真实路径:
- 引入CEP的
CSInterface(扩展默认自带) - 调用宿主的文件选择对话框(替代HTML FileInput,避免伪路径问题)
- 获取真实文件路径后直接传给FFmpeg
const csInterface = new CSInterface(); const ffmpeg = require('fluent-ffmpeg'); // 触发文件选择(替代HTML FileInput) document.getElementById('select-video-btn').addEventListener('click', () => { // 调用Adobe宿主的文件选择脚本 csInterface.evalScript(` var fileObj = new File(); var selectedPath = fileObj.browseDlg("选择视频文件", "*.mp4;*.mov;*.avi"); fileObj.exists ? fileObj.fsName : null; `, (realFilePath) => { if (realFilePath === 'null' || !realFilePath) return; // 用真实路径调用FFmpeg ffmpeg(realFilePath) .outputOptions('-vn') .format('mp3') .save('./extracted-audio.mp3') .on('end', () => console.log('音频提取完成')) .on('error', (err) => console.error('处理失败:', err)); }); });
方案3:写入临时文件后用路径调用FFmpeg
如果以上两种方式不兼容,可将File对象写入本地临时文件,用临时文件路径给FFmpeg:
const fs = require('fs'); const os = require('os'); const path = require('path'); const ffmpeg = require('fluent-ffmpeg'); const fileInput = document.getElementById('video-upload'); fileInput.addEventListener('change', async (e) => { const selectedFile = e.target.files[0]; if (!selectedFile) return; // 创建临时文件路径 const tempFilePath = path.join(os.tmpdir(), `temp_video_${Date.now()}.mp4`); // 将File写入临时文件 const arrayBuffer = await selectedFile.arrayBuffer(); fs.writeFileSync(tempFilePath, Buffer.from(arrayBuffer)); // 用临时文件路径处理 ffmpeg(tempFilePath) .outputOptions('-vn') .format('mp3') .save('./extracted-audio.mp3') .on('end', () => { console.log('音频提取完成'); // 清理临时文件 fs.unlinkSync(tempFilePath); }) .on('error', (err) => { console.error('处理失败:', err); // 报错也要清理临时文件 fs.unlinkSync(tempFilePath); }); });
关键注意事项
- 确保你的扩展
manifest.xml中开启了文件访问权限:<CEFCommandLine> <Parameter>--allow-file-access-from-files</Parameter> </CEFCommandLine> - 若使用
fluent-ffmpeg,需确保FFmpeg二进制文件已打包到扩展中,并正确配置ffmpeg.setFfmpegPath('./path/to/ffmpeg')。
内容的提问来源于stack exchange,提问作者CodingCode
相关产品推荐
相关产品推荐

