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

如何提升TCP套接字传输2K视频的速度?含YOLO处理优化

优化TCP视频传输+YOLO处理性能方案

当前核心瓶颈

  • 2K帧通过pickle序列化后体积过大(单帧约10MB),TCP传输带宽占用高、延迟显著
  • YOLO属于计算密集型任务,单线程下接收帧与处理帧串行执行,进一步放大卡顿问题

以下是针对性的优化方案:


1. 替换帧序列化方式:用图像编码替代Pickle

pickle会完整保存像素数组,而JPEG编码可将2K帧压缩至几百KB,直接减少90%以上的传输数据量。

服务器端修改

import socket, cv2, struct, imutils

# Socket Create
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_name  = socket.gethostname()
host_ip ='192.168.xx.xxx'
print('HOST IP:',host_ip)
port = 1234
socket_address = (host_ip,port)
source = 'video.mp4'
# Socket Bind
server_socket.bind(socket_address)

# Socket Listen
server_socket.listen(5)
print("LISTENING AT:",socket_address)

# Socket Accept
while True:
    client_socket,addr = server_socket.accept()
    print('GOT CONNECTION FROM:',addr)
    if client_socket:
        vid = cv2.VideoCapture(source)
                
        while(vid.isOpened()):
            ret, frame = vid.read()
            if not ret:
                break
            # 压缩帧为JPEG,quality参数0-100,值越小压缩率越高
            _, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 70])
            # 打包数据长度+压缩帧
            message = struct.pack("Q", len(buffer)) + buffer.tobytes()
            client_socket.sendall(message)
            
            cv2.imshow('TRANSMITTING VIDEO', frame)
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                client_socket.close()
                break
        vid.release()
cv2.destroyAllWindows()

客户端修改

import socket,cv2, struct, numpy as np

# create socket
client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host_ip = '192.168.xx.xxx'
port = 1234
client_socket.connect((host_ip,port))
data = b""
payload_size = struct.calcsize("Q")

while True:
    while len(data) < payload_size:
        packet = client_socket.recv(4096)
        if not packet: break
        data += packet

    packed_msg_size = data[:payload_size]
    data = data[payload_size:]
    msg_size = struct.unpack("Q", packed_msg_size)[0]
    
    while len(data) < msg_size:
        data += client_socket.recv(4096)
    frame_data = data[:msg_size]
    data  = data[msg_size:]
    # 解码JPEG帧
    frame = cv2.imdecode(np.frombuffer(frame_data, dtype=np.uint8), cv2.IMREAD_COLOR)
    
    # 后续加入YOLO处理(建议放在单独线程)
    # runYolo(frame)
    
    cv2.imshow("RECEIVING VIDEO",frame)
    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'):
        break
client_socket.close()
cv2.destroyAllWindows()

2. 分离接收与YOLO处理:多线程并行解耦

YOLO单帧处理耗时较长,单线程会阻塞帧接收。用队列+多线程实现"接收-处理"并行:

客户端多线程版本

import socket,cv2, struct, numpy as np
from threading import Thread
from queue import Queue

# 帧队列,最大缓存10帧避免内存溢出
frame_queue = Queue(maxsize=10)

def receive_frames():
    client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    host_ip = '192.168.xx.xxx'
    port = 1234
    client_socket.connect((host_ip,port))
    data = b""
    payload_size = struct.calcsize("Q")

    while True:
        while len(data) < payload_size:
            packet = client_socket.recv(4096)
            if not packet: 
                frame_queue.put(None) # 发送结束信号
                client_socket.close()
                return
            data += packet

        packed_msg_size = data[:payload_size]
        data = data[payload_size:]
        msg_size = struct.unpack("Q", packed_msg_size)[0]
        
        while len(data) < msg_size:
            data += client_socket.recv(4096)
        frame_data = data[:msg_size]
        data  = data[msg_size:]
        frame = cv2.imdecode(np.frombuffer(frame_data, dtype=np.uint8), cv2.IMREAD_COLOR)
        
        # 队列未满则放入,满了丢弃旧帧避免阻塞接收
        if not frame_queue.full():
            frame_queue.put(frame)

def process_frames():
    # 初始化YOLO模型(仅初始化一次)
    def runYolo(frame):
        # 替换为你的YOLO检测逻辑
        processed_frame = frame 
        return processed_frame

    while True:
        frame = frame_queue.get()
        if frame is None: # 接收线程结束
            break
        # 处理帧
        processed_frame = runYolo(frame)
        # 显示处理结果
        cv2.imshow("PROCESSED VIDEO", processed_frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

# 启动双线程
recv_thread = Thread(target=receive_frames)
process_thread = Thread(target=process_frames)
recv_thread.start()
process_thread.start()

recv_thread.join()
process_thread.join()

3. YOLO模型与推理优化

这是降低处理延迟的核心:

  • 用轻量化模型:选择YOLOv5n、YOLOv8n等nano版本,推理速度比大模型快5-10倍
  • 启用GPU加速:有NVIDIA显卡时,用PyTorch CUDA或OpenCV DNN的CUDA后端,推理速度提升数倍
  • 降低输入分辨率:将2K帧resize到640×640再喂模型,大幅提升推理速度(精度可接受的前提下)
  • 减少推理频率:每2-3帧检测一次,用前一次结果补帧,平衡速度与精度

4. 可选:改用UDP传输(牺牲可靠性换实时性)

TCP的重传机制会在丢包时拖慢速度,视频对少量丢包容忍度高,可尝试UDP:

  • 服务器端用socket.SOCK_DGRAM替代SOCK_STREAM,直接发送压缩帧
  • 客户端绑定端口接收,无需建立连接
  • 注意:UDP可能丢帧,适合实时性优先的场景

内容的提问来源于stack exchange,提问作者Yadu S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:02:08