ffmpeg实现画中画必须用overlay滤镜,主视频需统一分辨率并pad填充,小窗须预缩放;坐标用w-w-20等表达式动态计算,时间控制用enable='gte(t,5)',帧率需统一,php调用时须escapeshellarg()、proc_open()和捕获stderr。

如何用 FFmpeg 命令行实现画中画(PIP)而不依赖 PHP 扩展
PHP 本身不处理视频,所谓“PHP+FFmpeg”实际是 PHP 调用 ffmpeg 命令行。画中画效果必须靠 FFmpeg 的 overlay 滤镜完成,不是靠 PHP 函数拼接或 GD 库渲染——这点很多人一开始就想错了。
常见错误现象:PHP Warning: exec() has been disabled 或执行后无输出、黑屏、主画幅被裁切。根本原因是滤镜链写错、时间基不匹配,或输入流分辨率/帧率未对齐。
- 主视频(背景)建议先用
ffmpeg -i main.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" -c:a copy main_720p.mp4统一分辨率 - 画中画小窗视频需提前缩放(如
scale=320:180),否则overlay会拉伸或溢出 - 务必加
-c:a copy避免重编码音频——否则转码极慢且可能音画不同步
overlay 滤镜的坐标和时间控制怎么写才不出错
overlay 的 x 和 y 是像素坐标,原点在左上角;但直接写死数值(如 overlay=100:100)极易导致小窗跑出画面,尤其当主视频宽高比变化时。更健壮的写法是用表达式动态计算:
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=320:180[fg]; [0:v][fg]overlay=x=W-w-20:y=H-h-20" -c:a copy output.mp4
其中 W/H 是主视频宽高,w/h 是小窗宽高,20 是右下角边距。注意:所有表达式必须用双引号包裹,且变量名大小写敏感。
- 如果小窗要从第 5 秒开始出现,用
overlay=enable='gte(t,5)',不能写成if或start - 想让小窗淡入?得额外加
fade=in:st=5:d=0.5到小窗流上,overlay本身不支持透明度动画 - 两路视频时间基不一致(如主视频 30fps、小窗 25fps)会导致卡顿——务必用
-r 30统一输出帧率
PHP exec() 调用时必须处理的三个底层细节
直接 exec("ffmpeg -i ...") 很危险:超时、路径空格、错误静默、资源泄漏都会发生。PHP 层不能只图省事。
- 输入路径含中文或空格?必须用
escapeshellarg()包裹,例如escapeshellarg('/path/to/主视频.mp4') - 务必设置超时(
stream_set_timeout($proc, 300))并捕获 stderr:2>&1重定向到 stdout,否则 FFmpeg 报错你完全看不到 - 不要用
shell_exec()——它会阻塞直到结束,大视频可能卡死整个 PHP 进程;改用proc_open()并实时读取输出流,方便前端显示进度
为什么用 PHP 写 FFmpeg 参数容易生成无效命令
FFmpeg 命令里大量使用单引号、双引号、方括号、等号,而 PHP 字符串拼接时引号嵌套极易出错。比如这个常见写法:"overlay=x='W-w-20':y='H-h-20'" 在 PHP 双引号中,$W 会被误解析为变量。
正确做法是全部用单引号定义字符串,变量单独拼接:'[1:v]scale=320:180[fg]; [0:v][fg]overlay=x=W-w-20:y=H-h-20' —— 注意这里没有 PHP 变量,所有动态值应在 shell 层用 escapeshellarg() 处理后再填入固定模板。
- 别在 PHP 里拼
-vf "...",而是把整个 filter_complex 当作一个不可分割的字符串参数传入 - Windows 下路径分隔符用
/而非\,FFmpeg 自己认得;但 PHP 的realpath()返回的是\,必须替换 - 输出目录不存在?FFmpeg 不会自动创建,PHP 层得先
mkdir(),否则静默失败
画中画真正难的不是命令怎么写,而是每一帧的像素对齐、时间戳同步、以及错误时如何快速定位是滤镜语法错、路径错,还是权限错——这些全藏在 stderr 里,漏看一行就白调半小时。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











