问题
如何通过 FFmpeg、mediamtx、ncat、管道、隧道或它们的任意组合将运行 Raspberry Pi OS 的远程 Raspberry Pi 4B 上的 USB 网络摄像头的原始视频和音频流式复制到运行 Windows 11 的计算机上的 FFmpeg(或文件!)?最好是 FFmpeg 或 mediamtx。
目标
在 Raspberry Pi 上,从“/dev/video0”流式复制原始视频,从“plughw:CARD=CameraB409241,DEV=0”流式复制或 PCM 编码音频到远程机器,而无需保存到 Pi 的磁盘或在 Pi 上编码视频。
为什么不直接在 Pi 上编码呢?
网络上有机器在等待工作,所以我宁愿将 Pi 的 CPU 用于其他用途。Pi 通过 USB 连接到 SSD 和网络摄像头;从 USB 摄像头读取数据并将原始文件写入 SSD 占用了很大一部分可用 USB 带宽。
笔记
相机是 PS3Eye;YUYV422、640x480 @ 60Hz / 320x240 @ 187Hz
Raspberry Pi 上的 FFmpeg 版本 5.1.3-1+rpt4(apt 安装,未构建)。Windows 11 上的最新 FFmpeg 版本。
Raspberry Pi 上最新的(截至 11 月 14 日)mediamtx 和最新的 Nmap/Ncat。Windows 11 上最新的 mediamtx 和 Windows 二进制安装版本的 Nmap/Ncat。
FFmpeg 和 Ncat 被允许通过防火墙。
像素格式似乎在某些命令中给我带来了麻烦。RTSP 似乎特别不喜欢它(YUYV422)。
似乎很接近
在 mediamtx.yml 中
runOnInit: FFmpeg -use_wallclock_as_timestamps 1 -thread_queue_size 1024 -f alsa -i "plughw:CARD=CameraB409241,DEV=0" -f v4l2 -framerate 187 -video_size 320x240 -thread_queue_size 1024 -i /dev/video0 -c:v copy -c:a copy -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH
在 Pi 上本地输出 .mkv 时,此命令在 FFmpeg 中有效。在 -f rtsp 或 mediamtx 中,它会出现以下错误;
2023/11/15 01:28:18 INF [RTSP] [conn [::1]:33070] opened
[rtsp @ 0x7fe534f318] Unsupported pixel format.
2023/11/15 01:28:18 INF [RTSP] [conn [::1]:33070] closed: EOF
在 mediamtx.yml 中
runOnInit: FFmpeg -use_wallclock_as_timestamps 1 -thread_queue_size 1024 -f alsa -i "plughw:CARD=CameraB409241,DEV=0" -f rawvideo -pix_fmt yuv420p -framerate 187 -video_size 320x240 -i /dev/video0 -c:v copy -c:a pcm_s16be -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH
该命令在 mediamtx 和 FFmpeg 中有效,但由于传递给 ffmpeg 的输入摄像头的像素格式错误,导致视频损坏。
终端
cat /dev/video0 | ncat 192.1.1.250 9999
确实会将数据(以及 YUYV422、rawvideo、480p @ 60Hz 的正确数量)发送到监听机器 ncat(充斥终端),但我不知道如何以可用格式保存这些数据。使用 -o 或不使用附加选项都不会产生可用文件。
我感觉我已经很接近了,但却缺少了一些简单的东西。
更新
我基本上已经解决了这个问题;是我考虑得太多了。
以下命令通过 FFmpeg 和 UDP 直接从我的 Raspberry Pi 网络摄像头流复制 rawvideo 和 pcm 音频。
对于传输 FFmpeg 客户端,在我的情况下是 Raspberry Pi;
ffmpeg -use_wallclock_as_timestamps 1 -thread_queue_size 1024 -f alsa -i "plughw:CARD=CameraB409241,DEV=0" -video_size 640x480 -thread_queue_size 1024 -i /dev/video0 -c:v copy -c:a copy -f matroska udp://ReceiverIP:port
对于接收 FFmpeg 客户端,在我的情况下是 Windows 11;
ffmpeg -use_wallclock_as_timestamps 1 -f matroska -i udp://TrasnmitterIP:port -c:v copy -c:a copy Output.mkv
这几乎完美地工作了。我还没有让 TCP 工作。考虑到 UDP 的性质,我并不认为这个问题已经解决了。对于以后尝试类似方法的人,顺便提一下,您可以使用以下命令在接收端自动分割输出视频;
-f segment -segment_time 300 -reset_timestamps 1 Output_%03d
这会将输出文件分割成 300 秒的剪辑,并逐步增加文件名。-segment_time 300
根据需要更改文件名。
例子;
ffmpeg -use_wallclock_as_timestamps 1 -f matroska -i udp://TrasnmitterIP:port -c:v copy -c:a copy -f segment -segment_time 300 -reset_timestamps 1 Output_%03d.mkv
如果这向您发出有关非单调 DTS 错误的警告,请尝试删除-use_wallclock_as_timestamps 1
和/或-reset_timestamps
。