You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 23:45:03