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

Flask屏幕共享应用白屏加载异常,请求代码排查

Flask屏幕共享应用白屏问题排查与修复

代码中的核心问题

  • 错误启动线程调用路由函数:主函数里的线程启动代码完全多余,screen_sharing是Flask路由函数,只有客户端请求/screen_sharing时才会触发,直接通过线程调用会在无请求上下文的情况下执行,还会提前阻塞Socket连接,毫无实际作用。
  • Socket接收逻辑阻塞请求:generate_frames里的内层循环会一直调用recv直到返回空包,这意味着只有当Socket连接断开时才会进入帧处理步骤。如果服务端持续发送数据,这个循环会无限等待,永远不会解码帧,导致网页请求一直挂起,出现白屏。
  • 缺少对应服务端发送数据:你的代码只有Flask客户端部分,没有实现屏幕捕获并发送帧数据的服务端程序。没有服务端的情况下,client_socket.recv会一直阻塞,请求永远得不到响应。
  • Socket连接无异常处理:连接服务端时没有设置超时或错误处理,一旦服务端未启动,请求会一直挂起,没有任何报错提示。

修复步骤

  1. 删除无用线程代码:把主函数里的线程启动相关代码全部删掉,Flask会自动处理路由请求。
  2. 修改Socket帧接收逻辑:和服务端约定帧传输格式,先发送帧的长度,再发送帧数据,避免无限等待:
import struct  # 需要导入struct模块

@app.route('/screen_sharing')
def screen_sharing():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.settimeout(5)
    try:
        client_socket.connect(('192.168.1.112', 5000))
    except Exception as e:
        print(f"连接失败: {str(e)}")
        return Response("无法连接到屏幕共享服务", status=500)
    client_socket.settimeout(None)

    def generate_frames():
        while True:
            try:
                # 接收帧长度(4字节大端格式)
                len_bytes = client_socket.recv(4)
                if not len_bytes:
                    break
                frame_len = struct.unpack('!I', len_bytes)[0]
                
                # 接收完整帧数据
                data = b''
                while len(data) < frame_len:
                    chunk = client_socket.recv(min(4096, frame_len - len(data)))
                    if not chunk:
                        break
                    data += chunk
                
                if len(data) != frame_len:
                    continue
                
                frame = np.frombuffer(zlib.decompress(data), dtype=np.uint8)
                frame = cv2.imdecode(frame, 1)
                
                if frame is not None:
                    _, buffer = cv2.imencode('.jpg', frame)
                    yield (b'--frame\r\n'
                           b'Content-Type: image/jpeg\r\n\r\n' + buffer.tobytes() + b'\r\n')
            except Exception as e:
                print(f"帧处理错误: {str(e)}")
                client_socket.close()
                break
    return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
  1. 编写对应服务端代码:使用mss捕获屏幕,压缩后按约定格式发送数据:
import socket
import zlib
import struct
from mss import mss
import cv2
import numpy as np

SERVER_IP = '0.0.0.0'
SERVER_PORT = 5000

def send_screen_frames(conn):
    with mss() as sct:
        monitor = sct.monitors[1]  # 捕获主屏幕
        while True:
            try:
                img = sct.grab(monitor)
                frame = np.array(img)
                frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
                
                _, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 80])
                compressed_data = zlib.compress(buffer.tobytes())
                
                # 发送帧长度和数据
                conn.sendall(struct.pack('!I', len(compressed_data)))
                conn.sendall(compressed_data)
            except Exception as e:
                print(f"服务端错误: {str(e)}")
                break

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((SERVER_IP, SERVER_PORT))
    s.listen()
    print(f"服务端监听 {SERVER_IP}:{SERVER_PORT}")
    conn, addr = s.accept()
    with conn:
        print(f"客户端连接: {addr}")
        send_screen_frames(conn)
  1. 开启Flask多线程模式:修改app.run为app.run(host='0.0.0.0', port=5000, threaded=True),支持同时处理页面请求和帧流传输。

内容的提问来源于stack exchange,提问作者Hassan Shehzad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 10:58:14