使用Windows 7,从Decklink卡捕获(并记录)720p音频和视频的FFmpeg命令行

19

我正在尝试使用Windows 7 @ 720p从一张黑魔法DeckLink采集卡中捕获音频和视频,但我似乎无法正确设置ffmpeg命令行参数。

ffmpeg -list_devices true -f dshow -i dummy

[dshow @ 02457a60] DirectShow video devices
[dshow @ 02457a60]  "Blackmagic WDM Capture"
[dshow @ 02457a60]  "Decklink Video Capture"
[dshow @ 02457a60] DirectShow audio devices
[dshow @ 02457a60]  "Decklink Audio Capture"

使用ffmpeg -list_options true -f dshow -i video="Decklink Video Capture"命令

[dshow @ 03c2ea20] DirectShow video device options
[dshow @ 03c2ea20]  Pin "Capture"
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=720x486 fps=29.97 max s=720x486 fps=29.97
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=720x486 fps=23.976 max s=720x486 fps=23.976
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=720x576 fps=25 max s=720x576 fps=25
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=720x486 fps=59.9402 max s=720x486 fps=59.9402
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=720x576 fps=50 max s=720x576 fps=50
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=1920x1080 fps=23.976 max s=1920x1080 fps=23.976
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=1920x1080 fps=24 max s=1920x1080 fps=24
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=1920x1080 fps=25 max s=1920x1080 fps=25
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=1920x1080 fps=29.97 max s=1920x1080 fps=29.97
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=1920x1080 fps=30 max s=1920x1080 fps=30
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=1280x720 fps=50 max s=1280x720fps=50
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=1280x720 fps=59.9402 max s=1280x720 fps=59.9402
[dshow @ 03c2ea20]   pixel_format=uyvy422  min s=1280x720 fps=60.0002 max s=1280x720 fps=60.0002

使用ffmpeg命令列出true选项,然后使用dshow输入格式并指定音频设备为"Decklink Audio Capture"

[dshow @ 047fea20] DirectShow audio device options
[dshow @ 047fea20]  Pin "Capture"
[dshow @ 047fea20]   min ch=1 bits=16 rate= 48000 max ch=1 bits=16 rate= 48000
[dshow @ 047fea20]   min ch=2 bits=16 rate= 48000 max ch=2 bits=16 rate= 48000
[dshow @ 047fea20]   min ch=4 bits=16 rate= 48000 max ch=4 bits=16 rate= 48000
[dshow @ 047fea20]   min ch=6 bits=16 rate= 48000 max ch=6 bits=16 rate= 48000
[dshow @ 047fea20]   min ch=8 bits=16 rate= 48000 max ch=8 bits=16 rate= 48000
[dshow @ 047fea20]   min ch=10 bits=16 rate= 48000 max ch=10 bits=16 rate= 48000
[dshow @ 047fea20]   min ch=12 bits=16 rate= 48000 max ch=12 bits=16 rate= 48000
[dshow @ 047fea20]   min ch=16 bits=16 rate= 48000 max ch=16 bits=16 rate= 48000

这是我当前视频/音频源连接到Decklink卡HDMI端口的流信息

Stream #0:0: Video: rawvideo (UYVY / 0x59565955), uyvy422(tv), 1280x720, 59.94 tbr, 10000k tbn, 59.94 tbc
Stream #0:1: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s
最终我需要在屏幕上显示这个视频,并同时能够启动和停止录制,而预览仍在播放。
我的想法是使用FFmpeg捕获视频和音频信号,并将其传输到网络流(例如127.0.0.1:6666)。然后使用VLC播放器来显示流(即预览)。最终启动和/或停止另一个FFmpeg将同一流保存到磁盘中。
在我看来,这样可以实现,但我不是音视频专家,如果有更有经验的人能帮助一下,我会非常感激。
更新:
我已经成功使用以下命令使用ffplay显示视频:
ffplay -f dshow -video_size 1280x720 -rtbufsize 702000k -framerate 60 -i video="Decklink Video Capture":audio="Decklink Audio Capture" -threads 2

下一步是将其流式传输,以便我可以使用 VLC 查看流式预览。

尝试使用以下命令:

ffmpeg -f dshow -video_size 1280x720 -rtbufsize 702000k -framerate 60 -i video="Decklink Video Capture":audio="Decklink Audio Capture" -threads 2 -f mpegts rtp://127.0.0.1:6666?pkt_size=188?buffer_size=65535

这似乎没有出现任何错误,所以看起来是有效的。但是当我尝试在VLC中打开流时,我收到以下错误:

SDP要求: 需要以SDP格式提供描述以接收RTP流。请注意,rtp:// URI无法与动态RTP负载格式(65)一起使用。

经过一些阅读,似乎我不应该将流媒体发送到rtp://,而应该发送到udp://

命令变为:

ffmpeg -f dshow -video_size 1280x720 -rtbufsize 702000k -framerate 60 -i video="Decklink Video Capture":audio="Decklink Audio Capture" -threads 2 -f mpegts udp://127.0.0.1:6666?pkt_size=188?buffer_size=65535

