视频画面裁剪与尺寸压缩实战:ffmpeg crop/scale 用法与在线替代

前言

上一篇讲了"按目标大小压缩"的码率反推(链接),但压缩只是视频瘦身的一半。另一半是裁剪------很多视频里其实塞了大量"无用画面":

  • 会议 / 课程录屏,顶部是菜单栏、底部是任务栏,甚至两侧有黑色信箱边;
  • 从 B 站 / YouTube 下载的视频,上下自带大黑边(pillarbox / letterbox);
  • 想把一个 16:9 的横屏 改成 9:16 的竖屏发抖音 / 视频号,直接上传会被自动压缩得很难看。

把无用画面裁掉,有两个直接好处:一是观感干净,二是像素总量下降,后续压缩的体积和耗时同步减少(裁剪和压缩是乘性关系,先裁 20% 面积 ≈ 后续压缩少编码 20% 的数据)。

本文聚焦 cropscale 两个滤镜的工程用法,附可直接跑的命令和脚本,最后给出不想装环境时的在线替代。

环境准备

bash 复制代码
# 验证 ffmpeg 在位
ffmpeg -version        # 需 4.0+,cropdetect 早已支持
ffprobe -version

本文所有命令在 ffmpeg 6.0 / Windows 11 下验证。Windows 下 -f null -/dev/null 换成 NUL

一、crop 滤镜语法

复制代码
crop=w:h:x:y
  • wh:输出宽高
  • xy:裁剪区域左上角在原图里的坐标
  • 省略 x:y 时默认居中裁剪crop=w:h
  • 宽度高度建议用表达式自动取偶数(编码器要求尺寸为偶数):
    • crop=iw:ih-100 表示"高度减 100,宽度不变,居中"
    • crop=ih*9/16:ih 表示"按 9:16 竖屏裁切,高度用满"

二、实战 1:裁掉录屏的多余界面

一个 1920×1080 的屏幕录屏,顶部 40px 是浏览器标签栏、底部 50px 是任务栏,真正有用的画面在 y=40y=1030

bash 复制代码
# 裁掉顶部 40px + 底部 50px,保留 1920×990
ffmpeg -i screen.mp4 -vf "crop=1920:990:0:40" -c:a copy screen_crop.mp4

-c:a copy 音轨不动只重封装,省时间。若想顺带压缩视频:

bash 复制代码
ffmpeg -i screen.mp4 -vf "crop=1920:990:0:40" \
       -c:v libx264 -crf 24 -c:a aac screen_crop_comp.mp4

三、实战 2:自动检测黑边(cropdetect)

不知道黑边具体多宽?用 cropdetect 让 ffmpeg 自己扫一遍,输出建议的裁剪参数:

bash 复制代码
ffmpeg -i video.mp4 -vf cropdetect -f null NUL

输出类似:

复制代码
[Parsed_cropdetect_0 @ ...] x1:0 y1:138 x2:1919 y2:941 w:1920 h:804 crop=1920:804:0:138

最后一行 crop=1920:804:0:138 就是建议值,直接套用:

bash 复制代码
ffmpeg -i video.mp4 -vf "crop=1920:804:0:138" -c:a copy video_nobar.mp4

注意:cropdetect 是按抽样帧判断的,若视频前后黑边不一致(比如片头有、正片无),建议手动指定或分段处理。

四、实战 3:16:9 转 9:16 竖屏(中心裁剪)

短视频平台要竖屏。直接把 1920×1080 拉伸会变形,正确做法是裁出中间的竖条

bash 复制代码
# 高度用满 1080,宽度 = 1080 * 9/16 = 607.5 → 取偶数 608
ffmpeg -i landscape.mp4 -vf "crop=608:1080" -c:a copy portrait.mp4

用表达式更稳(不写死数字):

bash 复制代码
ffmpeg -i landscape.mp4 -vf "crop=ih*9/16:ih" -c:a copy portrait.mp4

如果同时想缩小体积,叠加 scale:

bash 复制代码
# 竖屏 + 缩到宽 540(高度自动 960),H.264 压缩
ffmpeg -i landscape.mp4 -vf "crop=ih*9/16:ih,scale=540:-2" \
       -c:v libx264 -crf 26 -c:a aac portrait_small.mp4

scale=540:-2-2 表示高度按宽度比例自动算,且取最近偶数(编码器硬性要求)。

五、用 Python 批量裁剪(带自动黑边检测)

把"检测 + 裁剪"封装一下,处理一堆录屏:

python 复制代码
#!/usr/bin/env python3
"""auto_crop.py --- 自动检测黑边并裁剪一批视频

用法:
    python auto_crop.py input_dir
"""
import os
import re
import subprocess
import sys
from pathlib import Path


def detect_crop(path: str) -> str | None:
    """用 cropdetect 拿建议的 crop 参数,返回 'w:h:x:y' 或 None"""
    cmd = ["ffmpeg", "-i", path, "-vf", "cropdetect", "-f", "null",
           "NUL" if os.name == "nt" else "/dev/null"]
    out = subprocess.run(cmd, capture_output=True, text=True)
    # cropdetect 的最后一条建议通常最准(基于全片抽样)
    matches = re.findall(r"crop=(\d+:\d+:\d+:\d+)", out.stderr)
    return matches[-1] if matches else None


