【问题标题】:Maintaining exact aspect ratio when scaling videos using ffmpeg使用 ffmpeg 缩放视频时保持精确的纵横比
【发布时间】:2012-06-01 05:29:42
【问题描述】:

我有一个 mkv 视频,它混合了多种分辨率的录像,例如我有宽屏 16:9 (1024x576) 分辨率的前几秒钟,如果是 4:3 (768x576) 分辨率,则视频的其余部分。我想将此视频缩小 3 倍,同时复制所有其他属性(音频编解码器、字幕等)。我使用ffmpeg -i <input_mkv> -vf scale=iw/2:-1 -acodec copy <output_mp4>。此外,VLC 检测到它的分辨率为 720x576。

问题是缩放后分辨率不断变为 4:3 (360x288)。如何保持输入视频文件的动态纵横比,即 16:9 部分缩放为 16:9,而 4:3 部分缩放为 4:3?

更新

当分辨率切换时,播放器大小实际上会发生变化,至少在 mplayer 中是这样。我发现了主要问题。似乎每一帧都标有一个样本纵横比(SAR),所以当玩家播放它时,它可以找到显示纵横比。编码为 MKV 时不会复制此 SAR 值。当编码为 MPG 时,它确实被复制了,我得到了一个精确的副本,播放器切换大小,但不是 MKV。

ffprobe -show_streams filename的输出:

ffprobe version 0.10.3 Copyright (c) 2007-2012 the FFmpeg developers
  built on May  9 2012 17:51:07 with gcc 4.7.0 20120505 (prerelease)
  configuration: --prefix=/usr --enable-libmp3lame --enable-libvorbis --enable-libxvid --enable-libx264 --enable-libvpx --enable-libtheora --enable-libgsm --enable-libspeex --enable-postproc --enable-shared --enable-x11grab --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libschroedinger --enable-libopenjpeg --enable-librtmp --enable-libpulse --enable-gpl --enable-version3 --enable-runtime-cpudetect --disable-debug --disable-static
  libavutil      51. 35.100 / 51. 35.100
  libavcodec     53. 61.100 / 53. 61.100
  libavformat    53. 32.100 / 53. 32.100
  libavdevice    53.  4.100 / 53.  4.100
  libavfilter     2. 61.100 /  2. 61.100
  libswscale      2.  1.100 /  2.  1.100
  libswresample   0.  6.100 /  0.  6.100
  libpostproc    52.  0.100 / 52.  0.100
Input #0, matroska,webm, from 'sample.mkv':
  Metadata:
    title           : Pan prstenu. Dve veze
  Duration: 00:00:29.80, start: 0.000000, bitrate: 3124 kb/s
    Stream #0:0(eng): Video: mpeg2video (Main), yuv420p, 720x576 [SAR 64:45 DAR 16:9], 15000 kb/s, 25 fps, 25 tbr, 1k tbn, 50 tbc (default)
    Stream #0:1(cze): Audio: mp2, 48000 Hz, stereo, s16, 128 kb/s (default)
[STREAM]
index=0
codec_name=mpeg2video
codec_long_name=MPEG-2 video
codec_type=video
codec_time_base=1/50
codec_tag_string=[0][0][0][0]
codec_tag=0x0000
width=720
height=576
has_b_frames=1
sample_aspect_ratio=64:45
display_aspect_ratio=16:9
pix_fmt=yuv420p
level=8
timecode=16:35:19:10
id=N/A
r_frame_rate=25/1
avg_frame_rate=25/1
time_base=1/1000
start_time=0.000000
duration=N/A
nb_frames=N/A
TAG:language=eng
[/STREAM]
[STREAM]
index=1
codec_name=mp2
codec_long_name=MP2 (MPEG audio layer 2)
codec_type=audio
codec_time_base=1/48000
codec_tag_string=[0][0][0][0]
codec_tag=0x0000
sample_fmt=s16
sample_rate=48000
channels=2
bits_per_sample=0
id=N/A
r_frame_rate=0/0
avg_frame_rate=125/3
time_base=1/1000
start_time=0.000000
duration=N/A
nb_frames=N/A
TAG:language=cze
[/STREAM]

【问题讨论】:

  • 你真的有一个多分辨率的视频流吗?这不是编解码器或播放软件广泛支持的设置。您能否发布ffprobe -show_streams input_mkv 的输出,以便我们了解 FFmpeg 如何看待文件的组织?
  • 添加了您要求的信息,以及我到现在为止的发现。

标签: ffmpeg scaling video-encoding


【解决方案1】:

FFmpeg 视频过滤器有一个 surprisingly rich set of logical functions 用于构建复杂的过滤器,您应该能够使用它们来保留文件中不断变化的 SAR。试试这样的:

ffmpeg ... -vf scale='if(gt(dar\, 4/3)\, 512) + ifnot(gt(dar\, 4/3)\, 384):-1' ...

根据需要将512384 替换为适当的值。也就是说,我没有要测试的多 SAR 视频,所以 YMMV。

您还可以查看 showinfo filter 以获取有关每个帧的极其详细的信息,并可能查看 setsar filter,尽管缺少特定于帧的变量意味着很难在中途更改它。

【讨论】:

  • 这是一个示例:db.tt/0AOs4x2f。这不起作用,视频保持不变的大小。我认为问题在于 ffmpeg 根据第一帧对整个视频进行 SAR,然后简单地将其放入整个剩余视频中。有没有办法让它在每一帧中查找数据?
  • ffmpeg man pages 对过滤器表达式的描述相当完整。
最近更新 更多