Python Socket程序中视频播放1秒后卡顿的问题排查与解决
问题分析与解决方案
核心问题
- 服务器端阻塞导致视频卡顿:原代码内层
while True循环持续阻塞在s.accept(),完全卡住了视频帧的读取与渲染流程,视频自然无法正常播放,客户端只能拿到第一帧的1.0。 - 缺少OpenCV窗口事件处理:原代码没有
cv2.waitKey(),即便移除Socket代码,视频窗口也会因为未处理GUI事件而无响应。 - 客户端单次连接限制:原客户端仅连接一次就关闭,无法持续获取更新的timestamp。
修复后的代码
服务器端(多线程分离视频与Socket服务)
import cv2 import socket import threading # 全局变量存储当前帧timestamp,线程锁保证读写安全 current_frame = 0.0 frame_lock = threading.Lock() def video_player(): global current_frame cap = cv2.VideoCapture("D:/video.mp4") if not cap.isOpened(): print("Error opening video file") return try: while cap.isOpened(): ret, frame = cap.read() if ret: cv2.imshow("Frame", frame) # 加锁更新当前帧timestamp with frame_lock: current_frame = cap.get(cv2.CAP_PROP_POS_FRAMES) # 控制播放帧率,40ms对应约25fps,可根据视频实际帧率调整 if cv2.waitKey(40) & 0xFF == ord('q'): break else: # 视频循环播放 cap.set(cv2.CAP_PROP_POS_FRAMES, 0) continue finally: cap.release() cv2.destroyAllWindows() def socket_server(): global current_frame s = socket.socket() port = 12345 s.bind(('', port)) s.listen(5) print(f"Socket bound to {port}, listening...") try: while True: # 阻塞等待客户端连接,但不影响视频线程运行 c, addr = s.accept() print(f'Got connection from {addr}') # 加锁读取当前timestamp并发送 with frame_lock: frame_data = str(current_frame).encode("utf-8") c.sendall(frame_data) c.close() except Exception as e: print(f"Socket error: {e}") finally: s.close() if __name__ == "__main__": # 启动两个独立线程 video_thread = threading.Thread(target=video_player) server_thread = threading.Thread(target=socket_server) video_thread.start() server_thread.start() video_thread.join() server_thread.join()
客户端(持续获取timestamp版本)
import socket import time s = socket.socket() port = 12345 try: s.connect(('localhost', port)) print("Connected to server") # 持续拉取最新timestamp,间隔可自定义 while True: data = s.recv(32).decode().strip() if data: print(f"Current video frame: {data}") time.sleep(1) except Exception as e: print(f"Client error: {e}") finally: s.close()
关键修改说明
- 多线程分离:将视频播放与Socket服务拆分为两个独立线程,避免互相阻塞,保证视频流畅播放的同时响应客户端请求。
- 线程安全控制:用
threading.Lock()保护全局变量current_frame,避免多线程读写冲突。 - OpenCV事件处理:加入
cv2.waitKey()处理窗口事件,解决视频窗口无响应问题,同时支持按q退出播放。 - 客户端持续请求:修改为循环接收逻辑,可实时获取视频最新的timestamp。
内容的提问来源于stack exchange,提问作者Monty Swanson
相关产品推荐
相关产品推荐

