You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用FFmpeg/ffmpeg-python移除绿幕背景并替换多段背景视频?

绿幕视频背景移除与分时段替换方案

一、纯FFmpeg命令移除绿幕

针对无阴影的单一纯色绿幕,chromakey滤镜是最高效的选择:

1. 输出带透明背景的视频

ffmpeg -i test.mp4 -filter_complex "[0:v]chromakey=green:0.1:0.2[fg];[fg]format=rgba[v]" -map "[v]" -map 0:a transparent_output.mp4

参数解释:

  • green:目标抠除色(也可替换为十六进制值如#00FF00)
  • 0.1:相似度阈值,数值越小抠像精度越高(无阴影场景用0.1足够)
  • 0.2:边缘融合阈值,控制抠像边缘的柔和度

2. 直接替换为固定背景视频

ffmpeg -i test.mp4 -i background.mp4 -filter_complex "[0:v]chromakey=green:0.1:0.2[fg];[1:v][fg]overlay[outv]" -map "[outv]" -map 0:a final_fixed_bg.mp4

二、用ffmpeg-python实现分时段替换不同背景

假设你有对应时段的背景视频:bg1.mp4(0-5秒)、bg2.mp4(5-15秒),以下是完整实现代码:

import ffmpeg

# 加载输入文件
input_vid = ffmpeg.input('test.mp4')
bg1 = ffmpeg.input('bg1.mp4')
bg2 = ffmpeg.input('bg2.mp4')

# 全局抠除绿幕
foreground = input_vid.video.filter('chromakey', color='green', similarity=0.1, blend=0.2)

# 处理0-5秒片段:匹配bg1与前景时长并叠加
clip1_bg = bg1.video.trim(start=0, end=5).setpts('PTS-STARTPTS')
clip1_fg = foreground.trim(start=0, end=5).setpts('PTS-STARTPTS')
clip1_combined = ffmpeg.filter([clip1_bg, clip1_fg], 'overlay')
clip1_audio = input_vid.audio.filter('atrim', start=0, end=5).filter('asetpts', 'PTS-STARTPTS')

# 处理5-15秒片段:匹配bg2与前景时长并叠加
clip2_bg = bg2.video.trim(start=0, end=10).setpts('PTS-STARTPTS')
# 若bg2时长不足,可添加loop滤镜循环:bg2.video.loop(loop=-1, size=10).trim(start=0, end=10).setpts('PTS-STARTPTS')
clip2_fg = foreground.trim(start=5, end=15).setpts('PTS-STARTPTS')
clip2_combined = ffmpeg.filter([clip2_bg, clip2_fg], 'overlay')
clip2_audio = input_vid.audio.filter('atrim', start=5, end=15).filter('asetpts', 'PTS-STARTPTS')

# 拼接视频与音频轨道
final_video = ffmpeg.concat(clip1_combined, clip2_combined, v=1, a=0)
final_audio = ffmpeg.concat(clip1_audio, clip2_audio, v=0, a=1)

# 输出最终视频
ffmpeg.output(final_video, final_audio, 'segmented_bg_output.mp4').run(overwrite_output=True)

关键提示:

  • 确保所有视频分辨率一致,不一致时可添加.filter('scale', 1920, 1080)统一尺寸
  • 背景视频时长不足时,用loop滤镜循环填充对应时段长度

三、OpenCV替代方案(纯Python无FFmpeg依赖)

适合短视频场景,手动调整HSV阈值实现抠像:

import cv2
import numpy as np

# 初始化视频流与输出
cap = cv2.VideoCapture('test.mp4')
bg_cap = cv2.VideoCapture('bg1.mp4')  # 可根据时间帧切换不同背景视频
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
out = cv2.VideoWriter('opencv_output.mp4', cv2.VideoWriter_fourcc(*'mp4v'), fps, (width, height))

# 绿色HSV阈值(可根据实际绿幕微调)
lower_green = np.array([35, 43, 46])
upper_green = np.array([77, 255, 255])

frame_count = 0
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    
    # 切换背景视频(示例:0-5秒用bg1,5-15秒用bg2)
    if 5 * fps <= frame_count < 15 * fps:
        if not bg_cap.isOpened():
            bg_cap = cv2.VideoCapture('bg2.mp4')
    ret_bg, bg_frame = bg_cap.read()
    if not ret_bg:
        bg_cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
        ret_bg, bg_frame = bg_cap.read()
    
    # 抠像逻辑
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower_green, upper_green)
    mask_inv = cv2.bitwise_not(mask)
    
    foreground = cv2.bitwise_and(frame, frame, mask=mask_inv)
    background = cv2.bitwise_and(bg_frame, bg_frame, mask=mask)
    final_frame = cv2.add(foreground, background)
    
    out.write(final_frame)
    frame_count += 1

# 释放资源
cap.release()
bg_cap.release()
out.release()

内容的提问来源于stack exchange,提问作者Billi Alt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 16:15:40