我有以下代码创建一个gstreamer管道来处理HLS流。
cap = cv2.VideoCapture(
f"souphttpsrc is_live=true location={hls_stream_link} ! hlsdemux !
queue ! decodebin ! videorate ! video/x-raw,framerate=1/1 !
videoconvert ! appsink max-buffers=1 drop=true sync=false",
cv2.CAP_GSTREAMER)
我现在这样读取流:
while True:
success, frame = cap.read()
time.sleep(1.0)
注意,我以1 FPS的速度读取流,并且具有属性max-buffers=1 drop=true sync=false
。这样,我总是从缓冲区必须提供的流中获取最新的帧。
与此有关的问题是CPU使用率非常高,在我的i7机器上有时达到120%。取消睡眠会使情况变得更糟。
关于为何处理HLS流如此之多的CPU密集度的任何解决方案或想法都是很不错的。同样,关于减少使用量的想法也很棒。
答案 0 :(得分:1)
您正在解码完整的流。用软件完成时,这可能会非常昂贵。我在这里看到的一个潜在的优化步骤是在解码器之前添加GstPadProbe
并将一个比特解析为比特流,并丢弃所有非IDR的样本。然后,您将仅将IDR帧发送到解码器。这样做会减少解码器的负载,但是只有在每个IDR帧间隔(通常为每2秒(但可能在每个之间可能有所不同))之后,您才会得到一个新帧。
答案 1 :(得分:0)
您的应用程序出现峰值的一个原因可能是由于读取帧时的I / O延迟。 cv2.VideoCapture().read()
是一项阻止操作,因此您的程序将停顿,直到从流中读取一帧为止。一种提高性能的方法是生成另一个线程以 parallel 的方式处理抓帧,而不是依赖单个线程以 sequential 的顺序抓帧。通过指定一个仅轮询新帧的单独线程,可以提高性能,因为您的主线程可以执行其他操作。
from threading import Thread
import time
def read_frames():
while True:
if cap.isOpened():
success, frame = cap.read()
time.sleep(1)
thread = Thread(target=read_frames, args=())
thread.daemon = True
thread.start()