Python中使用Tkinter实现多路IP视频GUI显示及卡顿问题解决
多路IP视频GUI播放解决方案
卡顿原因说明
- 原有代码为单线程串行拉流、处理3路视频,每路的IO等待、计算都会阻塞后续视频的处理,路数越多卡顿越明显
- cv2.imshow多独立窗口渲染会额外消耗渲染资源,也会加剧卡顿
- 改用多线程独立拉流+Tkinter单窗口聚合展示即可解决卡顿问题,同时支持4路及以上视频播放
可直接运行的代码
import cv2 import tkinter as tk from PIL import Image, ImageTk import threading from queue import Queue # 配置参数 CAM_COUNT = 4 # 视频路数,可根据需求调整 FRAME_WIDTH = 360 # 单路视频宽度,4路2*2排列总宽度720 FRAME_HEIGHT = 270 # 单路视频高度,可根据实际视频比例调整 STREAM_URLS = [ "你的第一路IP视频地址", "你的第二路IP视频地址", "你的第三路IP视频地址", "你的第四路IP视频地址" ] # 每路视频对应一个队列存储最新帧 frame_queues = [Queue(maxsize=1) for _ in range(CAM_COUNT)] # 全局运行标记 running = True def stream_worker(cam_idx, url): """单路视频拉流线程,独立拉流不阻塞主线程""" cap = cv2.VideoCapture(url) while running and cap.isOpened(): ret, frame = cap.read() if not ret: # 拉流失败自动重试,可根据需求调整重试逻辑 cap.release() cap = cv2.VideoCapture(url) continue # 提前在子线程做resize,减少主线程计算压力 frame = cv2.resize(frame, (FRAME_WIDTH, FRAME_HEIGHT)) # 队列仅保留最新帧,旧帧直接丢弃避免延迟累积 if not frame_queues[cam_idx].empty(): try: frame_queues[cam_idx].get_nowait() except: pass frame_queues[cam_idx].put(frame) cap.release() def update_frame(): """主线程更新UI界面""" for cam_idx in range(CAM_COUNT): if not frame_queues[cam_idx].empty(): frame = frame_queues[cam_idx].get() # OpenCV的BGR格式转RGB适配PIL frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = Image.fromarray(frame_rgb) imgtk = ImageTk.PhotoImage(image=img) # 更新对应展示组件的图像 label_list[cam_idx].imgtk = imgtk label_list[cam_idx].configure(image=imgtk) # 每20ms刷新一次,对应50fps刷新率 root.after(20, update_frame) def on_closing(): """窗口关闭回调,释放所有资源""" global running running = False root.destroy() if __name__ == "__main__": # 启动所有拉流子线程 for i in range(CAM_COUNT): t = threading.Thread(target=stream_worker, args=(i, STREAM_URLS[i]), daemon=True) t.start() # 初始化Tkinter主窗口 root = tk.Tk() root.title("4路IP视频监控") root.protocol("WM_DELETE_WINDOW", on_closing) # 创建4路视频展示Label,默认2行2列排列 label_list = [] for row in range(2): for col in range(2): label = tk.Label(root) label.grid(row=row, column=col, padx=2, pady=2) label_list.append(label) # 启动UI刷新逻辑 update_frame() root.mainloop()
使用说明
- 运行前需安装依赖:
pip install opencv-python pillow - 将
STREAM_URLS列表中的地址替换为你实际的IP摄像头拉流地址即可 - 可修改
CAM_COUNT参数调整视频路数,同步调整Label的排列逻辑即可支持更多路播放 - 关闭窗口即可自动释放所有摄像头资源退出程序
内容的提问来源于stack exchange,提问作者Ansh Tyagi
相关产品推荐
相关产品推荐

