video-use:视频处理全链路命令行工具集实战指南

发布时间:2026/9/26 13:48:38
video-use:视频处理全链路命令行工具集实战指南 1. 项目概述一个围绕视频处理全链路的实战型工具集命名“video-use”这个名字乍看简单甚至有点像随手起的临时文件夹名但恰恰是这种极简命名暴露了它背后的真实定位——它不是某个具体功能模块而是一套面向视频内容创作者、自动化脚本开发者和轻量级媒体工程人员的标准化操作入口。我第一次在团队内部看到这个目录时它下面已经塞满了十几个 shell 脚本、Python 小工具和配置模板从 YouTube 视频批量下载、格式转码、字幕提取到语音合成驱动画面、动态图文生成再到最终推流发布整条链路都用统一的命名规范、参数结构和错误处理逻辑串了起来。核心关键词 video-use 不是功能描述词而是操作动词 对象的组合体video 是领域use 是动作——强调“拿来即用、快速调用、可组合、可复用”。这和 ffmpeg、yt-dlp、elevenlabs、remotion 这些工具的定位高度一致它们都不是“开箱即用”的成品软件而是可编程的媒体能力积木。ffmpeg 是底层编解码与流处理的肌肉yt-dlp 是网络视频资源抓取的触手elevenlabs 提供高质量语音合成的声带remotion 则是把静态设计变成动态视频的画笔。video-use 就是把这四块积木拧在一起的那把多功能扳手——它不替代任何一块但让它们能严丝合缝地协同工作。适合谁不是给只想点一下就导出MP4的普通用户而是给那些每天要处理几十条短视频素材、需要批量重制封面、自动加配音、统一水印、适配不同平台分辨率的运营同学是给想用 Python 写个定时任务凌晨三点自动下载昨日热门视频并生成摘要短视频的技术型内容编辑也是给刚学完 FFmpeg 基础命令、正卡在“怎么把 yt-dlp 下来的 m3u8 流无损转成 H.265 MP4 并保留原始音轨”这种具体问题上的入门者。它解决的不是“能不能做”而是“要不要每次重写一遍同样的参数组合、路径拼接和错误判断逻辑”。2. 整体架构设计为什么不用 GUI 工具而坚持命令行脚本化2.1 四大工具的职责边界与协作逻辑很多人一看到 video-use 就下意识觉得“是不是又一个封装了 yt-dlp 和 ffmpeg 的图形界面下载器”——这是最大的误解。video-use 的设计哲学是从第一天就拒绝 GUI 封装。原因很实在GUI 工具在单次、手动、探索性操作中体验好但在重复、批量、嵌入工作流、需要条件判断和状态追踪的场景下会迅速成为瓶颈。举个真实例子某知识类账号每周要处理 30 条讲师录播课每条课需完成 5 步① 从私有链接下载yt-dlp② 提取音频并降噪ffmpeg noisereduce③ 用 elevenlabs 合成课程简介旁白④ 用 remotion 渲染带讲师头像文字标题的片头⑤ 将片头与原视频拼接并推流到内部 SRS 服务器。如果用 GUI 工具每一步都要人工点击、等待、确认、再切换窗口——30 条就是 150 次重复操作出错率高无法记录过程日志更没法在某一步失败后自动重试。而 video-use 的做法是把这 5 步写成一个 YAML 配置文件定义输入 URL、输出路径、降噪强度、语音角色、片头模板 ID、推流地址等参数然后执行一条命令video-use process --config course_weekly_202406.yaml。整个流程全自动跑完失败时精确报错到第 3 步elevenlabs API 调用超时并生成 debug 日志供排查。这种能力GUI 工具根本做不到。四大工具在 video-use 中的分工非常清晰不是简单堆砌而是按数据流分层yt-dlp 层获取层只负责“把视频资源拿到本地”。它不处理格式、不修改内容、不关心后续用途。video-use 对它的调用严格限定在--no-part --no-cache-dir --restrict-filenames --write-info-json --write-thumbnail等基础安全参数上并强制指定-o %(title)s.%(ext)s输出命名规则确保后续所有脚本都能通过文件名稳定识别输入源。我们曾测试过直接用浏览器下载或第三方下载插件结果因文件名含特殊字符如:/*导致 ffmpeg 解析失败而 yt-dlp 的--restrict-filenames参数就是为这种生产环境兜底的。ffmpeg 层处理层承担所有“像素与波形”的硬核操作。它被 video-use 拆解为多个原子命令extract-audio分离音轨、reencode-videoH.264/H.265 转码、crop-resize智能裁切缩放、add-watermark时间戳水印、concat-videos无黑场拼接。每个原子命令都是独立可测试的 shell 函数接受标准化输入本地文件路径和输出新文件路径中间不依赖全局变量。比如reencode-video函数内部会根据输入视频的原始编码通过ffprobe -v quiet -show_entries streamcodec_name -of csvp0 input.mp4获取决定是否跳过转码避免无谓的 CPU 消耗对 H.265 源视频优先使用libx265编码器并启用--preset slow保证质量对老旧设备兼容需求则强制libx264profile:v baseline。这种细粒度控制GUI 工具的预设档位根本覆盖不了。elevenlabs 层生成层专注“声音内容”的程序化生成。video-use 不把它当作“配音工具”而是当成一个 RESTful 音频服务端点。所有文本输入都经过预处理去除多余空格、替换常见缩写如 “AI” → “A.I.” 避免发音错误、按语义停顿插入 SSML 标签break time500ms/。调用时固定使用voice_idEXAVITQu4vr4K3MDaWkZ其官方推荐的清晰男声和model_ideleven_multilingual_v2多语言支持并设置stability0.5/similarity_boost0.75这组实测最平衡的参数组合——太高会导致机械感太低则发音不准。生成的 MP3 文件名严格按input_basename_voice.mp3命名与视频文件形成天然关联remotion 渲染时可直接引用。remotion 层合成层解决“视觉表达”的动态化问题。video-use 不直接调用 remotion CLI而是将其打包为一个 Node.js 子进程管理器。关键在于 template 的抽象每个 remotion 项目都被封装为一个独立 npm 包如video-use/template-intro包含src/index.tsx主渲染逻辑、src/data.json可配置参数 schema和package.json版本与依赖。video-use 通过npm install video-use/template-intro1.2.0安装指定版本再读取data.json获取该模板支持的参数如title,speakerName,durationSec最后用npx remotion render命令传入这些参数生成 MP4。这样做的好处是模板升级不影响 video-use 主干代码不同项目可共用同一套渲染基础设施甚至能用remotion preview在本地启动调试服务器实时查看参数变化效果——这是纯命令行工具无法提供的开发体验。2.2 为什么选择 Bash Python 混合而非单一语言video-use 的核心脚本是 Bash 写的video-use.sh但关键业务逻辑如 JSON 配置解析、API 调用、日志聚合用 Python 实现lib/core.py。这个混合架构不是技术炫技而是基于多年踩坑经验的务实选择Bash 的不可替代性它天生就是 Unix/Linux 系统的“胶水语言”。ffmpeg、yt-dlp、git、curl 这些命令行工具Bash 调用起来零成本、无依赖、启动快。一个ffmpeg -i $input -c:v libx264 -crf 23 $output命令在 Bash 里就是一行在 Python 里得用subprocess.run()还要处理 shell 字符转义、编码、信号传递等问题。更重要的是Bash 的管道|和重定向机制让日志收集、错误捕获变得极其简洁。比如yt-dlp ... 21 | tee $log_file一行就搞定输出捕获Python 里得写十几行才能等效。Python 的必要性当逻辑复杂到需要 JSON 解析、HTTP 请求、条件分支嵌套、异常分类处理时Bash 就力不从心了。比如 elevenlabs 的 API 调用需要构造带 Authorization Header 的 POST 请求解析返回的{audio: base64...}再 base64 decode 写入文件。Bash 做这些要么依赖外部工具jq,curl,base64要么写一堆脆弱的字符串操作Python 用requests和json库三五行就搞定且类型安全、可单元测试。video-use 的core.py里所有 API 调用都封装成带重试tenacity库、超时timeout30、错误码映射429 → rate_limit_exceeded的健壮函数这是 Bash 几乎不可能做到的。混合的实践技巧我们约定所有 Python 模块必须是“纯函数式”的——不读写全局状态输入为 dict 或 str输出为 dict 或 bool。Bash 脚本只负责“调度”解析命令行参数getopts设置环境变量export VIDEO_USE_CONFIG_PATH...调用 Python 函数python -m lib.core process_config $config_path然后根据 Python 返回的 exit code 决定下一步成功则继续失败则打印core.py返回的详细错误信息。这种隔离让 Python 代码可以独立测试pytest tests/test_core.pyBash 脚本也保持轻量。曾有人提议全用 Python 重写但我们实测发现一个纯 Python 的 video-use 启动时间比 Bash 版慢 300ms主要花在 import 上对于高频调用的场景如 CI/CD 中每分钟触发一次这点延迟会累积成可观的资源浪费。2.3 配置驱动 vs 硬编码如何让同一套代码适配不同业务线video-use 的生命力来自于它彻底抛弃了“为 A 业务写一套、为 B 业务再写一套”的模式全部交由配置驱动。核心配置文件是 YAML 格式config.yaml结构分三层# 全局配置影响所有任务 global: cache_dir: /tmp/video-use-cache log_level: INFO timeout_sec: 300 # 工具配置各工具的连接参数 tools: yt-dlp: cookies_file: ~/.yt-dlp/cookies.txt proxy: null # 显式设为 null 表示不走代理 elevenlabs: api_key: sk-xxx # 生产环境从环境变量读取 remotion: render_concurrency: 2 # 控制并发渲染数防内存溢出 # 任务配置具体要执行的操作 tasks: - name: weekly-course-intro type: composite input: url: https://example.com/course.mp4 title: 机器学习入门 steps: - action: download tool: yt-dlp - action: extract-audio tool: ffmpeg params: { codec: libmp3lame, bitrate: 128k } - action: synthesize-voice tool: elevenlabs params: { voice_id: EXAVITQu4vr4K3MDaWkZ } - action: render-intro tool: remotion params: { template: video-use/template-intro1.2.0, duration: 5 } - action: concat tool: ffmpeg params: { order: [intro.mp4, course.mp4] }这个结构的设计解决了三个关键问题环境隔离global.cache_dir可根据不同服务器设置为/mnt/fast-ssd/cache或/home/user/.cache/video-use无需改代码tools.elevenlabs.api_key在 CI 环境中从SECRETS_ELEVENLABS_KEY环境变量注入本地开发用~/.video-use/secrets.yaml加载完全解耦。流程复用tasks下可以定义多个任务共享同一套global和tools配置。运营同学只需复制weekly-course-intro任务块改name和input.url就能复用全部处理逻辑。我们有个客户用这套配置同时管理教育、电商、游戏三个频道的视频处理共用 90% 的代码仅维护 3 份不同的config.yaml。灰度发布steps中的action是 video-use 内置的原子操作名如download,reencode-video每个 action 对应一个 Bash 函数。当需要升级 ffmpeg 转码逻辑时只需更新lib/ffmpeg.sh中的reencode-video函数所有引用它的任务自动生效无需逐个修改配置。更进一步我们支持action: reencode-videov2这种带版本号的调用让新旧逻辑并存逐步迁移。提示YAML 配置不是万能的。我们明确规定所有涉及密码、密钥、内部 API 地址的敏感字段必须从环境变量读取配置文件中只留占位符。例如api_key: ${ELEVENLABS_API_KEY}启动时由 Bash 的envsubst命令替换。这避免了密钥误提交到 Git 仓库的风险——我们曾因一个同事忘记.gitignore里的secrets.yaml导致 API Key 泄露从此所有敏感项强制环境变量化。3. 核心工具深度解析与实操要点3.1 yt-dlp不只是下载器更是视频元数据采集器yt-dlp 的价值常被低估——大家只看到它能下载 YouTube 视频却忽略了它强大的元数据提取能力。video-use 中yt-dlp的首要任务不是“得到视频文件”而是“得到关于视频的完整信息”。我们几乎从不直接调用yt-dlp -o out.mp4 URL而是固定使用这一组参数yt-dlp \ --no-part \ --no-cache-dir \ --restrict-filenames \ --write-info-json \ --write-thumbnail \ --skip-download \ --print id:%(id)s,title:%(title)s,uploader:%(uploader)s,upload_date:%(upload_date)s,duration:%(duration)s \ $url拆解每个参数的生产意义--no-part禁用.part临时文件。在 NFS 或网络存储上.part文件可能因权限问题无法原子重命名导致下载中断后残留垃圾文件。--no-cache-dir关闭 yt-dlp 自身的缓存。video-use 统一用global.cache_dir管理所有中间文件避免多处缓存造成空间浪费和清理混乱。--restrict-filenames强制将文件名转换为 ASCII 字符。这是跨平台Linux/macOS/Windows WSL兼容的基石。没有它yt-dlp下载C 教程.mp4会生成C 教程.mp4而某些旧版 ffmpeg 会因字符解析失败。--write-info-json生成video_id.info.json文件包含 200 个字段如formats所有可用码率列表、chapters章节时间戳、subtitles字幕 URL。video-use 的extract-subtitles功能就依赖此文件中的subtitles.en.vtt字段。--write-thumbnail下载缩略图通常是 JPG。很多业务需要封面图做海报直接用此图省去额外截图步骤。--skip-download关键先不下载视频主体只获取元数据。video-use 会先解析info.json判断哪个 format 最合适如选height1080且acodec!none的 DASH 流再针对性下载避免下载完整 4K 视频后才发现只需要 720p 音频。--print参数是精髓所在。它让 yt-dlp 直接输出一行结构化文本如id:abc123,title:FFmpeg实战指南,uploader:TechMaster,upload_date:20240601,duration:1245Bash 脚本用IFS, read -r id title uploader upload_date duration $(yt-dlp --print ...)即可安全分割赋值比解析 JSON 更快更轻量。这个技巧让我们在批量处理 100 个 URL 时元数据获取阶段提速 40%。注意yt-dlp 的--proxy参数在企业环境中极易引发问题。我们明确规定所有代理配置必须通过环境变量HTTPS_PROXY设置而非 yt-dlp 命令行参数。因为 yt-dlp 会把--proxy透传给底层urllib3而某些内网代理要求特定认证头HTTPS_PROXY能被更底层的库正确处理。曾有个客户在阿里云 ECS 上配置--proxy http://proxy.internal:8080结果 yt-dlp 报Connection refused换成export HTTPS_PROXYhttp://proxy.internal:8080后立即正常——这是底层网络栈的差异命令行参数无法覆盖。3.2 ffmpeg从“万能命令”到“精准手术刀”ffmpeg 常被戏称为“Linux 下的瑞士军刀”但 video-use 的理念是不要用瑞士军刀削苹果要用专业水果刀。我们把 ffmpeg 的海量功能提炼为 7 个高频、安全、可预测的原子操作并为每个操作固化最佳实践参数。这不是限制能力而是降低出错概率。3.2.1extract-audio分离音轨的黄金参数目标从视频中无损提取音频保留原始采样率、声道数、编码格式AAC/MP3/Opus。错误做法ffmpeg -i input.mp4 -q:a 0 -map a output.mp3问题-q:a 0是 VBR 最高质量但对 AAC 编码无效-map a可能选错音轨多音轨视频未指定采样率可能导致重采样失真。video-use 的标准命令ffmpeg -i $input \ -vn \ # 禁用视频流避免解码视频浪费 CPU -c:a copy \ # 直接拷贝音频流零失真 -map 0:a:0 \ # 明确指定第一个音频流索引 0 $output-vn是关键它告诉 ffmpeg “别碰视频”解码器只加载音频解码器CPU 占用直降 70%。-c:a copy实现真正的“无损提取”比特率、采样率、帧结构完全不变。只有当目标格式不支持原始编码如提取 AAC 到 WAV时才启用重编码-c:a pcm_s16le -ar 44100 -ac 2。-map 0:a:0消除歧义。yt-dlp下载的 DASH 流常含多个音轨主音轨、评论音轨、描述音轨-map a会随机选一个而0:a:0指向容器中第一个音频流稳定可靠。3.2.2reencode-videoH.264/H.265 转码的理性选择目标将任意源视频转为指定分辨率、码率、编码器的 MP4兼顾质量与体积。核心原则不做无谓转码。video-use 先用ffprobe检查源视频# 获取原始编码和分辨率 codec$(ffprobe -v quiet -show_entries streamcodec_name -of csvp0 $input) width$(ffprobe -v quiet -show_entries streamwidth -of csvp0 $input) height$(ffprobe -v quiet -show_entries streamheight -of csvp0 $input)然后决策若codec h264且width 1280 height 720直接cp $input $output跳过转码。若需转码优先选libx264兼容性最好或libx265体积小 40%但编码慢 3 倍。H.264 推荐参数ffmpeg -i $input \ -c:v libx264 \ -crf 23 \ # CRF 23 是视觉无损与体积的甜点18-28 范围 -preset medium \ # 平衡速度与压缩率 -profile:v baseline \ # 强制 baseline profile确保老设备播放 -c:a aac -b:a 128k \ # 音频用 AAC固定码率 -vf scale1280:720:force_original_aspect_ratiodecrease,pad1280:720:(ow-iw)/2:(oh-ih)/2 \ # 智能缩放居中填充 $output-crf 23是实测最优值CRF 18 质量提升微乎其微文件大 35%CRF 28 开始出现明显块状模糊。-profile:v baseline是移动端兼容的关键。很多安卓机不支持main或highprofile强制 baseline 后 100% 兼容。scale...pad...滤镜链实现“保持宽高比缩放 黑边填充”比简单scale1280:720更专业。H.265 推荐参数需 ffmpeg 4.0ffmpeg -i $input \ -c:v libx265 \ -crf 28 \ # H.265 的 CRF 比 H.264 高 5同等质量 -preset slow \ # 慢速预设提升压缩率 -x265-params level-idc4.0:repeat-headers1 \ # 强制 Level 4.0兼容主流设备 -c:a aac -b:a 128k \ $output-crf 28对应 H.264 的 23实测体积小 38%主观质量无差异。-x265-params level-idc4.0是重点。H.265 默认 Level 可能过高如 5.1导致部分播放器报错显式设为 4.0支持 1080p30fps确保兼容。3.2.3add-watermark时间戳水印的工业级实现目标在视频右下角添加半透明文字水印内容为当前时间格式2024-06-01 14:23:05且随视频播放实时更新。错误做法用drawtext滤镜写死时间text2024-06-01水印变成静态。video-use 的方案ffmpeg -i $input \ -vf drawtextfontfile/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf: \ fontsize24:fontcolorwhite0.8:x(w-tw)/10:yh-th-10: \ text%{localtime\:%Y-%m-%d %H\\:%M\\:%S}: \ box1:boxcolorblack0.5 \ -c:a copy $output%{localtime\:%Y-%m-%d %H\\:%M\\:%S}是 ffmpeg 的时间变量\:中的反斜杠用于转义冒号否则被解析为滤镜分隔符。x(w-tw)/10将水印放在右边缘 1/10 处yh-th-10距底边 10 像素避免遮挡字幕。fontcolorwhite0.8设置白色半透明80% 不透明度boxcolorblack0.5添加黑色半透明背景框提升文字可读性。-c:a copy保持音频流不变节省时间。实操心得字体文件路径/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf是 Debian/Ubuntu 的默认路径。CentOS/RHEL 系统需改为/usr/share/fonts/dejavu/DejaVuSans.ttf。video-use 在启动时会检测字体是否存在不存在则自动下载并缓存避免因字体缺失导致命令失败——这是很多教程忽略的细节。3.3 elevenlabs语音合成的稳定性保障策略elevenlabs 的 API 调用看似简单但在生产环境中网络抖动、限流、token 过期等问题频发。video-use 不满足于“调通就行”而是构建了一套容错体系。3.3.1 API 调用的三层防护客户端限流video-use 使用tenacity库实现指数退避重试retry( stopstop_after_attempt(3), waitwait_exponential(multiplier1, min1, max10), retryretry_if_exception_type((requests.exceptions.RequestException, ValueError)) ) def call_elevenlabs(text, voice_id): # 实际 API 调用第一次失败后等 1 秒第二次失败等 2 秒第三次失败等 4 秒避免雪崩。服务端限流应对elevenlabs 的免费 tier 有 10k 字符/月限制。video-use 在调用前检查text长度若超限则自动分段按句号/问号/感叹号分割每段单独调用并合并音频。合并用 ffmpeg 的concat协议# 创建 concat.txt echo file part1.mp3 concat.txt echo file part2.mp3 concat.txt ffmpeg -f concat -safe 0 -i concat.txt -c copy output.mp3缓存机制相同文本 相同 voice_id 的请求结果缓存在global.cache_dir/elevenlabs/下文件名用sha256(text voice_id)哈希避免重复调用。缓存有效期设为 30 天兼顾新鲜度与效率。3.3.2 音频质量的精细调控elevenlabs 的stability和similarity_boost参数组合直接影响语音自然度。我们通过 A/B 测试确定了最佳区间stabilitysimilarity_boost效果适用场景0.30.9声音非常稳定但略显机械会议纪要、新闻播报0.50.75平衡自然与清晰推荐值课程讲解、产品介绍0.70.5富有情感起伏但偶有发音不准故事讲述、广告配音video-use 默认采用0.5/0.75组合并允许在配置中覆盖steps: - action: synthesize-voice params: { stability: 0.7, similarity_boost: 0.5 }注意elevenlabs 的model_id选择至关重要。eleven_monolingual_v1仅支持英语eleven_multilingual_v2支持 29 种语言但英语发音稍逊。video-use 的默认配置是eleven_multilingual_v2因为业务常需中英混杂内容如 “TensorFlow 的tf.keras模块”。若纯英文场景可显式指定model_id: eleven_monolingual_v1获得更佳效果。3.4 remotion动态视频生成的工程化实践remotion 的强大在于 React TypeScript 的开发体验但 video-use 关注的是如何把它变成一个可靠的“视频工厂”。核心挑战是如何让设计师写的 React 组件变成运维同学能一键渲染的标准化服务3.4.1 模板的工程化封装video-use 要求所有 remotion 模板必须遵循统一结构video-use/template-intro/ ├── package.json # name, version, dependencies ├── src/ │ ├── index.tsx # default export 必须是 RemotionVideo component │ ├── data.json # JSON Schema定义可配置参数 │ └── assets/ # 图片、字体等静态资源 └── README.md # 模板说明、参数示例data.json示例{ title: { type: string, description: 视频标题, default: Hello World }, speakerName: { type: string, description: 讲师姓名, default: 张老师 }, durationSec: { type: number, description: 视频时长秒, default: 5, minimum: 3, maximum: 10 } }video-use 的render-intro步骤会读取data.json验证配置中title等字段是否存在且符合类型生成src/data.ts文件内容为export const config { title: 机器学习入门, speakerName: 李教授, durationSec: 5 };执行npx remotion render --concurrency2 --outputintro.mp4 src/index.tsx。这样设计师只需维护src/index.tsx运营同学只需改 YAML 配置双方零耦合。3.4.2 渲染性能的硬核优化remotion 渲染慢是公认痛点。video-use 通过三招提速硬件加速强制使用--gpu参数macOS或--enable-gpuLinux利用 GPU 解码/编码。测试显示开启 GPU 后 1080p 渲染速度提升 3.2 倍。并发控制tools.remotion.render_concurrency参数限制同时渲染的实例数。一台 32GB 内存的服务器设为 2 最稳设为 4 时常因 OOM 被系统 kill。缓存复用remotion 的--cache-dir指向global.cache_dir/remotion/相同组件的相同 props 渲染结果会被缓存二次渲染秒出。实操心得remotion 的--browser-executable参数常被忽略。在无图形界面的服务器如 AWS EC2上必须指定 Chrome 二进制路径否则渲染失败。video-use 自动检测google-chrome或chromium-browser是否存在不存在则提示安装apt install chromium-browser。我们还提供video-use setup-chrome命令一键下载并配置 Chromium省去运维麻烦。4. 完整实操流程从零开始搭建一个“课程视频自动加工流水线”4.1 环境准备最小化依赖安装video-use 的设计原则是“尽可能少依赖”但以下四项是硬性要求Python 3.8用于核心逻辑。推荐用pyenv管理版本避免系统 Python 冲突。curl https://pyenv.run | bash # 添加到 ~/.bashrc export PYENV_ROOT$HOME/.pyenv command -v pyenv /dev/null || export PATH$PYENV_ROOT/bin:$PATH eval $(pyenv init -) # 安装并设为全局 pyenv install 3.11.9 pyenv global 3.11.9ffmpeg 4.4必须包含libx264,libx265,libvpx编码器。强烈建议从官网下载静态编译版而非apt install ffmpegUbuntu 22.04 的 ffmpeg 版本太旧缺 H.265 支持。wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-git-amd64-static.tar.xz tar -xf ffmpeg-git-amd64-static.tar.xz sudo cp ffmpeg-git-*/ffmpeg /usr/local/bin