视频画中画 PIP
两个视频叠加显示 · 主视频 + 小窗口画面
双视频画面合成/位置可控
两个视频叠加显示 · 主视频 + 小窗口画面
视频处理涉及复杂的解码 / 编码 / 滤镜操作,桌面 FFmpeg(开源 / 免费)是业界事实标准。安装 5 分钟,运行如下命令一次解决:
用 Homebrew,5 秒安装
Debian/Ubuntu/Fedora
无需本地安装
按上方系统对应的命令安装。验证:ffmpeg -version 应输出版本号。
将 input.mp4 改为你的实际视频文件路径。
用终端 (Terminal / cmd / PowerShell) 切到视频所在目录,粘贴命令并回车。
短视频几秒,长视频几分钟。输出文件出现在同目录。
了解工具定位 · 使用场景 · 对比优势
游戏主播录屏时需将摄像头画面叠加到游戏画面右上角。本工具直接上传两段视频,一次设定摄像头位置(右上/左下/任意像素坐标)和大小,避免后期软件逐帧拖拽。输出视频自带画中画,省去剪辑软件多轨道合成步骤。
企业培训录制时,屏幕共享内容(PPT/软件操作)与主讲人特写画面需同时保留。本工具将两路视频合成为一路,主讲人画面可缩小置于右下角,避免学员在多个窗口间切换。输出视频直接用于内部分享或回放。
电商产品拍摄时,主画面展示产品整体外观,同时用第二路视频特写细节(如面料纹理、接口做工)。本工具将两路画面同屏合成,特写窗口可拖拽到主画面任意位置,避免后期用剪辑软件做分屏或画中画嵌套。
手工艺/编程教学视频需要同时展示讲师面部表情和操作台/屏幕。本工具将讲师面部画面缩小置于左上角,操作画面作为主背景,一次合成即可发布。避免录制后手动对齐两路音视频轨道。
App 功能演示时需同时录制手机屏幕操作和前置摄像头拍摄的讲解人面部。本工具将前置摄像头画面叠加到屏幕录屏上,位置可调整至不遮挡关键 UI 区域。输出视频直接用于教程或 bug 反馈。
| 维度 | 本工具 | 竞品 A (Kapwing) | 传统方法 (Premiere Pro) |
|---|---|---|---|
| 处理速度 | 1-3 秒(纯前端 WASM) | 10-30 秒(上传+云端渲染) | 5-30 分钟(导入+渲染+导出) |
| 数据隐私 | 纯浏览器处理,不上传任何视频 | 视频上传至服务器处理 | 本地处理,但依赖软件安装 |
| 离线可用 | 完全离线可用(WASM 在浏览器内运行) | 必须联网 | 必须安装软件,可离线 |
| 文件大小限制 | 取决于浏览器内存(通常 500MB 以内) | 免费版 250MB,付费版 1GB | 无限制(取决于硬盘) |
| 费用 | 免费,无隐藏付费 | 免费版有水印,付费版 $16/月 | 订阅制 $22.99/月 |
| 操作复杂度 | 选择两个视频,一键合成 | 上传 + 调整参数 + 导出 | 新建项目 + 导入素材 + 拖拽时间线 + 导出 |
| 输出质量 | 与原视频一致(无二次编码) | 有压缩,免费版 720p 限制 | 可自定义编码参数,无损输出 |
上手步骤 · 输入输出 · 避坑提示
| 输入 | 输出 | 说明 |
|---|---|---|
| 主视频:demo_main.mp4(1920×1080,30fps,时长60秒) 子视频:demo_sub.mp4(640×480,25fps,时长60秒) 子视频位置:右下角(x=1200, y=540) 子视频尺寸:320×240 | 输出视频:output.mp4(1920×1080,30fps,时长60秒) 主视频铺满全屏,子视频以 320×240 尺寸叠加在右下角坐标 (1200,540) 处,音频混合两个视频的音轨 | 典型场景:直播回放叠加主播摄像头画面 |
| 主视频:main_vertical.mp4(1080×1920,竖屏,30fps) 子视频:sub_vertical.mp4(540×960,竖屏,30fps) 子视频位置:左上角(x=20, y=20) 子视频尺寸:300×533 | 输出视频:output_vertical.mp4(1080×1920,30fps) 主视频铺满全屏,子视频以 300×533 尺寸叠加在左上角坐标 (20,20) 处,音频混合 | 竖屏场景:抖音/快手短视频画中画 |
| 主视频:main_landscape.mp4(1920×1080,30fps) 子视频:sub_landscape.mp4(1920×1080,30fps) 子视频位置:居中(x=0, y=0) 子视频尺寸:1920×1080 | 输出视频:output_fullcover.mp4(1920×1080,30fps) 子视频完全覆盖主视频,输出仅显示子视频内容,音频仅保留子视频音轨 | 边界 case:子视频与主视频同尺寸且位置居中,完全遮盖 |
| 主视频:main.mp4(1920×1080,30fps) 子视频:sub.mp4(1920×1080,30fps) 子视频位置:右下角(x=1700, y=800) 子视频尺寸:400×300 | 输出视频:output_clipped.mp4(1920×1080,30fps) 子视频部分超出画面边界(右边界超出 180px,下边界超出 20px),超出部分被裁剪,仅显示画面内的 220×280 区域 | 易错 case:子视频位置超出主画面边界,部分被裁剪 |
| 主视频:main.mp4(1920×1080,30fps,时长120秒) 子视频:sub.mp4(640×480,25fps,时长30秒) 子视频位置:左下角(x=20, y=700) 子视频尺寸:320×240 | 输出视频:output_shorter_sub.mp4(1920×1080,30fps,时长120秒) 主视频全程播放,子视频从第0秒开始叠加,持续30秒后消失,后续90秒仅显示主视频 | 边界 case:子视频时长短于主视频,结束后自动消失 |
| 主视频:main.mp4(1920×1080,30fps) 子视频:sub.mp4(1920×1080,30fps) 子视频位置:左上角(x=-100, y=-50) 子视频尺寸:400×300 | 输出视频:output_negative_offset.mp4(1920×1080,30fps) 子视频左上角偏移至画面外(x=-100, y=-50),仅画面内部分(300×250)可见,位于左上角边缘 | 易错 case:坐标使用负值,子视频部分移出画面 |
| 主视频:main.mp4(1920×1080,30fps) 子视频:sub.mp4(640×480,25fps) 子视频位置:右上角(x=1600, y=20) 子视频尺寸:320×240 透明度:50% | 输出视频:output_alpha.mp4(1920×1080,30fps) 子视频以 50% 透明度叠加在右上角,主视频透过子视频可见,形成半透明画中画效果 | 典型场景:需要子视频半透明不遮挡主内容 |
主视频 1920×1080,画中画视频 640×480,直接合成后画中画区域变形上传前将画中画视频裁剪/缩放为与主视频比例一致的尺寸(如 320×180),或使用工具内置的“保持原比例”选项FFmpeg 默认将画中画视频直接缩放至指定矩形区域,不保持宽高比会导致画面扭曲;需手动加 -aspect 或 scale=force_original_aspect_ratio=decrease
主视频 1920×1080,设置画中画位置 (x:1800, y:900),画中画尺寸 300×200,右侧和下侧超出画面确保 x + 画中画宽度 ≤ 主视频宽度,y + 画中画高度 ≤ 主视频高度;建议使用工具提供的“九宫格预设”避免手动计算FFmpeg overlay 滤镜中坐标 (x,y) 是画中画左上角位置,超出部分会被裁剪;用户常误以为坐标是中心点或右下角
两个视频都有音频,合成后只保留主视频音频,画中画音频丢失在工具中选择“混合音频”(amix)或“仅保留主视频音频”;若需画中画音频,勾选“保留双音轨”并在播放器中切换FFmpeg 默认只取第一个输入流的音频(-map 0:a),第二个视频的音频被丢弃;需显式使用 -filter_complex amix 或 -map 1:a 来保留
设置透明度为 1.0(完全不透明)或 0.0(完全透明),用户以为 0 是“不透明”透明度值范围 0.0~1.0,1.0=完全不透明,0.0=完全透明;建议从 0.8 开始调试FFmpeg colorkey/colorchannelmixer 的 alpha 参数与 CSS opacity 语义一致(1=不透明),但许多用户习惯 0=透明,导致反向操作
上传 .mov 或 .avi 文件,浏览器提示“无法解析视频”或转码失败使用 H.264(.mp4)或 WebM(.vp9)格式;若工具支持服务端转码,等待进度条完成即可浏览器原生只支持 MP4/H.264、WebM/VP9、OGV/Theora;其他格式需服务端 FFmpeg 转码,会增加等待时间
主视频 30 秒,画中画视频 60 秒,合成后 30~60 秒画中画区域显示黑屏提前裁剪画中画视频至与主视频等长,或使用工具“循环短视频”功能(若提供)FFmpeg overlay 滤镜默认以最短输入流为结束点,超出部分无画面;需加 shortest=1 或手动 trim
希望画中画在 5 秒后出现,但未设置延迟,结果从第 0 秒就显示在工具的时间轴设置中填入“延迟 5 秒”或使用 FFmpeg 参数 setpts=PTS+5/TBoverlay 滤镜支持 enable='between(t,5,30)' 条件表达式,但需用户明确知道时间单位是秒
公式推导 · 流程图解 · 依据出处
P(x, y) = B1 × α + B2 × (1 - α), 其中 α = f(x, y, w, h)
P(x, y) — 合成画面在坐标 (x, y) 处的像素值B1 — 主视频在对应坐标的像素值B2 — 画中画视频在对应坐标的像素值α — 由位置参数决定的混合权重(0~1)w — 画中画视频的显示宽度(像素)h — 画中画视频的显示高度(像素)主视频 1920×1080,画中画视频缩放至 320×240,放置于右下角(偏移 x=1500, y=780)。对于画中画区域内的像素 (1600, 900),α 由该点距画中画边界的距离计算得出(边缘羽化时 α=0.5,中心 α=1.0)。若 α=0.8,B1=100(灰度值),B2=200,则 P=100×0.8+200×0.2=80+40=120。
适用于双视频叠加合成场景,核心为 alpha blending(α 混合)算法,由 Porter & Duff 于 1984 年(SIGGRAPH)提出。当画中画位置超出主视频边界时,超出部分自动裁剪;不支持透明度渐变以外的混合模式(如相乘、屏幕)。
3 种主流语言 · 复制即用
import subprocess
# 使用 FFmpeg 将两个视频合成为画中画,主视频全屏,子视频置于右上角
# 子视频缩放至 320x240,位置偏移 (main_w - 320 - 20):20
def pip_overlay(main_video, sub_video, output):
cmd = [
"ffmpeg",
"-i", main_video,
"-i", sub_video,
"-filter_complex",
"[1:v]scale=320:240[sub];[0:v][sub]overlay=main_w-340:20",
"-c:a", "copy",
output
]
subprocess.run(cmd, check=True)
# 示例:将 main.mp4 与 sub.mp4 合成,输出 pip.mp4
pip_overlay("main.mp4", "sub.mp4", "pip.mp4")package main
import (
"fmt"
"os/exec"
)
// 调用系统 FFmpeg 实现画中画合成
// 子视频缩放至 320x240,置于主视频右下角 (main_w-340, main_h-260)
func pipOverlay(mainVideo, subVideo, output string) error {
args := []string{
"-i", mainVideo,
"-i", subVideo,
"-filter_complex", "[1:v]scale=320:240[sub];[0:v][sub]overlay=main_w-340:main_h-260",
"-c:a", "copy",
output,
}
cmd := exec.Command("ffmpeg", args...)
return cmd.Run()
}
func main() {
err := pipOverlay("main.mp4", "sub.mp4", "pip.mp4")
if err != nil {
fmt.Println("合成失败:", err)
} else {
fmt.Println("画中画视频已生成")
}
}const { execSync } = require('child_process');
// 使用 FFmpeg 合成画中画视频,子视频置于左上角 (10:10)
function pipOverlay(mainVideo, subVideo, output) {
const cmd = [
'ffmpeg',
'-i', mainVideo,
'-i', subVideo,
'-filter_complex', '[1:v]scale=320:240[sub];[0:v][sub]overlay=10:10',
'-c:a', 'copy',
output
];
execSync(cmd.join(' '), { stdio: 'inherit' });
}
// 示例:合成 main.mp4 和 sub.mp4 为 output.mp4
pipOverlay('main.mp4', 'sub.mp4', 'output.mp4');9 个高频疑问