如何让 AVFoundation 设备在 MacOS 上使用 FFMPEG 获得一致的播放速率(1.0x)

如何让 AVFoundation 设备在 MacOS 上使用 FFMPEG 获得一致的播放速率(1.0x)

背景信息:我一直用 QuickTime 录制我的“相机”,但它只允许两种质量选项,低质量(720p60fps)或高质量(使用 ProRes422 编码的 1080p60fps),如您所见,这里真的没有控制。您要么得到不尽人意的结果,要么得到过度的结果。使用另一个程序/FFMPEG 的原因:

  1. 将录音分成几段(即每小时开始一段新录音)
  2. 一个更安全的容器,因为我的 QT 中有多个损坏的文件。(mkv)
  3. 控制比特率。
  4. 一次处理多个摄像机/角度。(打开 QuickTime 实例很快就会变得混乱且令人疲惫。)

我想要实现的是使用 FFMPEG 以 1080p 60FPS 捕获我的 Elgato HD60s+(在 MacOS 中显示为相机)。我只想捕获视频(由于 FFMPEG 在 Mac 上存在音频问题,所以我在其他地方录制了音频,我尝试解决这个问题超过 8 个小时,但无济于事。)

首先,这是以下输出:

ffmpeg -f avfoundation -list_devices true -i “”

>     [AVFoundation indev @ 0x14c638710] AVFoundation video devices:
>     [AVFoundation indev @ 0x14c638710] [0] Reincubate Camo
>     [AVFoundation indev @ 0x14c638710] [1] HD Pro Webcam C920
>     [AVFoundation indev @ 0x14c638710] [2] Game Capture HD60 S+
>     [AVFoundation indev @ 0x14c638710] [3] Capture screen 0
>     [AVFoundation indev @ 0x14c638710] AVFoundation audio devices:
>     [AVFoundation indev @ 0x14c638710] [0] Wavelink test
>     [AVFoundation indev @ 0x14c638710] [1] Elgato Wave:3
>     [AVFoundation indev @ 0x14c638710] [2] Krisp Mk2
>     [AVFoundation indev @ 0x14c638710] [3] Reincubate
>     [AVFoundation indev @ 0x14c638710] [4] Safari
>     [AVFoundation indev @ 0x14c638710] [5] Astro MixAmp Pro Voice
>     [AVFoundation indev @ 0x14c638710] [6] Wave Link Stream
>     [AVFoundation indev @ 0x14c638710] [7] Game Capture HD60 S+
>     [AVFoundation indev @ 0x14c638710] [8] Elgato Audio
>     [AVFoundation indev @ 0x14c638710] [9] krisp microphone
>     [AVFoundation indev @ 0x14c638710] [10] CalDigit Thunderbolt 3 Audio
>     [AVFoundation indev @ 0x14c638710] [11] StreamOutput
>     [AVFoundation indev @ 0x14c638710] [12] HD Pro Webcam C920
>     : Input/output error

我一直使用的基本命令是:ffmpeg -f avfoundation -i "2:none" output.mkv,它会引发错误:

>     [avfoundation @ 0x159008200] Selected framerate (29.970030) is not supported by the device.
>     [avfoundation @ 0x159008200] Supported modes:
>     [avfoundation @ 0x159008200] 1920x1080@[59.940180 59.940180]fps

因此,使用此命令我们可以获得可用的素材。ffmpeg -framerate 59.940180 -f avfoundation -i "2:none" output.mkv,但它会生成不同步的视频。 1 分钟后,它会提前约 3 秒(1.03 倍)

这是来自以下输出视频的日志

ffmpeg version 4.3.2 Copyright (c) 2000-2021 the FFmpeg developers
  built with Apple clang version 12.0.0 (clang-1200.0.32.29)
  configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/4.3.2 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox
  libavutil      56. 51.100 / 56. 51.100
  libavcodec     58. 91.100 / 58. 91.100
  libavformat    58. 45.100 / 58. 45.100
  libavdevice    58. 10.100 / 58. 10.100
  libavfilter     7. 85.100 /  7. 85.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  7.100 /  5.  7.100
  libswresample   3.  7.100 /  3.  7.100
  libpostproc    55.  7.100 / 55.  7.100
[avfoundation @ 0x12d00ca00] Selected pixel format (yuv420p) is not supported by the input device.
[avfoundation @ 0x12d00ca00] Supported pixel formats:
[avfoundation @ 0x12d00ca00]   uyvy422
[avfoundation @ 0x12d00ca00]   yuyv422
[avfoundation @ 0x12d00ca00]   nv12
[avfoundation @ 0x12d00ca00]   0rgb
[avfoundation @ 0x12d00ca00]   bgr0
[avfoundation @ 0x12d00ca00] Overriding selected pixel format to use uyvy422 instead.
[avfoundation @ 0x12d00ca00] Stream #0: not enough frames to estimate rate; consider increasing probesize
Input #0, avfoundation, from '2:none':
  Duration: N/A, start: 991066.674467, bitrate: N/A
    Stream #0:0: Video: rawvideo (UYVY / 0x59565955), uyvy422, 1920x1080, 1000k tbr, 1000k tbn, 1000k tbc
File 'output.mkv' already exists. Overwrite? [y/N] y
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
Press [q] to stop, [?] for help
[libx264 @ 0x12c016c00] MB rate (8160000000) > level limit (16711680)
[libx264 @ 0x12c016c00] using cpu capabilities: ARMv8 NEON
[libx264 @ 0x12c016c00] profile High 4:2:2, level 6.2, 4:2:2, 8-bit
[libx264 @ 0x12c016c00] 264 - core 161 r3048 b86ae3c - H.264/MPEG-4 AVC codec - Copyleft 2003-2021 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, matroska, to 'output.mkv':
  Metadata:
    encoder         : Lavf58.45.100
    Stream #0:0: Video: h264 (libx264) (H264 / 0x34363248), yuv422p, 1920x1080, q=-1--1, 1000k fps, 1k tbn, 1000k tbc
    Metadata:
      encoder         : Lavc58.91.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
