
本文详解如何在 php 调用 ffmpeg 转换视频(如 mp4)的同时,精准叠加公司 logo 作为水印,涵盖坐标定位、尺寸适配、格式兼容及生产环境注意事项。
本文详解如何在 php 调用 ffmpeg 转换视频(如 mp4)的同时,精准叠加公司 logo 作为水印,涵盖坐标定位、尺寸适配、格式兼容及生产环境注意事项。
在视频转码流程中嵌入品牌 Logo 是提升专业性与版权保护的关键一步。FFmpeg 提供了强大且灵活的 overlay 滤镜实现该功能,而 PHP 可通过 exec() 安全调用完成自动化集成。以下为完整、可落地的技术方案。
✅ 核心原理:双输入 + filter_complex 处理流
FFmpeg 不支持直接“编辑”视频文件,而是通过多输入流(主视频 + Logo 图片)+ 复杂滤镜链(filter_complex)合成输出。关键点包括:
- 输入顺序决定索引:-i video.mp4 → [0:v](主视频流),-i logo.png → [1:v](Logo 视频流)
- overlay 滤镜控制位置(x, y)、像素格式(推荐 format=yuv420 保证 H.264 兼容性)
- 必须显式映射音视频流:-map 0:a(保留原音频),-map [out](输出合成后的视频流)
?️ 推荐命令(带自适应缩放,生产首选)
假设您的 Logo 需固定显示在右下角(距右边缘 20px、底边 20px),并按视频宽度的 15% 自适应缩放:
ffmpeg -i "original/input.mp4" -i "logo-whiteb.png" \
-filter_complex \
"[1:v]scale=w='iw*0.15':h=-1:force_original_aspect_ratio=decrease[logo]; \
[0:v][logo]overlay=x=W-w-20:y=H-h-20:format=yuv420[out]" \
-map 0:a -map [out] \
-c:v libx264 -crf 23 -preset medium \
-c:a aac -b:a 128k \
-y "converted/output.mp4"? 说明:
立即学习“PHP免费学习笔记(深入)”;
- scale=w='iw*0.15':h=-1:Logo 宽度设为原视频宽度(iw)的 15%,高度等比缩放
- overlay=x=W-w-20:y=H-h-20:W/H 是主视频宽高,w/h 是缩放后 Logo 宽高,实现动态右下角定位
- -crf 23 -preset medium:平衡画质与编码速度(生产环境推荐)
? PHP 集成示例(安全增强版)
<?php
$uploads_dir = 'original/';
$output_dir = 'converted/';
$file_name = basename($_FILES['file']['name']);
$output_name = pathinfo($file_name, PATHINFO_FILENAME);
$uploaded_file = $uploads_dir . $file_name;
$logo_path = 'https://propeview.com/wp-content/uploads/2021/08/logo-whiteb.png'; // ⚠️ 注意:需先下载到本地!
$local_logo = 'assets/logo-whiteb.png';
// 1. 下载远程 Logo(仅首次或定期更新,避免每次请求)
if (!file_exists($local_logo)) {
file_put_contents($local_logo, file_get_contents($logo_path));
}
if (isset($_POST['submit']) && move_uploaded_file($_FILES['file']['tmp_name'], $uploaded_file)) {
$ffmpeg = '/usr/bin/ffmpeg'; // ✅ 务必用绝对路径,并确认权限(chmod +x)
$output_mp4 = $output_dir . $output_name . '.mp4';
// 构建命令(注意 shell 字符转义)
$cmd = escapeshellcmd(
"$ffmpeg -i " . escapeshellarg($uploaded_file) .
" -i " . escapeshellarg($local_logo) .
" -filter_complex " . escapeshellarg(
"[1:v]scale=w='iw*0.15':h=-1:force_original_aspect_ratio=decrease[logo];" .
"[0:v][logo]overlay=x=W-w-20:y=H-h-20:format=yuv420[out]"
) .
" -map 0:a -map [out]" .
" -c:v libx264 -crf 23 -preset medium" .
" -c:a aac -b:a 128k" .
" -y " . escapeshellarg($output_mp4)
);
exec($cmd . " 2>&1", $output, $return_code);
if ($return_code === 0) {
echo "✅ 水印视频已生成:<a href='$output_mp4'>$output_mp4</a>";
} else {
error_log("FFmpeg failed: " . implode("\n", $output));
echo "❌ 转码失败,请检查 convert.txt 或错误日志。";
}
}
?>⚠️ 关键注意事项
- Logo 必须本地化:ffmpeg -i 不支持直接读取 HTTP URL(除非编译时启用 libcurl 且版本 ≥ 4.3)。务必提前下载并验证 PNG 透明通道是否保留。
- 路径与权限:确保 PHP 进程对 ffmpeg 二进制、输入/输出目录有读写执行权限;使用 escapeshellarg() 防止命令注入。
- 性能优化:大视频建议异步处理(如队列 + Supervisor),避免 Web 请求超时;可先用 ffprobe 获取分辨率再动态计算 x/y。
- 透明背景支持:PNG 必须含 Alpha 通道,且 FFmpeg 编译需支持 png 解码器(默认开启)。
✅ 总结
添加水印不是简单追加参数,而是理解 FFmpeg 的流处理模型。通过 filter_complex 组合 scale 与 overlay,配合 PHP 的安全调用封装,即可稳定实现品牌露出。始终优先测试单条命令行,再集成至脚本——这是规避 90% 问题的黄金法则。











