
本文详细讲解如何在 php 中调用 ffmpeg,将公司 logo(如 png 图片)作为水印叠加到 mp4 视频上,涵盖位置控制、尺寸适配、色彩空间兼容性及安全执行要点。
本文详细讲解如何在 php 中调用 ffmpeg,将公司 logo(如 png 图片)作为水印叠加到 mp4 视频上,涵盖位置控制、尺寸适配、色彩空间兼容性及安全执行要点。
在视频转码流程中嵌入品牌标识(如 Logo 或半透明水印),是提升内容版权保护与品牌曝光的关键实践。FFmpeg 提供了强大且灵活的 overlay 滤镜,配合 scale 可实现任意尺寸 Logo 的精准叠加。以下教程基于您现有的 PHP 视频转换逻辑进行增强,确保水印稳定、清晰、跨分辨率兼容。
✅ 基础水印命令结构解析
核心命令由三部分组成:
- 双输入:主视频(-i video.mp4) + Logo 图片(-i logo.png);
- 滤镜链:通过 -filter_complex 组合 scale(可选)和 overlay;
- 流映射:显式指定音频(-map 0:a)与处理后的视频流(-map [out]),避免音频丢失。
⚠️ 关键注意:必须使用 format=yuv420 参数——因大多数 PNG 含 alpha 通道(RGBA),而 H.264 编码默认不支持 RGB/YUV444,强制转为 yuv420 可确保兼容性与播放稳定性。
? 示例代码(含 Logo 叠加的完整 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'; // 远程 URL 需先下载为本地文件
$local_logo = 'assets/logo-whiteb.png'; // 推荐:提前下载并存放于服务器本地(提升性能 & 避免网络失败)
// ✅ 安全前提:验证上传文件 & 下载 Logo(仅首次)
if (isset($_POST['submit']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
if (!move_uploaded_file($_FILES['file']['tmp_name'], $uploaded_file)) {
die("文件上传失败");
}
// 下载远程 Logo(生产环境建议改用 CDN 本地缓存或预置路径)
if (!file_exists($local_logo)) {
file_put_contents($local_logo, file_get_contents($logo_path));
}
$ffmpeg = '/usr/bin/ffmpeg'; // ✅ 务必用 `which ffmpeg` 确认真实路径,避免权限/找不到问题
$output_mp4 = $output_dir . $output_name . '.mp4';
// ? 核心命令:叠加 Logo 到左上角(x=0,y=0),自动适配视频尺寸,保留原音频
$cmd = sprintf(
'%s -i "%s" -i "%s" -filter_complex "[1:v]scale=w=iw*0.15:h=ih*0.15:force_original_aspect_ratio=decrease[logo]; [0:v][logo]overlay=x=20:y=20:format=yuv420[out]" -map 0:a -map "[out]" -c:v libx264 -c:a aac -y "%s" 2>&1',
escapeshellarg($ffmpeg),
escapeshellarg($uploaded_file),
escapeshellarg($local_logo),
escapeshellarg($output_mp4)
);
// ✅ 安全执行:禁用 shell 元字符注入,捕获完整错误日志
exec($cmd, $output, $return_code);
if ($return_code !== 0) {
error_log("FFmpeg failed: " . implode("\n", $output));
echo "<p>❌ 转码+水印失败,请检查 convert.log</p>";
} else {
echo "<p>✅ 已生成带水印视频:<a href='{$output_mp4}'>{$output_mp4}</a></p>";
}
}
?>? 关键配置说明与最佳实践
| 项目 | 推荐做法 | 说明 |
|---|---|---|
| Logo 尺寸缩放 | scale=w=iw*0.15:h=ih*0.15:force_original_aspect_ratio=decrease | 按视频宽高的 15% 自适应缩放,保持比例,避免拉伸变形 |
| 水印位置 | overlay=x=20:y=20 | 距左上角 20px,避免遮挡关键画面;支持 x='w-w/5':y='h-h/5' 等表达式实现右下角定位 |
| 透明度控制 | 在 overlay 后追加 enable='between(t,5,30)' | 仅在第 5–30 秒显示水印(进阶用法);若需淡入淡出,需结合 fade 滤镜 |
| 错误处理 | 始终检查 $return_code 并记录 $output | FFmpeg 错误信息全部输出到 stderr,2>&1 确保捕获完整日志 |
| 安全性 | 严格使用 escapeshellarg() 包裹所有路径变量 | 防止恶意文件名导致命令注入(如 ; rm -rf /) |
? 进阶提示
-
批量分析源视频:对不确定分辨率的输入,建议先用 ffprobe 获取宽高:
ffprobe -v quiet -show_entries stream=width,height -of csv=p=0 input.mp4
再动态生成 scale 参数,实现真正响应式水印。
立即学习“PHP免费学习笔记(深入)”;
- 多水印支持:可在同一 filter_complex 中叠加多个 [1:v], [2:v] 输入,分别缩放+定位。
- 硬件加速(可选):如服务器支持 NVENC,可替换 -c:v libx264 为 -c:v h264_nvenc 加速处理。
通过以上方案,您不仅能稳定地为每个转码视频添加专业级 Logo 水印,还能兼顾性能、安全与可维护性。记住:一次正确配置,千次可靠执行。











