输出视频:https://youtu.be/VxfoBQjoY6E
解释:
我想:在Opencv中处理相机流,并将其推送到RTMP服务器。我已经设置了NGINX(RTMP模块),我已经用RTMP(Flash Player)和HLS测试了流媒体视频。
我正在循环中读取帧,并使用python中的"subprocess"来执行ffmpeg命令。这是我正在使用的命令:
command = [ffmpeg,
'-y',
'-f', 'rawvideo',
'-vcodec','rawvideo',
'-pix_fmt', 'bgr24',
'-s', dimension,
'-i', '-',
'-c:v', 'libx264',
'-pix_fmt', 'yuv420p',
'-preset', 'ultrafast',
'-f', 'flv',
'rtmp://10.10.10.80/live/mystream']
import subprocess as sp
...
proc = sp.Popen(command, stdin=sp.PIPE,shell=False)
...
proc.stdin.write(frame.tostring()) #frame is read using opencv
问题:
我可以很好地看到这条小溪,但它经常结冰并恢复。以下是FFMPEG终端日志的输出:
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
frame= 117 fps= 16 q=22.0 size= 344kB time=00:00:04.04 bitrate= 697.8kbits/s speed=0.543x
最后提到了速度。我认为应该接近1x。我不知道如何做到这一点。
我和服务器在同一个网络上,如果需要,我可以发布我的python代码。需要一些ffmpeg大师给我一些建议。
编辑
我的输入fps实际上是~3。使用'-use_wallclock_as_timestamps', '1'
,我可以在日志中看到速度接近1x。但HLS并没有进行直播,有大约2分钟的延迟,它暂停了。克里斯的建议部分奏效了。我不确定问题到底出在哪里,我开始相信这与nginxrtmp模块有关。
这是最后的输出,左边是闪光,右边是hls。我在最后展示了ffmpeg选项。https://youtu.be/jsm6XNFOUE4
我以前在流式传输原始视频(就像你一样)或MJPEG源时遇到过类似的问题。有两种输入选项可以尝试使用ffmpeg使其保持1x速度:
选项1
ffmpeg -re -i <rest of input options>
-re
告诉ffmpeg以本机输入速率进行读取
选项2
ffmpeg -use_wallclock_as_timestamps 1 -i <rest of input options>
-use_wallclock_as_timestamps
告诉ffmepg只在每一帧进入时取一帧,取系统时间,并将其作为时间戳。我发现当速度降下来时,这个选项最有效。
不管怎样
请确保以恒定的帧速率进行编码。当帧速率变化时,ffmpeg可能会变得有点挑剔,所以在输出选项上,使用-r 25
(将25替换为所需的输出帧速率)来强制ffmpeg使用静态帧速率输出
我认为最简单的方法是使用MoviePy模块(顺便说一句,我觉得它很棒)。看一下MoviePy视频编剧。它应该写入本地文件,但您也可以通过在命令末尾添加-f flv
来指定输出格式,将其与rtmp流一起使用。要将帧写入流,只需使用方法write_frame(your_frame)
即可。它对我来说运行得很好
我遇到了同样的问题,发现ffmpeg无法自动填补空白,所以当你以3帧/秒的速度馈送ffmpeg时,客户端仍将以25帧/秒播放,因此客户端需要在播放前缓存大量帧,然后快速播放,然后停下来再次缓存帧
因此,当你给ffmpeg提供这样的代码时,很容易填补空白
timeStart = get_time_seconds()
count = 0
some loop:
frame = getimage()
targetCount = (get_time_seconds()-timeStart)*25
repeatCount = targetCount - count
loop for repeatCount times:
proc.stdin.write(frame.tostring())
count = targetCount