目录

使用ffmpeg叠加视频

使用ffmpeg叠加视频

使用 FFmpeg 的滤镜功能来实现视频叠加和参数调整。

版本要求

请确保 FFmpeg 版本 ≥ 4.0。

参数说明

参数名称作用
背景视频作为背景的视频文件
上层视频叠加在上层的视频文件
上层宽度上层视频的宽度(高度按比例自适应)
时间偏移上层视频从第几秒开始显示
透明度上层视频的透明度(0.0 完全透明,1.0 完全不透明)
x比例上层视频的水平位置比例(0=左侧,1=右侧,0.5=居中)
y比例上层视频的垂直位置比例(0=顶部,1=底部,0.5=居中)
输出文件名最终生成的视频文件名

运行示例

假设:

  • 背景视频: <font style="color:rgb(64, 64, 64);">background.mp4</font>
  • 上层视频: <font style="color:rgb(64, 64, 64);">input1.mp4</font>
  • 上层宽度: <font style="color:rgb(64, 64, 64);">640</font> (宽度640,高度按比例自适应)
  • 时间偏移: <font style="color:rgb(64, 64, 64);">5</font> (从第5秒开始显示上层视频)
  • 透明度: <font style="color:rgb(64, 64, 64);">0.5</font> (50%透明度)
  • x比例: <font style="color:rgb(64, 64, 64);">0.5</font> (水平居中)
  • y比例: <font style="color:rgb(64, 64, 64);">0.2</font> (垂直位置在顶部20%处)
  • 输出文件名: <font style="color:rgb(64, 64, 64);">output.mp4</font>

./merge_videos.sh background.mp4 input1.mp4 640 5 0.5 0.5 0.2 output.mp4

脚本逻辑详解

  1. 位置比例计算

    • 水平位置: <font style="color:rgb(64, 64, 64);">X=(W-w)*$x_ratio</font>
      • <font style="color:rgb(64, 64, 64);">W</font> 是背景视频宽度, <font style="color:rgb(64, 64, 64);">w</font> 是上层视频宽度。
      • <font style="color:rgb(64, 64, 64);">$x_ratio</font> 是水平比例系数(0~1)。
    • 垂直位置: <font style="color:rgb(64, 64, 64);">Y=(H-h)*$y_ratio</font>
      • <font style="color:rgb(64, 64, 64);">H</font> 是背景视频高度, <font style="color:rgb(64, 64, 64);">h</font> 是上层视频高度。
      • <font style="color:rgb(64, 64, 64);">$y_ratio</font> 是垂直比例系数(0~1)。
  2. 动态参数注入

    所有参数(如宽度、透明度、时间偏移、位置比例等)都会动态注入到 FFmpeg 命令中。

  3. 上层视频时长计算

    使用 <font style="color:rgb(64, 64, 64);">ffprobe</font> 提取上层视频时长,确保叠加时间正确。

  4. FFmpeg 滤镜链

    • <font style="color:rgb(64, 64, 64);">scale=$overlay_width:-1</font> :按指定宽度缩放上层视频。
    • <font style="color:rgb(64, 64, 64);">colorchannelmixer=aa=$opacity</font> :设置透明度。
    • <font style="color:rgb(64, 64, 64);">setpts=PTS-STARTPTS+$time_offset/TB</font> :调整上层视频的开始时间。
    • <font style="color:rgb(64, 64, 64);">overlay=X=(W-w)*$x_ratio:Y=(H-h)*$y_ratio</font> :根据比例系数计算实际位置。
    • <font style="color:rgb(64, 64, 64);">enable='gte(t,$time_offset)*lte(t,$duration+$time_offset)'</font> :控制上层视频的显示时间范围。

脚本

#!/bin/bash

# 脚本功能:叠加背景视频和上层视频,支持调整上层视频的宽度、透明度、开始时间、位置比例等参数
# 使用方法:./merge_videos.sh <背景视频> <上层视频> <上层宽度> <时间偏移> <透明度> <x比例> <y比例> <输出文件名>

# 参数说明
# ----------------------------------------------------------------------------------------------
# | 参数名称       | 作用                                                                 |
# ----------------------------------------------------------------------------------------------
# | 背景视频       | 作为背景的视频文件                                                   |
# | 上层视频       | 叠加在上层的视频文件                                                 |
# | 上层宽度       | 上层视频的宽度(高度按比例自适应)                                   |
# | 时间偏移       | 上层视频从第几秒开始显示                                             |
# | 透明度         | 上层视频的透明度(0.0 完全透明,1.0 完全不透明)                     |
# | x比例          | 上层视频的水平位置比例(0=左侧,1=右侧,0.5=居中)                   |
# | y比例          | 上层视频的垂直位置比例(0=顶部,1=底部,0.5=居中)                   |
# | 输出文件名     | 最终生成的视频文件名                                                 |
# ----------------------------------------------------------------------------------------------

# 检查参数数量
if [ "$#" -ne 8 ]; then
    echo "错误:参数数量不正确!"
    echo "使用方法:$0 <背景视频> <上层视频> <上层宽度> <时间偏移> <透明度> <x比例> <y比例> <输出文件名>"
    exit 1
fi

# 从命令行读取参数
background_video=$1      # 背景视频文件名
overlay_video=$2         # 上层视频文件名
overlay_width=$3         # 上层视频宽度
time_offset=$4           # 上层视频开始时间偏移(秒)
opacity=$5               # 上层视频透明度
x_ratio=$6               # 上层视频水平位置比例(0~1)
y_ratio=$7               # 上层视频垂直位置比例(0~1)
output_file=$8           # 输出文件名

# 获取上层视频时长
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$overlay_video")

# 合成视频
ffmpeg -i "$background_video" -i "$overlay_video" \
-filter_complex "
[1:v]scale=$overlay_width:-1,colorchannelmixer=aa=$opacity,format=rgba,setpts=PTS-STARTPTS+$time_offset/TB[fg];
[0:v][fg]overlay=x='(W-w)*$x_ratio':y='(H-h)*$y_ratio':enable='gte(t,$time_offset)*lte(t,$duration+$time_offset)'" \
-c:a copy "$output_file"

# 输出完成信息
echo "视频合成完成!输出文件:$output_file"