通过裁剪和调整大小将视频转换为固定屏幕尺寸

通过裁剪和调整大小将视频转换为固定屏幕尺寸

我试图自己解决这个问题,但无数的选择让我感到困惑。

理想情况下,我想使用 或ffmpegmencoder或其他东西,但我知道这两个我已经工作)将任何传入的视频转换为固定的屏幕尺寸。

如果视频太宽或太短,则对视频进行居中裁剪。如果尺寸不正确,请向上或向下调整尺寸以使其完全符合固定的屏幕尺寸。

我最终需要的是 720x480 的 XVid AVI 和 MP3 音轨。

我发现很多页面显示如何调整大小到最大分辨率,但我需要视频完全达到该分辨率(剪掉多余的部分,没有黑条)。

谁能告诉我要运行的命令行 - 或者至少让我知道一些/大部分的方式?如果需要多个命令行(运行 X 以获得分辨率,进行此计算,然后使用该计算的输出运行 Y),我可以编写脚本。

答案1

ffmpeg -i input.file -vf "scale=(iw*sar)*max(720/(iw*sar)\,480/ih):ih*max(720/(iw*sar)\,480/ih), crop=720:480" -c:v mpeg4 -vtag XVID -q:v 4 -c:a libmp3lame -q:a 4 output.avi

将“input.file”替换为输入文件的名称。

答案2

我不是 ffmpeg 专家,但这应该可以解决问题。

首先,您可以像这样获取输入视频的大小:

ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width in.mp4

使用相当新的 ffmpeg,您可以使用以下选项调整视频大小:

ffmpeg -i in.mp4 -vf scale=720:480 out.mp4

您可以将宽度或高度设置为,-1以便ffmpeg调整视频大小并保持宽高比。实际上,-2这是一个更好的选择,因为计算值应该均匀。所以你可以输入:

ffmpeg -i in.mp4 -vf scale=720:-2 out.mp4

获得视频后,720x480由于您要ffmpeg计算高度,因此它可能比预期大,因此您必须对其进行裁剪。这可以这样做:

ffmpeg -i in.mp4 -filter:v "crop=in_w:480" out.mp4

最后,您可以编写这样的脚本(可以轻松优化,但为了易读,我保持简单):

#!/bin/bash

FILE="/tmp/test.mp4"
TMP="/tmp/tmp.mp4"
OUT="/tmp/out.mp4"

OUT_WIDTH=720
OUT_HEIGHT=480

# Get the size of input video:
eval $(ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width ${FILE})
IN_WIDTH=${streams_stream_0_width}
IN_HEIGHT=${streams_stream_0_height}

# Get the difference between actual and desired size
W_DIFF=$[ ${OUT_WIDTH} - ${IN_WIDTH} ]
H_DIFF=$[ ${OUT_HEIGHT} - ${IN_HEIGHT} ]

# Let's take the shorter side, so the video will be at least as big
# as the desired size:
CROP_SIDE="n"
if [ ${W_DIFF} -lt ${H_DIFF} ] ; then
  SCALE="-2:${OUT_HEIGHT}"
  CROP_SIDE="w"
else
  SCALE="${OUT_WIDTH}:-2"
  CROP_SIDE="h"
fi

# Then perform a first resizing
ffmpeg -i ${FILE} -vf scale=${SCALE} ${TMP}

# Now get the temporary video size
eval $(ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width ${TMP})
IN_WIDTH=${streams_stream_0_width}
IN_HEIGHT=${streams_stream_0_height}

# Calculate how much we should crop
if [ "z${CROP_SIDE}" = "zh" ] ; then
  DIFF=$[ ${IN_HEIGHT} - ${OUT_HEIGHT} ]
  CROP="in_w:in_h-${DIFF}"
elif [ "z${CROP_SIDE}" = "zw" ] ; then
  DIFF=$[ ${IN_WIDTH} - ${OUT_WIDTH} ]
  CROP="in_w-${DIFF}:in_h"
fi

# Then crop...
ffmpeg -i ${TMP} -filter:v "crop=${CROP}" ${OUT}

答案3

如果你想一次性裁剪和缩放,你可以像这样制作一个裁剪然后缩放的过滤器链:

ffmpeg -i SomeInput.mp4 -vf "crop=in_h*9/16:in_h,scale=-2:400" -t 4 SomeOutput.mp4

上面的代码首先将视频裁剪为 16:9 纵向,然后缩放到 400px 高 x 适当的(偶数)宽度。

答案4

我是 ffmpeg 的新手,但现在在 VB.NET 中有一个不错的小转换器,它可以创建各种输出格式的原始电影,以便在具有 SD 卡访问权限但没有足够功能来解码复杂视频的小型设备中使用。

由于它在调整大小和裁剪时的工作方式,我必须手动编码并构建参数。基本上我需要知道最终的宽度和高度。

我有 2 个选项复选框:-

保留纵横比 (X) 填充所有像素 (X)

仅需要 4 个变量作为输入(1)原始视频宽度,(2)原始视频高度,(3)设备宽度,(4)设备高度。

尽管 VB.NET 可以很容易地适应任何语言。

    Dim crop As String = "" ' will build this in ffmpeg format for -s or scale and crop

    If cbAspectRatio.Checked = False Then
        m_dest_output_w = sz._w
        m_dest_output_h = sz._h

        ' scale to w * h - simple
        crop = " -s " & m_dest_output_w & ":" & m_dest_output_h
    Else
        Dim ratio As Double = CDbl(m_video_width) / CDbl(m_video_height) ' this is aspect ratio of original unsized video

        If cbFillPixels.Checked = False Then ' shrink to fit
            If sz._w * ratio <= m_video_height Then
                m_dest_output_w = sz._w
                m_dest_output_h = sz._w / ratio
            Else
                m_dest_output_h = sz._h
                m_dest_output_w = sz._h / ratio
            End If

            ' no cropping just resizing to a non-filled area that fits

            crop = " -s " & m_dest_output_w & ":" & m_dest_output_h ' no cropping needed as letterboxed

        Else ' expand / fill --- cropping needed
            If sz._w * ratio >= m_video_height Then
                m_dest_output_w = sz._w
                m_dest_output_h = sz._w * ratio

                crop = ",crop=" & sz._w & ":" & sz._h & ":0:" & Math.Abs((m_dest_output_h - sz._h)) \ 2
            Else
                m_dest_output_h = sz._h
                m_dest_output_w = sz._h * ratio

                crop = ",crop=" & sz._w & ":" & sz._h & ":" & Math.Abs((m_dest_output_w - sz._w)) \ 2 & ":0"
            End If

            crop = " -vf scale=" & m_dest_output_w & ":" & m_dest_output_h & crop

            m_dest_output_w = sz._w
            m_dest_output_h = sz._h
        End If
    End If

相关内容