frame= 9219 fps= 55 q=-1.0 Lsize=   49384kB time=00:02:42.68 bitrate=2486.8kbits/s speed=0.973x    
video:49319kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.133110%
[libx264 @ 0x12c016c00] frame I:47    Avg QP:21.49  size:121163
[libx264 @ 0x12c016c00] frame P:2720  Avg QP:23.86  size: 12078
[libx264 @ 0x12c016c00] frame B:6452  Avg QP:26.29  size:  1853
[libx264 @ 0x12c016c00] consecutive B-frames:  5.1%  4.0%  2.2% 88.7%
[libx264 @ 0x12c016c00] mb I  I16..4: 15.2% 68.0% 16.7%
[libx264 @ 0x12c016c00] mb P  I16..4:  0.7%  1.5%  0.2%  P16..4: 28.0%  4.1%  4.4%  0.0%  0.0%    skip:61.1%
[libx264 @ 0x12c016c00] mb B  I16..4:  0.1%  0.1%  0.0%  B16..8: 25.5%  0.2%  0.0%  direct: 0.1%  skip:73.9%  L0:40.0% L1:59.6% BI: 0.4%
[libx264 @ 0x12c016c00] 8x8 transform intra:64.8% inter:81.0%
[libx264 @ 0x12c016c00] coded y,uvDC,uvAC intra: 50.1% 43.2% 8.9% inter: 3.1% 3.8% 0.1%
[libx264 @ 0x12c016c00] i16 v,h,dc,p: 26% 32%  5% 37%
[libx264 @ 0x12c016c00] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 21% 23% 21%  4%  6%  6%  7%  5%  7%
[libx264 @ 0x12c016c00] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 24% 28% 11%  5%  7%  6%  8%  4%  6%
[libx264 @ 0x12c016c00] i8c dc,h,v,p: 62% 17% 18%  3%
[libx264 @ 0x12c016c00] Weighted P-Frames: Y:3.1% UV:2.0%
[libx264 @ 0x12c016c00] ref P L0: 59.6% 14.8% 17.1%  8.5%  0.0%
[libx264 @ 0x12c016c00] ref B L0: 93.8%  4.6%  1.6%
[libx264 @ 0x12c016c00] ref B L1: 96.3%  3.7%
[libx264 @ 0x12c016c00] kb/s:2482.67
Exiting normally, received signal 2.

我想非常清楚地表明,我已经搜索了又搜索,尝试了很多不同的命令,但无法解决视频无法以一致的 1.0 倍速播放的问题。

基于这一切,我尝试了垂直同步、编码预设-超快、捕捉原始镜头,但无论我做什么似乎都无法让视频正常工作。

如果你已经做到了这一点,谢谢你!如果您需要任何澄清,我会每天检查多次,因此您应该会在约 12 小时内收到答复!

答案1

我也一直在努力解决这个问题。这似乎是由于帧拼接造成的,这意味着丢帧会导致在相同速率下视频变短(即视频变快)。我找到了一个可以实现稳定帧速率的解决方案:

-framerate 和 -r 是单独的输入选项

如果你看一下本文档页面它解释了-r-framerate是单独的选项,但通常您会想要使用输入选项-framerate

-r作为输入选项的工作方式与-r作为输出选项不同。我的理解是,使用-framerate作为输入选项会告诉捕获素材的网络摄像头要使用什么设置来输入流但不考虑输出流上的丢帧或额外帧。

指定输出文件的帧速率

相反,正如所提到的此维基页面,您可以使用-r选项作为输出选项.mp4如果使用作为目标格式,则指定恒定帧速率流。但是,由于您使用.mkv它,将指定 FPS 上限,并允许低于指定最大值的 FPS。

因为您的输入以大约 60fps 的速度录制,所以以下命令将每隔一帧删除一次,以给您稳定的 30fps:

ffmpeg -framerate 59.940180 -f avfoundation -i "2:none" -r 30 output.mkv

由于您实际上希望以每秒 60 帧的速度录制,因此在写入时提高 fps 上限对您没有多大帮助.mkv。相反,另一种选择是使用 FPS 过滤器,如果需要,该过滤器将复制帧以达到您想要的 60 fps。示例命令如下:

ffmpeg -framerate 59.940180 -f avfoundation -i "2:none" -filter:v fps=60 output.mkv

这会删除任何高于 30fps 的帧并复制任何低于该数字的帧,以给您稳定的帧速率和(希望)稳定的录制速度。

补充说明

还有一件事可能对您的需求并不重要,但值得考虑,那就是上述命令的默认功能还将在将输入流保存到磁盘之前对其进行编码。对于高端相机或多摄像机设置来说,这会高度占用 CPU。这可能是您遇到的问题的一部分,除非您的计算机非常强大。

这里的一个解决方案(也是我目前所做的)是将视频流复制到未编码的文件中,然后稍后执行编码。即

ffmpeg -framerate 59.940180 -f avfoundation -i "2:none" -c:v copy -filter:v fps=60 output.mkv

上述命令将视频编解码器更改为仅复制流,而不是使用编码算法。-c:v copy这样做。

然后,您可以使用类似以下内容对输出进行编码:

ffmpeg -i out.mkv -c:v libx264 -crf 0 -preset medium -tune film -pix_fmt yuv420p encoded.mkv

请注意,-c:v现在指定libx264。希望这有帮助!

相关内容