Duix.Heygem icon indicating copy to clipboard operation
Duix.Heygem copied to clipboard

mac上传视频时报 cannot find ffprobe是什么问题

Open JI-tangdou opened this issue 6 months ago • 2 comments

Image

JI-tangdou avatar Jul 07 '25 08:07 JI-tangdou

mac怎么部署啊

feifanhanmc avatar Aug 03 '25 07:08 feifanhanmc

`import ffmpeg from 'fluent-ffmpeg' import path from 'path' import fs from 'fs' import log from '../logger.js'

function initFFmpeg() { const ffmpegPath = { 'development-win32': path.join(__dirname, '../../resources/ffmpeg/win-amd64/bin/ffmpeg.exe'), 'development-linux': path.join(__dirname, '../../resources/ffmpeg/linux-amd64/ffmpeg'), 'development-darwin': '/opt/homebrew/bin/ffmpeg', 'production-win32': path.join( process.resourcesPath, 'app.asar.unpacked', 'resources', 'ffmpeg', 'win-amd64', 'bin', 'ffmpeg.exe' ), 'production-linux': path.join( process.resourcesPath, 'app.asar.unpacked', 'resources', 'ffmpeg', 'linux-amd64', 'ffmpeg' ), 'production-darwin': '/opt/homebrew/bin/ffmpeg' }

if(process.env.NODE_ENV === undefined){ process.env.NODE_ENV = 'production' }

function resolveBinary(map, program) { const key = ${process.env.NODE_ENV}-${process.platform} const candidate = map[key] const fallback = [ candidate, /opt/homebrew/bin/${program}, /usr/local/bin/${program}, /usr/bin/${program} ] for (const p of fallback) { if (p && fs.existsSync(p)) return p } return candidate }

const ffmpegPathValue = resolveBinary(ffmpegPath, 'ffmpeg') log.debug('ENV:', ${process.env.NODE_ENV}-${process.platform}) log.info('FFmpeg path:', ffmpegPathValue) if (ffmpegPathValue) { ffmpeg.setFfmpegPath(ffmpegPathValue) } else { log.warn('FFmpeg binary not resolved, please ensure ffmpeg is installed and on PATH') }

const ffprobePath = { 'development-win32': path.join(__dirname, '../../resources/ffmpeg/win-amd64/bin/ffprobe.exe'), 'development-linux': path.join(__dirname, '../../resources/ffmpeg/linux-amd64/ffprobe'), 'development-darwin': '/opt/homebrew/bin/ffprobe', 'production-win32': path.join( process.resourcesPath, 'app.asar.unpacked', 'resources', 'ffmpeg', 'win-amd64', 'bin', 'ffprobe.exe' ), 'production-linux': path.join( process.resourcesPath, 'app.asar.unpacked', 'resources', 'ffmpeg', 'linux-amd64', 'ffprobe' ), 'production-darwin': '/opt/homebrew/bin/ffprobe' }

const ffprobePathValue = resolveBinary(ffprobePath, 'ffprobe') log.info('FFprobe path:', ffprobePathValue) if (ffprobePathValue) { ffmpeg.setFfprobePath(ffprobePathValue) } else { log.warn('FFprobe binary not resolved, please ensure ffprobe is installed and on PATH') } }

initFFmpeg()

export function extractAudio(videoPath, audioPath) { return new Promise((resolve, reject) => { ffmpeg(videoPath) .noVideo() .save(audioPath) .on('end', () => { log.info('audio split done') resolve(true) }) .on('error', (err) => { reject(err) }) }) }

export async function toH264(videoPath, outputPath) { // const hasNvidia = await detectNvidia() return new Promise((resolve, reject) => { ffmpeg(videoPath) .videoCodec('libx264') .outputOptions('-pix_fmt yuv420p') .save(outputPath) .on('end', () => { log.info('video convert to h264 done') resolve(true) }) .on('error', (err) => { reject(err) }) }) }

function detectNvidia() { return new Promise((resolve) => { const exec = require('child_process').exec; exec('nvidia-smi', (error, stdout, stderr) => { if (error || stderr) { resolve(false); } else { resolve(true); } }); }); }

export function getVideoDuration(videoPath) { return new Promise((resolve, reject) => { ffmpeg(videoPath).ffprobe((err, data) => { if (err) { log.error("🚀 ~ ffmpeg ~ err:", err) reject(err) } else if (data && data.streams && data.streams.length > 0) { resolve(data.streams[0].duration) // 单位秒 } else { log.error('No streams found') reject(new Error('No streams found')) } }) }) } `问题定位

  • 主进程通过 fluent-ffmpeg 需要找到 ffprobe / ffmpeg 二进制,但只为 win32 和 linux 配置了路径,缺少 darwin (macOS)映射,导致在 macOS 上报“找不到 ffprobe”。 修复方案

  • 增加 macOS 的路径解析,并加入常见 Homebrew 安装位置的回退检测;找不到时打印日志提示安装或配置 PATH。

  • 已更新的文件与关键位置:

    • src/main/util/ffmpeg.js:1-4 引入 fs 用于存在性检测
    • src/main/util/ffmpeg.js:6-26 扩展 ffmpegPath ,新增 development-darwin 与 production-darwin
    • src/main/util/ffmpeg.js:32-41 新增 resolveBinary ,按映射与常见位置( /opt/homebrew/bin , /usr/local/bin , /usr/bin )解析路径
    • src/main/util/ffmpeg.js:43-48 解析并设置 ffmpeg 路径,找不到时 log.warn
    • src/main/util/ffmpeg.js:50-64 扩展 ffprobePath ,新增 development-darwin 与 production-darwin
    • src/main/util/ffmpeg.js:66-71 解析并设置 ffprobe 路径,找不到时 log.warn 如何验证
  • 在 macOS 上执行任意触发 ffprobe 的功能(如读取视频或音频信息):

    • src/main/util/ffmpeg.js:111-125 的 getVideoDuration 会调用 ffprobe ,若路径正确应无“找不到 ffprobe”的错误日志。
    • 文件信息接口使用点:
      • src/main/handlers/file.js 的 getVideoInfo(...) 与 getAudioInfo(...) ,内部均调用 .ffprobe(...) 。
  • 如日志仍提示未解析到二进制,请在本机安装 FFmpeg(包含 ffprobe):

    • Apple Silicon: brew install ffmpeg 使用 /opt/homebrew/bin/ffprobe
    • Intel: brew install ffmpeg 使用 /usr/local/bin/ffprobe
    • 安装后无需改代码,应用会自动识别这些路径;或将 FFmpeg 加入系统 PATH。 补充说明
  • 在生产打包中,若未内置 macOS 的 FFmpeg 资源,以上回退逻辑会优先使用本机安装的 FFmpeg/ffprobe。

  • 若希望完全内置二进制,可在 resources/ffmpeg 下添加 macos-amd64 / macos-arm64 目录并映射对应路径,然后移除回退逻辑即可。

hackyinge avatar Nov 18 '25 10:11 hackyinge