我搭建了一个从摄像头读取视频流然后目标检测后再推流的框架,现在我想进行16路推流。
我试了一下发现最多只能推出8路视频流,下图是7路视频流的情况,一切正常。
但是在8路视频流时出现问题
我查看手册,说是编码器通道0-31都可以。
现在想请问一下,是不是理论上可以推32*8=256路,还是说整个板子只能推8路视频流。
以下是我的相关代码,希望有大佬和官方大佬进行解答,谢谢各位 :
class RtspYoloEncoder:
def __init__(self, rtsp_stream, rtsp_url, encode_channel):
self.rtsp_stream = rtsp_stream
self.encode_queue = queue.Queue(maxsize=5)
self.encoder_thread = EncoderThread(self.encode_queue, rtsp_stream.width, rtsp_stream.height, rtsp_url, encode_channel)
def start(self):
self.encoder_thread.start()
def stop(self):
self.encoder_thread.stop()
def enqueue(self, frame):
if not self.encode_queue.full():
self.encode_queue.put(frame.copy())
class EncoderThread(threading.Thread):
def __init__(self, encode_queue, width, height, rtsp_url, encode_channel):
super().__init__()
self.encode_queue = encode_queue
self.width = width
self.height = height
self.rtsp_url = rtsp_url
self.running = True
self.encode_channel = encode_channel
# 启动 ffmpeg 子进程进行 RTSP 推流
self.ffmpeg_process = subprocess.Popen(
[
'ffmpeg',
'-f', 'h264',
'-i', '-', # 从 stdin 读取 H.264 数据
'-c:v', 'copy', # 直接复制 H.264 流
'-f', 'rtsp',
'-rtsp_transport', 'tcp',
rtsp_url # 目标 RTSP 地址
],
stdin=subprocess.PIPE
)
# 初始化编码器
self.encoder = srcampy.Encoder()
self.encoder.encode(self.encode_channel, 1, self.width, self.height)
def run(self):
global is_stop
start = time()
count = 0
while self.running or not self.encode_queue.empty():
if is_stop and self.encode_queue.empty():
break
try:
frame = self.encode_queue.get(timeout=0.5)
except queue.Empty:
continue
try:
yuv = cv2.cvtColor(frame, cv2.COLOR_BGR2YUV_I420)
h, w = frame.shape[:2]
y = yuv[0:h, :]
u = yuv[h:h + h // 4, :].reshape(h // 2, w // 2)
v = yuv[h + h // 4:, :].reshape(h // 2, w // 2)
uv = np.empty((h // 2, w), dtype=np.uint8)
uv[:, 0::2] = u
uv[:, 1::2] = v
nv12 = np.vstack((y, uv))
ret = self.encoder.encode_file(nv12.tobytes())
if ret == 0:
out = self.encoder.get_img()
if out:
self.ffmpeg_process.stdin.write(out)
self.ffmpeg_process.stdin.flush()
count += 1
except Exception as e:
print("Encoder thread error:", e)
if time() - start >= 5:
print("Encode FPS:", count / 5)
count = 0
start = time()
def stop(self):
self.running = False
self.join()
self.encoder.close()
self.ffmpeg_process.stdin.close()
self.ffmpeg_process.terminate()
try:
self.ffmpeg_process.wait(timeout=2)
except subprocess.TimeoutExpired:
self.ffmpeg_process.kill()
print("FFmpeg process terminated.")
if __name__ == '__main__':
rtsp_url = "rtsp://admin:Xyh523523@192.168.30.64/102"
is_stop = False
signal.signal(signal.SIGINT, signal_handler)
print(rtsp_url)
vdec_chan = 0
rtsp_stream = DecodeRtspStream(rtsp_url)
ret = rtsp_stream.open(vdec_chan, 1)
if ret != 0:
quit(ret)
rtsp_stream.start()
# 创建多个 RtspYoloEncoder 实例
rtsp_urls = [
"rtsp://192.168.3.33:8554/test1",
"rtsp://192.168.3.33:8554/test2",
"rtsp://192.168.3.33:8554/test3",
"rtsp://192.168.3.33:8554/test4",
"rtsp://192.168.3.33:8554/test5",
"rtsp://192.168.3.33:8554/test6",
"rtsp://192.168.3.33:8554/test7",
"rtsp://192.168.3.33:8554/test8",
# "rtsp://192.168.3.33:8554/test9",
# "rtsp://192.168.3.33:8554/test10",
# "rtsp://192.168.3.33:8554/test11",
# "rtsp://192.168.3.33:8554/test12",
# "rtsp://192.168.3.33:8554/test13",
# "rtsp://192.168.3.33:8554/test14",
# "rtsp://192.168.3.33:8554/test15",
# "rtsp://192.168.3.33:8554/test16"
]
# 分配编码通道
encoder_channels = [0]*8
encoder_managers = [RtspYoloEncoder(rtsp_stream, url, channel) for url, channel in zip(rtsp_urls, encoder_channels)]
for encoder in encoder_managers:
encoder.start()
while not is_stop:
frame = rtsp_stream.get_frame()
if frame is not None:
bgr_frame = nv12_to_bgr(frame, rtsp_stream.width, rtsp_stream.height)
detect_and_display(bgr_frame)
for encoder in encoder_managers:
encoder.enqueue(bgr_frame)
else:
sleep(0.01)
for encoder in encoder_managers:
encoder.stop()