def crop(path: str, crop_arg: str, dst: str):
    subprocess.run(
        ["ffmpeg", "-y", "-i", path, "-vf", f"crop={crop_arg}",
         "-c:a", "copy", dst],
        check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)


def main():
    src_dir = Path(sys.argv[1] if len(sys.argv) > 1 else ".")
    for f in src_dir.glob("*.mp4"):
        arg = detect_crop(str(f))
        if not arg:
            print(f"[skip] {f.name} 未检测到黑边")
            continue
        dst = f.with_name(f"{f.stem}_crop.mp4")
        print(f"[crop {arg}] {f.name} -> {dst.name}")
        crop(str(f), arg, str(dst))


if __name__ == "__main__":
    main()

实测一个文件夹里 5 段带黑边的录屏(均为 1920×1080,实际内容 1920×804),自动裁剪后:

文件 原始大小 裁剪后 体积变化
rec01.mp4 312 MB 261 MB −16.3%
rec02.mp4 288 MB 241 MB −16.3%
rec03.mp4 401 MB 336 MB −16.2%
rec04.mp4 155 MB 130 MB −16.1%
rec05.mp4 220 MB 184 MB −16.3%

裁剪掉约 25% 的无效画面高度(1080→804),因为音轨未重编码,总体积下降约 16%,符合预期(画面数据占比约 65--70%,裁掉 25% 高度 ≈ 画面数据减 25%,加权到整体约 16%)。

六、什么时候不该自己写命令

上面这套适合有 ffmpeg 环境、要批量处理的情况。如果是:

  • 偶尔裁一个文件,装环境 + 算 crop 坐标的时间比裁剪本身长;
  • 在非技术同事的机器上(客户现场、临时借用的电脑);
  • 想要"上传即裁 + 压缩一步到位"

浏览器方案更实际。我处理临时需求时会用 VideoCompress 这类在线工具,它的"画面裁剪"和"压缩"在同一个入口,拖动选框就能定裁剪区域、填目标大小就能压,不用记 crop=w:h:x:y 语法。它支持 40 多种格式输入、导出不带水印,单文件上限免费 1 GB(付费 10 GB)。

边界和所有云端方案一样:文件要上传到服务器(其说明为完成后 24 小时内自动删除),涉密、未公开素材不建议往任何在线服务传。

七、几个工程上的坑

1. crop 坐标越界会报错。 x + w 不能超过原宽、y + h 不能超过原高,否则 ffmpeg 直接失败。手动填坐标时务必先 ffprobe 拿真实分辨率。

2. 尺寸必须是偶数。 H.264/H.265 的色度采样要求宽高为偶数,奇数会报错或绿边。表达式里用 -2trunc(.../2)*2 兜底最稳。

3. 裁剪和压缩顺序:先裁后压。 裁剪减少像素总量,后续编码的数据量随之下降,是先裁再压划算,不是反过来。

4. 竖屏中心裁会"丢两边内容"。 16:9 转 9:16 是从中间竖切,画面左右会被切掉。人物访谈、PPT 这类主体在中间的还好,主体偏左偏右的要手动定 x

总结

视频瘦身 = 裁剪无用画面 + 压缩冗余数据,二者乘性叠加:

  1. 先用 cropdetect 看有没有黑边/多余界面,有就 crop= 掉;
  2. 需要换比例(横转竖)用 crop=ih*9/16:ih 中心裁,注意左右内容取舍;
  3. 叠加 scale=宽:-2 控制输出尺寸,再用 libx264 压缩;
  4. 批量交给脚本,一次性任务 / 临时环境用在线工具。

工具只是手段,先想清楚"这段视频最终在哪里看、什么比例",再决定怎么裁、怎么压。

标签:视频处理、FFmpeg、视频裁剪、音视频开发、短视频制作

相关推荐
阿童木写作2 小时前
跨境电商图片翻译工具推荐:批量AI翻译+视频字幕+智能抠图
大数据·人工智能·python·音视频
勤劳X码农3 小时前
2026年四款免费配音轻量工具参数记录与实测数据
音视频
乐橙开放平台4 小时前
老旧小区监控事件驱动派单:基于 setMessageCallback 的 msgType 分级与工单闭环实现
后端·物联网·音视频
lailai04104 小时前
视频离线观看工具的多维度比较分析
音视频
程序员老陆6 小时前
音频为什么不编码成“声卡格式”(例如S16)?因为声卡只负责响,编码器只负责省
ffmpeg·音视频
调试到凌晨7 小时前
免费配音工具长文本处理能力实测:做长视频和有声书,谁更稳?
音视频
沐禾安信18 小时前
将AVCHD转换为AVI的3种简单方法
音视频·格式转换·视频转换·gif动图
mardelan20 小时前
2026年iOS短视频总结工具测评强识别提效率 整理清晰更省心
ios·音视频
山顶夕景20 小时前
【VQA】VideoChat3长视频理解模型
音视频·多模态·视频理解·长视频