FFMPEG:在不损失质量的情况下裁剪视频

mra*_*ana 19 video ffmpeg

我有mp4视频1920x1080.我想裁剪视频,480x270 没有质量损失.

我使用以下命令:

ffmpeg -i input.mp4 -filter:v "crop=480:270:200:200" -crf 23 output.mp4
Run Code Online (Sandbox Code Playgroud)

我也尝试过:

ffmpeg -i input.mp4 -filter:v "crop=480:270:200:100" -c:a copy -qp 0 output.mp4
Run Code Online (Sandbox Code Playgroud)

我使用-crf 23-qp 0无视视频裁剪,但裁剪后视频已失去质量.

有谁知道我如何裁剪视频而不会失去质量?

llo*_*gan 28

编码为有损格式时,不能在不降低质量的情况下执行任何过滤,但您有一些选择.

用你的播放器裁剪

一种可能的解决方案是在播放期间裁剪,因此您甚至不需要重新编码.预览作物也很有用.

使用ffplay裁剪过滤器:

ffplay -vf "crop=480:270:200:100" input.mp4
Run Code Online (Sandbox Code Playgroud)

使用vlc(或cvlc):

vlc input.mp4 --crop=480x270+200+100
Run Code Online (Sandbox Code Playgroud)

或者您可以使用VLC GUI裁剪:工具>效果和滤镜>视频效果>裁剪.

此方法不会创建输出文件.这将使用您的视频播放器在播放时进行裁剪.如果需要输出文件,请参阅其他方法之一.

使用无损格式

ffmpeg可以编码几个无损编码器:ffv1,huffyuv,ffvhuff,utvideo,libx264(使用-crf 0-qp 0).输出将是无损的,但输出文件将是巨大的.

ffmpeg -i input.mp4 -vf "crop=480:270:200:100" -c:v ffv1 -c:a copy output.mkv
Run Code Online (Sandbox Code Playgroud)

要么

ffmpeg -i input.mp4 -vf "crop=480:270:200:100" -c:v libx264 -crf 0 -c:a copy output.mp4
Run Code Online (Sandbox Code Playgroud)

接受一些质量损失

给它足够的位,你可能无法分辨出质量差异:

ffmpeg -i input -vf "crop=480:270:200:100" -c:v libx264 -crf 17 -c:a copy ouput.mp4
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅FFmpeg Wiki:H.264视频编码指南.

如果您的输入是MJPEG

使用流复制单个图像ffmpeg,无损地裁剪它们jpegtran,然后将它们重新混合ffmpeg.这将导致没有损失,但您将被限制在古老的MJPEG格式.

  • 在 mplayer 中播放新视频时,使用比特流过滤器效果很好,但在 VLC (3.0.9.2) 和 Kodi (18) 中都会出现混乱。 (2认同)

Cri*_*sov 6

至少对于某些视频格式,基于元数据的软解决方案应该可以通过 FFmpeg 以及使用libavcodec 中的比特流hevc_metadata过滤器来实现,例如或h264_metadata

\n\n

crop与和等过滤器不同cropdetect,这不需要解码。不过,语法略有不同,因为您只能设置四个边缘的裁剪量,而不能设置目标矩形大小。对于 1920×1080 全高清帧中左上角位置 (200,200) 处 OP 的 480×270 区域,我们得到:

\n\n
    \n
  • ffmpeg -i input.mp4 -codec copy -bsf:v h264_metadata=crop_left=200:crop_right=1240:crop_top=200:crop_bottom=610 output.mp4
  • \n
\n\n

由于这是编解码器元数据,因此无论容器格式如何,它都应该有效,即不仅在 MP4 中,而且在 MKV 或 AVI 中也是如此。唉,我还没有亲自测试过,也不能透露有关软件和硬件播放器的支持。(不过,第一次简单检查惨遭失败。)

\n\n

有关更详细的信息,FFmpeg 的文档分别参考了 H.265 和 H.264 规范的第 7.4.3.2.1 和 7.4.2.1.1 节,它们可以从 ITU 免费获得,并且基本上是等效的:

