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

如何用FFmpeg裁剪音视频片段且保留另一轨道完整?

FFmpeg 保留原时长的多片段裁剪方案

你的现有脚本是将两段视频/音频拼接,输出时长是两段的总和(10秒),但需求是保持原文件的完整时长,不需要的片段用冻结帧/黑屏+静音填充。下面是两种实现方案:

方案一:分段拼接(直观易理解)

这种方法把原时长拆分为「保留段」和「填充段」,分别处理后拼接,总时长与原文件一致。

步骤说明

  1. 视频处理:将原视频拆分为多个片段,不需要的部分替换为冻结帧(或黑屏)
  2. 音频处理:将原音频拆分为多个片段,不需要的部分替换为静音
  3. 分别拼接视频和音频片段,最后合并输出

完整命令(需先获取原文件时长)

先通过ffprobe获取原视频时长(存为变量DURATION):

DURATION=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 bdt.mkv)

然后执行FFmpeg命令:

ffmpeg -i bdt.mkv -filter_complex "
# 视频处理:拆分并替换不需要的片段为冻结帧
[0:v]trim=start=0:end=10,setpts=PTS-STARTPTS[v0];
[0:v]trim=start=10:end=15,setpts=PTS-STARTPTS[v1];
[0:v]trim=start=15:end=15.1,setpts=PTS-STARTPTS,loop=loop=-1:size=1[v2]; # 冻结15秒处的帧作为填充
[0:v]trim=start=65:end=70,setpts=PTS-STARTPTS[v3];
[0:v]trim=start=70:end=$DURATION,setpts=PTS-STARTPTS,loop=loop=-1:size=1[v4];
[v0][v1][v2][v3][v4]concat=n=5:v=1:a=0[outv];

# 音频处理:拆分并替换不需要的片段为静音
aevalsrc=0:d=10[a0]; # 0-10秒静音
[0:a]atrim=start=10:end=15,asetpts=PTS-STARTPTS[a1];
aevalsrc=0:d=50[a2]; # 15-65秒静音(时长65-15=50)
[0:a]atrim=start=65:end=70,asetpts=PTS-STARTPTS[a3];
aevalsrc=0:d=$(echo "$DURATION - 70" | bc)[a4]; # 70到结束的静音
[a0][a1][a2][a3][a4]concat=n=5:v=0:a=1[outa]
" -map [outv] -map [outa] out.mp4

方案二:基础流覆盖(简洁高效)

这种方法先创建与原时长一致的黑屏/静音基础流,再将需要保留的片段覆盖到对应时间段,无需拆分多个片段。

完整命令

DURATION=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 bdt.mkv)
VIDEO_SIZE=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 bdt.mkv)

ffmpeg -i bdt.mkv -filter_complex "
# 视频:创建黑屏基础流,覆盖需要保留的片段
color=c=black:s=$VIDEO_SIZE:d=$DURATION[basev];
[0:v]trim=start=10:end=15,setpts=PTS-STARTPTS+10/TB[v1]; # 调整时间戳回到原位置
[basev][v1]overlay=enable='between(t,10,15)'[tmpv];
[0:v]trim=start=65:end=70,setpts=PTS-STARTPTS+65/TB[v2];
[tmpv][v2]overlay=enable='between(t,65,70)'[outv];

# 音频:创建静音基础流,混合需要保留的片段
aevalsrc=0:d=$DURATION[basea];
[0:a]atrim=start=10:end=15,asetpts=PTS-STARTPTS+10/TB[a1];
[basea][a1]amix=inputs=2:duration=longest[tmpa];
[0:a]atrim=start=65:end=70,asetpts=PTS-STARTPTS+65/TB[a2];
[tmpa][a2]amix=inputs=2:duration=longest[outa]
" -map [outv] -map [outa] out.mp4

关键参数说明

  • setpts=PTS-STARTPTS+X/TB:将截取的片段时间戳偏移X秒,使其回到原文件中的位置
  • overlay=enable='between(t,X,Y)':仅在X到Y秒时间段内覆盖视频片段
  • amix=inputs=2:duration=longest:将保留的音频片段混合到静音基础流上
  • loop=loop=-1:size=1:单帧循环生成冻结画面,比黑屏更贴合原视频风格

适配Python变量的建议

在Python中,你可以先通过subprocess调用ffprobe获取时长和分辨率,再将时间戳变量(如start1=10、end1=15等)代入FFmpeg命令字符串,动态生成完整执行命令。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:35:38