
简介为简化FFmpeg在Linux系统上的安装流程而设计的自动安装脚本面向需要使用视频转码或流媒体处理的开发者和运维人员尤其适合不熟悉源码编译与依赖配置的新手能解决手动部署耗时长、依赖遗漏等问题。脚本封装了更新软件源、安装依赖库、下载源码、配置编译选项、编译安装及清理临时文件等完整步骤在基于apt或yum的常见Linux发行版中均可运行用户只需赋予执行权限并执行一条命令即可完成部署。压缩包内共1个文件为sh格式安装脚本整体仅2KB内容精简易读方便按需修改。当前已有553人学习下载。借助该脚本可获得完整FFmpeg命令行环境支持视频转码、视频剪辑与合并、音频提取以及RTMP、HLS等流媒体实时处理既能显著缩短部署时间又能避免手工编译中的常见问题为后续多媒体操作提供稳定基础。 做音视频处理的人几乎没人能绕开 ffmpeg。但这个工具强大归强大安装的时候是真的折磨人——特别是你在 CentOS 7 上敲yum install ffmpeg却提示“没有可用软件包”或者去官网下 Windows 版本时对着三四个 zip 文件名发愣的时候心态很容易崩。这篇文章想聊的就是我维护了很久的一个 ffmpeg 自动安装脚本它能用一段命令把 Linux、macOS、Windows 三个平台的安装流程收敛起来自动检测系统和芯片架构、下载对应版本、解压部署、配好环境变量最后再验证一遍 ffmpeg 能不能正常跑起来。适合经常要在新服务器上部署环境的人、做音视频相关的开发者以及刚接触 ffmpeg 想少走弯路的新手。1. 别再手动装 ffmpeg 了这几个坑我帮你列全1.1 服务器上用包管理器装版本老到让你怀疑人生先说最常用的 Linux 服务器场景。大多数人第一反应是yum install ffmpeg或者apt install ffmpeg但真执行起来问题一堆。CentOS 7 的默认源里根本没有 ffmpeg你得先装epel-release再折腾rpmfusion源好不容易装上之后版本往往停留在 3.x 甚至更老。这个版本有多老老到-fps_mode这类参数都不支持低版本里是-r或者其他写法老到某些编码器在 decode 的时候行为跟新版完全不一样。做视频处理的人应该都懂ffmpeg 是命令行工具不同小版本之间的参数行为差异能让你调一个滤镜调半天最后发现是版本问题。Ubuntu 稍微好一点但 apt 源里的版本也比较保守而且 Ubuntu 版本和 apt 源版本之间还有绑定关系你在这台机器上测好的命令换一台系统版本不同的机器可能就要调整参数。我见过不少同事在本地 Mac 上一切正常代码推到 CI 的 Ubuntu 容器里就跑不起来排查到最后发现是 CI 镜像里 ffmpeg 版本太低。1.2 源码编译是一条路但时间成本不划算有经验的人会说那我自己编译。这条路是通的但你要先编译一堆依赖libx264、libx265、libvpx、libfdk-aac、libmp3lame……每个依赖都有自己的 configure 参数和依赖关系编译一个完整功能的 ffmpeg在普通配置的服务器上轻松跑三四十分钟。而且编译链路上任何一步报错你都得上网查半天。一次性的服务器环境比如测试机、临时任务节点花四十分钟编译 ffmpeg这笔时间账怎么算都不划算。还有个小细节是关于 ffmpeg 命令的-y参数很多人第一次用的时候会在交互里卡住当你转换一个已经存在的文件不写-y的话 ffmpeg 会停下来问你是不是要覆盖而脚本化调用时根本没有人类去按y任务就挂在那了。-y的意思就是“全局自动覆盖输出文件”这个参数在批处理里几乎必加。这类“文档里写得很简单实际用起来才发现少了某个参数”的坑用顺手之后没什么但对新手来说每一个都能卡好一阵。1.3 Windows 和 macOS 的安装方式又完全是另一套如果你以为只有 Linux 麻烦那就低估了跨平台的痛。macOS 一般走brew install ffmpeg前提是你装了 Homebrew而且网络环境不给力的时候brew 下载 Bottle 的速度能让人怀疑人生。Windows 上则要面对另一套玩法官网下载 zip 包但文件名里有 release、full、gpl、lgpl 这些词新手根本不知道选哪个解压完还要手动把bin目录加进系统 PATH加完之后还得重启或者手动刷新环境变量否则你在新开的终端里就是找不到ffmpeg命令。也就是说三个平台的安装逻辑几乎没有重合点。你可以在脑海里记住三套流程但我选择把它们写进一个脚本里以后不管到哪台机器上跑一条命令就完事。2. 自动安装脚本的设计思路从一条命令到跨平台2.1 脚本要解决什么问题安装、收敛、幂等、可验证写这个脚本之前我先想清楚一个脚本要满足哪些条件不然写着写着就会变成一坨堆满if的“一次性代码”。第一是安装要收敛。一个入口不管你在什么平台上执行它自己去判断该做什么。第二是幂等。重复运行脚本不能把环境搞坏最好还能顺便把旧版本升级掉。第三是可验证。装完不能悄无声息得用ffmpeg -version和实际探测能力的方式确认这个二进制真的是能用的否则装完才发现有问题更费时间。第四是干净。尽量不要往系统里塞一堆编译依赖卸载的时候最好只删一个目录加几个软链接。这几条加在一起就决定了我的方案导向优先用二进制包而不是源码编译。2.2 平台适配Linux 静态包、macOS 走 brew、Windows 走 winget跨平台的本质是“知道自己在哪然后用那个平台最顺手的安装方式”。脚本第一步就是检测操作系统和 CPU 架构。Linux 下我用uname -s判断内核再进一步判断是 CentOS 系还是 Ubuntu 系——但如果你直接用静态编译包发行版之间的差异就基本被抹平了这也是我推荐静态包的主要原因。macOS 下我用uname -s识别出Darwin然后直接调 Homebrew。Windows 下情况比较特殊原生环境里没有 bash但你可以在 Git Bash 或 WSL 里跑这个脚本检测到MINGW*或MSYS*的时候优先用 winget 安装——Windows 10 和 Windows 11 自带 winget一条winget install就能把事情办了。架构检测同样重要。同样是 Linuxx86_64 和 arm64 的二进制包完全不通用。现在 ARM 服务器越来越多了如果不区分架构脚本在 ARM 机器上就会去下载 x86 的包然后解压出一个没法运行的二进制排查起来很麻烦。2.3 为什么我给 Linux 选“静态编译包”而不是源码编译这里很多朋友会有疑问网上大多数教程都在教源码编译静态包靠谱吗我实际用了这几年可以负责任地说对于绝大多数业务场景静态包是更优解。所谓静态编译就是编译的时候把依赖库全部打进了可执行文件里相当于一个自带干粮的二进制不依赖系统的动态库版本。好处非常明显不管你是 CentOS 7 还是 Ubuntu 22不管系统里缺不缺 libx264.so只要内核能跑这个二进制它就能正常工作。代价是文件体积大一点ffmpeg 和 ffprobe 两个文件加起来大概 80MB 左右但对现在的机器来说完全可以接受。源码编译的唯一优势是“可以精确裁剪功能”但这个优势在绝大多数场景下用不上。绝大多数人需要的功能静态包里全都有。你只需要确认一点这个静态包的来源可不可信。我用的源是 ffmpeg 官方推荐的 John Van Sickle 静态构建站更新比较及时跟随 ffmpeg 主线版本走这一点让我比较放心。3. 可直接复制的 ffmpeg 自动安装脚本3.1 完整脚本正文我直接放完整脚本这是我平时实际在用的版本你复制下来保存为install_ffmpeg.sh就能跑#!/usr/bin/env bash # ffmpeg 自动安装脚本 # 支持: Linux x86_64 / Linux arm64 / macOS / Windows(Git Bash 或 WSL) # 用法: bash install_ffmpeg.sh set -euo pipefail INSTALL_DIR${INSTALL_DIR:-/usr/local/ffmpeg} BIN_DIR/usr/local/bin log() { echo -e \033[32m[INFO]\033[0m $*; } warn() { echo -e \033[33m[WARN]\033[0m $*; } fail() { echo -e \033[31m[ERROR]\033[0m $*; exit 1; } check_root() { if [[ $(id -u) -ne 0 ]]; then fail Linux 安装需要 root 权限请用 sudo 执行 fi } detect_platform() { local kernel kernel$(uname -s) case $kernel in Linux*) OSlinux ;; Darwin*) OSmacos ;; MINGW*|MSYS*|CYGWIN*) OSwindows ;; *) fail 不支持的平台: $kernel ;; esac local arch arch$(uname -m) case $arch in x86_64|amd64) ARCHx86_64 ;; aarch64|arm64) ARCHarm64 ;; *) fail 不支持的架构: $arch ;; esac } install_linux() { local url if [[ $ARCH arm64 ]]; then urlhttps://johnvansickle.com/ffmpeg/releases/ffmpeg-release-arm64-static.tar.xz else urlhttps://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz fi local tarball/tmp/ffmpeg-static.tar.xz log 下载 ffmpeg 静态包... curl -fSL --retry 3 -o $tarball $url log 解压部署到 $INSTALL_DIR ... mkdir -p $INSTALL_DIR tar -xJf $tarball -C $INSTALL_DIR --strip-components1 ln -sf $INSTALL_DIR/ffmpeg $BIN_DIR/ffmpeg ln -sf $INSTALL_DIR/ffprobe $BIN_DIR/ffprobe } install_macos() { if command -v brew /dev/null 21; then brew install ffmpeg else fail macOS 需要先安装 Homebrew: https://brew.sh fi } install_windows() { if command -v winget /dev/null 21; then winget install --id Gyan.FFmpeg -e else fail Windows 建议用 winget或去 gyan.dev 手动下载 fi } verify() { if command -v ffmpeg /dev/null 21; then ffmpeg -version | head -n 1 ffmpeg -hide_banner -formats /dev/null 21 \\ log ffmpeg 安装成功可用 else fail ffmpeg 命令不可用请检查 PATH 或重新登录 shell fi } main() { detect_platform log 当前平台: $OS / $ARCH case $OS in linux) check_root; install_linux ;; macos) install_macos ;; windows) install_windows ;; esac verify } main $3.2 set -euo pipefail 和 root 检查为什么不能省脚本头部set -euo pipefail这行很多人不注意但我建议任何自动化脚本都加上。-e表示脚本里任何一条命令出错就直接退出避免“前面失败了后面还继续跑”的连锁反应-u表示使用未定义变量时报错能帮你抓住很多拼写错误pipefail表示管道命令中只要有一段失败整个管道的返回值就是失败。这三兄弟组合在一起基本保证了脚本不会在出错后继续“带病运行”。check_root里我强制要求 root 权限因为 Linux 下脚本要往/usr/local/ffmpeg和/usr/local/bin写文件普通用户没有这些目录的写权限。很多新手会忽略这个然后看到一堆Permission denied才反应过来。如果你实在不想用 root也可以把INSTALL_DIR改成用户目录下的路径并且让脚本只修改当前用户的PATH有兴趣的可以自己扩展。其实我原来在 macOS 和 Windows 分支里也检查 root后来发现 macOS 下用 brew 根本不需要 rootWindows 的 winget 也不需要所以我把 root 检查移到了install_linux之前。这也是写脚本过程中很典型的一个调整不是全局统一检查而是按平台按需检查。3.3 核心安装函数逐行说明detect_platform里我用uname -s来判断操作系统。这里有一个细节Windows 的 Git Bash 里uname -s输出的是MINGW64_NT-...这样的字符串用MINGW*|MSYS*|CYGWIN*这个 pattern 能把所有常见的 Windows 兼容层识别出来。架构判断我用uname -m在 x86 机器上输出x86_64在 ARM Mac 或 ARM 服务器上输出arm64部分 Linux 下是aarch64所以 pattern 里我两种都写了。install_linux里下载用了curl -fSL --retry 3。-f是让 HTTP 出错时直接失败而不是下载出一个错误页面-S是显示错误信息-L是跟随重定向--retry 3是失败后重试三次。下载地址对应的是 John Van Sickle 的静态构建包这个源的好处是包名固定不用像自己编译一样去记一堆依赖。解压的时候注意我用了--strip-components1因为压缩包解压后第一层是一个带版本号的目录比如ffmpeg-6.1-static用这个参数可以去掉第一层目录让文件直接落在/usr/local/ffmpeg下面方便后续管理。软链接这一步是关键我没有直接把二进制复制到/usr/local/bin而是创建软链接。好处是以后升级的时候只需要下载新包、解压覆盖/usr/local/ffmpeg目录软链接不用动。如果你直接复制文件升级的时候还要记得替换两个文件容易漏。3.4 安装完成后的验证逻辑verify函数做了两件事。第一件ffmpeg -version | head -n 1打印出版本号让你直观看到装的是什么版本。第二件ffmpeg -hide_banner -formats /dev/null 21检查 ffmpeg 能不能正常枚举所有支持的封装格式这个命令如果成功说明 ffmpeg 的核心功能模块是完整的不只是“能打印版本号”而已。版本号能打印只能说明可执行文件能跑起来但能枚举格式才能说明内部组件没缺失。我自己见过一次构建不完整的 ffmpeg版本号能正常打印但一跑实际转码就报 “Unknown encoder” 的错所以后来我坚持在验证环节加上功能性检查。4. 脚本实战常见报错和排查建议4.1 下载很慢或者直接卡住怎么办用这个脚本的人遇到最多的就是下载环节出问题。静态包虽然有 80MB 左右但某些网络环境下从国外源拉取速度很不稳定甚至直接超时。我在这里踩过几次坑目前觉得有三层处理思路。第一层是脚本里的--retry 3它只能解决瞬时网络抖动。如果你在的地区访问这个源长期很慢建议先手动用浏览器或者下载工具把 tar.xz 包拉到本地然后放到自己方便访问的地方比如公司内网的 HTTP 服务器再用如下方式离线安装。INSTALL_DIR/usr/local/ffmpeg mkdir -p $INSTALL_DIR tar -xJf ffmpeg-release-amd64-static.tar.xz -C $INSTALL_DIR --strip-components1 ln -sf $INSTALL_DIR/ffmpeg /usr/local/bin/ffmpeg ln -sf $INSTALL_DIR/ffprobe /usr/local/bin/ffprobe第二层是把这个脚本里的url变量直接改成本地地址或镜像地址。脚本开头的INSTALL_DIR用了环境变量传参的方式我其实建议 URL 也改成同样的策略这样用的时候不用改脚本本体只要在命令行前面指定一下就行。第三层是如果公司有内网缓存服务就把 URL 指向内网速度会快很多。4.2 明明装好了ffmpeg 命令却不生效这类问题我在 Windows 上遇到的最多。Git Bash 里运行完脚本后马上敲ffmpeg -version有时候就是提示找不到命令。原因通常是两个一是当时这个终端会话的 PATH 还没刷新二是 Windows 的环境变量没广播到已经打开的终端。解决办法也不复杂一种是新开终端窗口再试一种是手动执行export PATH/usr/local/bin:$PATH刷新当前会话。另外要提醒的是在 Git Bash 里创建的软链接跟 Windows 系统的快捷方式不是一回事如果你想把 ffmpeg 加到 Windows 的全局 PATH 里必须在“系统属性 - 环境变量”里把对应的目录手动添加进去。脚本在 Git Bash 里运行只能保证 Git Bash 这个环境能用做不到修改 Windows 系统级的 PATH这个边界需要知道。还有一个小坑是在部分 Linux 系统上/usr/local/bin不在默认 PATH 里。虽然大多数发行版都会包含但我确实在某个精简版容器镜像里遇到过command -v ffmpeg找不到的情况。排查方式先echo $PATH看看有没有/usr/local/bin没有的话在~/.bashrc里加上一行export PATH/usr/local/bin:$PATH。4.3 不同系统下脚本的差异点速查我整理了一个表格方便你快速对比三个平台下这个脚本的行为差异项目LinuxmacOSWindowsGit Bash/WSL安装方式下载静态包并解压Homebrewwinget是否需要 root是否否安装位置/usr/local/ffmpegHomebrew 默认路径winget 默认路径验证方式ffmpeg -version formats同上同上升级方式重跑脚本覆盖目录brew upgrade ffmpegwinget upgrade这张表同时体现了脚本的一个设计取舍macOS 和 Windows 没有强制使用同一种方案。有人会问为什么不统一用静态包这样跨平台体验一致但 macOS 下 Homebrew 生态已经很成熟升级也方便再用静态包反而给自己增加维护负担Windows 下 winget 是微软官方的包管理器信任度高。脚本的核心目标是“收敛”不是“统一”在能借助平台原生能力的地方就借用这种思路后期维护起来更省心。5. 让脚本更适合你自己的环境5.1 加参数自定义安装目录和版本目前脚本用INSTALL_DIR环境变量来指定安装目录其实可以继续扩展成命令行参数模式比如-d /opt/ffmpeg、-v 6.1。版本选择这块John Van Sickle 的构建站同时也提供具体版本的目录比如ffmpeg-6.1-amd64-static.tar.xz如果你对版本有要求可以加一个FFMPEG_VERSION变量拼 URL 时调整一下。我这里默认用 release 包是因为它跟随最新稳定版日常使用中遇到 bug 的概率更低修复也更快。不过要留意一个东西静态包的文件名结构偶尔会变比如新增了ffmpeg-6.1.1-amd64-static.tar.xz这种带补丁号的格式。如果你的脚本硬编码了完整文件名源站改版后就会下载失败。所以我这里一直用release这个相对固定的命名尽量降低这种风险。这也算是一个“不要为了灵活性牺牲可维护性”的例子。5.2 集成到 CI/CD 流水线我用这个脚本最多的场景其实是 CI。在 GitHub Actions 或者 GitLab CI 里Runner 每次都是一台新的临时的机器需要有一个可靠的方式快速把 ffmpeg 装好。这个脚本的价值在 CI 里被放得很大不用维护 Docker 镜像不用在多个项目里复制粘贴安装文档直接一行bash install_ffmpeg.sh跑完就有一个可用的 ffmpeg后续的转码、抽帧、合成步骤都能继续。在 CI 里还有一个小技巧先ffmpeg -version看看 Runner 自带的环境里有没有 ffmpeg如果有且版本符合要求就跳过安装。这样可以省掉十几秒的安装时间。我在脚本里没写这个判断因为本地场景判断意义不大但在 CI 场景下是可以自己加一个前置条件的。5.3 离线部署时的兜底方案最后聊一个很多人问的场景内网离线服务器怎么装很多生产环境是物理隔离的没法直接访问外网。这个脚本在这种场景下直接跑是跑不通的我一般会配合一个本地文件服务器来做。操作方法是在一台能访问外网的机器上把对应平台的静态包下载好放到内网机器能访问的共享目录或者 HTTP 服务上然后修改脚本里的url变量指向内网地址再执行脚本。包的解压路径、软链接逻辑都不需要改唯一的区别就是下载源变了。推荐把url单独提出去用环境变量覆盖这样脚本完全不用动内网部署时只需FFMPEG_URLhttp://192.168.1.100/packages/ffmpeg-release-amd64-static.tar.xz \ bash install_ffmpeg.sh这个兜底方案看起来挺简单但确实解决了内网部署的最后一百米问题。没有这个逻辑的时候我在离线环境里只能用最原始的方式手动解压、手动复制、手写软链接每台机器重复一遍效率很低。实际用下来这个脚本已经陪我部署了不下五十台各种环境从最老的 CentOS 7 到 Ubuntu 22从 X86 服务器到 ARM 开发板基本没有出过岔子。最大的体会是写自动化脚本关键不是把代码写得多么华丽而是要想清楚每个平台差异背后“为什么这么设计”把这些决策沉淀成脚本里的一个分支、一个参数这才是脚本真正的价值。本文还有配套的精品资源点击获取