\n\n
\n
    \n
  • frame_cropping_flag等于 1 指定帧裁剪偏移参数紧随序列参数集中的下一个。\nframe_cropping_flag 等于 0 指定帧裁剪偏移参数不存在。
  • \n
  • frame_crop_left_offsetframe_crop_right_offsetframe_crop_top_offsetframe_crop_bottom_offset指定从解码过程输出的编码视频序列中的图片样本,以输出帧坐标中指定的矩形区域为单位。\n 变量CropUnitXCropUnitY的推导如下:

    \n\n

    \xe2\x80\x93 如果 ChromaArrayType 等于 0,则 CropUnitX 和 CropUnitY 导出为:\n CropUnitX = 1\n CropUnitY = 2 \xe2\x88\x92 frame_mbs_only_flag\n \xe2\x80\x93 否则(ChromaArrayType等于 1、2 或 3),CropUnitX导出CropUnitY为: \n CropUnitX = SubWidthC\n CropUnitY = SubHeightC * ( 2 \xe2\x88\x92 frame_mbs_only_flag )

  • \n
\n\n

帧裁剪矩形包含水平帧坐标来自 \n CropUnitX * frame_crop_left_offset to PicWidthInSamplesL \xe2\x88\x92 ( CropUnitX * frame_crop_right_offset + 1 )\n 和垂直帧坐标来自 \n 的 亮度样本CropUnitY * frame_crop_top_offset to ( 16 * FrameHeightInMbs ) \xe2\x88\x92\n ( CropUnitY * frame_crop_bottom_offset + 1 )(含)。

\n\n

的值frame_crop_left_offset应在 0\n 到 的范围内( PicWidthInSamplesL / CropUnitX ) \xe2\x88\x92 ( frame_crop_right_offset + 1 )(含);\n 的值frame_crop_top_offset应在 0 到 之间( 16 * FrameHeightInMbs / CropUnitY ) \xe2\x88\x92 ( frame_crop_bottom_offset + 1 )(含)。

\n\n

frame_cropping_flag等于 0 时,frame_crop_left_offsetframe_crop_right_offsetframe_crop_top_offset、的值frame_crop_bottom_offset应推断为等于 0。

\n\n

ChromaArrayType不等于 0 时,两个色度数组对应的指定样本就是帧坐标 的样本( x / SubWidthC, y / SubHeightC ),其中( x, y )是指定亮度样本的帧坐标。

\n\n

对于解码字段,解码字段的指定样本是落在帧坐标中指定的矩形内的样本。

\n
\n

  • 这是一个很好的解决方案。它确实不会重新编码 h264 视频。我用我的一个视频文件尝试了这一点,但它在不同的视频播放器之间无法可靠地工作。我正在使用 VLC 播放器,它对crop_left 和crop_top 的解释错误,视频已从右侧和底部裁剪。然后我尝试了 Windows Media Player,并按照预期从顶部和左侧裁剪了相同的视频。我需要以相同的方式在所有播放器中裁剪视频,因此我无法使用此选项。 (2认同)

MoD*_*oDJ 3

在基本层面上,您不能使用有损编码,然后期望它在解码然后再次编码时不会损失质量。唯一可行的方法是使用无损编解码器,例如带有动画编解码器的 Quicktime。这只是数字视频制作的基本事实,您无法通过仅将命令行选项传递给 ffmpeg 来解决此问题。

  • 但你正在压缩视频。视频在压缩形式下无法修改。就像任何其他压缩内容一样,例如 zip 文件。必须对其进行解压缩、修改(裁剪),然后再次压缩。话虽如此,只要比特率足够高,您就不应该损失太多质量。 (3认同)
  • 请注意,这个答案讨论的是“解码然后再次编码”。OP似乎不知道裁剪需要解码和编码。这是必要的,因为裁剪会更改图像数据(如果您想删除未使用的数据)。 (3认同)