现在我尝试在VLC中打开它,没有错误提示,也没有视频。

是时候再多阅读一些了。


1
我的建议是你对ffmpeg期望过高了。使用directshow并构建一个应用程序(看起来像录制器)来完成这个任务。 - Daniel Mošmondor
我必须说那是我的第一意图。所以我继续这样做,很快就意识到我面临的挑战是及时转换源帧。这是因为源是8位YUV422。所以我与黑魔法的开发支持人员交谈,看看使用什么选项最好。他们指向了libav。既然它在ffmpeg中使用,我想我也可以尝试那条路。 - Huron
最近在FFmpeg中添加了“本地”DeckLink输入/输出设备,顺便说一下。 - rogerdpack
我对你的帖子印象深刻,我在FFmpeg网站上添加了一个关于Blackmagic的页面。由于我有一张4K卡,所以它与其他线路不同,我必须使用“-vsync drop”来避免时间戳的一些问题。 - max246
1个回答

34

终于让它正常工作了。我的设置是在一台机器上运行所有内容。

为了通过UDP获取视频并提供服务,我使用以下命令:

ffmpeg -f dshow -video_size 1280x720 -rtbufsize 702000k -framerate 60 -i video="Decklink Video Capture":audio="Decklink Audio Capture" -r 30 -threads 4 -vcodec libx264 -crf 0 -preset ultrafast -f mpegts "udp://239.255.12.42:6666"
  • -f dshow 参数告诉ffmpeg我们需要使用direct show。
  • -video_size 1280x720 设置源文件大小,因为我使用的是720p60源文件。
  • 702000k 非常重要,没有它实时缓冲区将在几秒钟内被填满。
  • -framerate 60 告诉ffmpeg源文件使用60fps。
  • 选项:video="Decklink Video Capture":audio="Decklink Audio Capture" 让ffmpeg使用这些设备作为输入,但通过这种方式指定它们,音频和视频之间的延迟会大大降低(或消失)。
  • -r 30 强制输出为30fps,而不是源文件中的60fps。
  • -threads 4 使用4线程。
  • -vcodec libx264 将源流编码为h264,并进行广播。
  • -crf 0 将“constant rate factor”(量化器刻度)设置为0,表示无损。
  • -preset ultrafast 表示我们没有耐心,所以尽可能少地使用压缩。这会导致高比特率,但对于我的目的来说没问题。
  • -f mpegts 选项告诉ffmpeg使用MPEG-TS数据包,这将“强制”ffmpeg使用恒定比特率的MPEG格式,因为MPEG本身通常是可变比特率。
  • 最后一个选项udp://239.255.12.42:6666指定我们想要将此流广播到组播地址239.255.12.42,并使用端口6666通过UDP进行传输。我之所以选择在这里使用多播地址,仅仅是因为我需要同时显示(预览)和记录流,尽可能少地进行处理。这样可以避免我必须将音频和视频流复制到两个不同的网络地址中。

要使用VLC播放器捕获此视频,我打开以下网络流地址:

udp://@239.255.12.42:6666

最后,为了记录流,我会生成一个新的进程并发出以下命令:

ffmpeg -y -threads 4 -i udp://239.255.12.42:6666 -map 0 -acodec copy -vcodec copy output.mkv
  • -y选项用于总是覆盖文件,如果文件存在而不需要询问。
  • -threads 4选项会使用4个线程。
  • -i udp://239.255.12.42:6666连接到我们正在广播的流。
  • -map 0告诉ffmpeg我们需要所有流(包括视频和音频)。
  • -acodec copy-vcodec copy确保流按原样采取,而不进行任何压缩/转码。

唯一剩下要做的事情是(目前正在进行中)为此创建一个C# GUI。基本工作流程是在窗体加载时生成流程进程。使用vlc com+控件在应用程序中显示视频。

然后当记录按钮被按下时,生成另一个进程来记录并停止该进程以结束录制。

但是我会在开始录制时停止流,这将使录制/检测变得更加平稳。如果流保持开启并且我开始录制,则录制过程需要一些时间才能“调整”到流上。通过停止流,开始录制(在流回来之前不会发生任何事情),然后再次启动流,录制将从第一帧开始进行而没有任何问题。

对于我的目的来说,这种小延迟/闪烁是完全可以接受的。


你能测量延迟时间吗?它超过100毫秒还是秒? - user1767754
-acodec copy -vcodec copy 可以被简化为 -c copy - Yay295
@Huron,你使用的是哪个版本的FFmpeg?我使用了你的命令行,但输出的output.mkv保存为黑色视频。你有特殊的FFmpeg构建吗? - Mehmed
1
我当时使用的是最新的Zeranoe FFmpeg Build版本,您可以在这里找到它们:http://ffmpeg.zeranoe.com/builds/但每当我遇到黑屏问题时,都是由于源视频和videosize/framerate选项不匹配造成的。因此,请务必检查这些选项。 - Huron
你也可以尝试使用-f decklink -i "BlackMagic SDI (1)@1"@后面的数字是输入端口)代替-f dshow...。我们在使用你的方法时遇到了音频无法工作的问题。 - mbirth
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接