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

如何基于Flask采用h264编码实现PC摄像头视频流传输

Flask 实现PC摄像头H264实时流推送方案

全程规避MJPEG逐帧传输方案,编码后码率可控制在500kbps-2Mbps,完全适配4G窄带传输场景,端到端延迟可稳定在1s以内。

核心配置前提

你已经完成H264编解码环境配置、可正常输出H264编码帧的基础上,只需要解决Flask响应透传、码流低延迟参数配置、前端播放适配三个核心问题,不需要额外引入重型流媒体服务。

  • 编码侧统一开低延迟编码参数:关闭B帧,GOP长度设为和帧率一致(比如25帧就设GOP=25),用CBR码率控制,避免码率波动抢占4G带宽
  • Flask侧关闭响应缓存,用生成器逐帧返回码流,开启多线程模式避免请求阻塞
  • 前端用MSE做H264裸流适配,不需要引入额外第三方播放库

可直接运行的实现代码

from flask import Flask, Response, render_template_string
import cv2
import time

app = Flask(__name__)

# 初始化PC摄像头
cap = cv2.VideoCapture(0)
# 配置H264编码输出,如果你已有验证可用的自定义H264编码逻辑,可跳过这部分OpenCV编码配置
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'H264'))
cap.set(cv2.CAP_PROP_FPS, 25)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

def h264_stream_generator():
    # 输出码流起始标识,方便播放器识别解码起点
    yield b'\x00\x00\x00\x01'
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        # 替换为你自己的H264编码逻辑即可,直接返回编码后的字节数据
        # 以下是OpenCV内置H264编码的低延迟参数配置
        encode_params = [
            cv2.IMWRITE_FFMPEG_FLAGS,
            '-tune zerolatency',  # 零延迟调优
            '-b:v 1M',  # 码率1Mbps,4G场景可按需降到500k
            '-g 25',  # GOP长度和帧率一致
            '-bf 0'  # 关闭B帧
        ]
        ret, h264_frame = cv2.imencode('.h264', frame, encode_params)
        if not ret:
            continue
        yield h264_frame.tobytes()
        # 按配置帧率控制发送节奏,避免突发流量占满带宽
        time.sleep(1/25)

@app.route('/stream.h264')
def stream_endpoint():
    return Response(
        h264_stream_generator(),
        mimetype='video/h264',
        direct_passthrough=True,  # 核心参数:关闭Flask响应缓存,直接透传二进制流
        headers={
            'Cache-Control': 'no-cache, no-store, must-revalidate',
            'Pragma': 'no-cache',
            'Expires': '0',
            'Transfer-Encoding': 'chunked'
        }
    )

# 内置播放页面,不需要额外静态文件
@app.route('/')
def player_page():
    return render_template_string('''
    <!DOCTYPE html>
    <html>
    <body>
        <video id="livePlayer" autoplay muted controls width="1280" height="720"></video>
        <script>
            const player = document.getElementById('livePlayer');
            const codecType = 'video/mp4; codecs="avc1.42E01E"';
            if (window.MediaSource && MediaSource.isTypeSupported(codecType)) {
                const ms = new MediaSource();
                player.src = URL.createObjectURL(ms);
                ms.addEventListener('sourceopen', () => {
                    URL.revokeObjectURL(player.src);
                    const sb = ms.addSourceBuffer(codecType);
                    fetch('/stream.h264').then(res => {
                        const reader = res.body.getReader();
                        const pushFrame = ({done, value}) => {
                            if (done) {
                                ms.endOfStream();
                                return;
                            }
                            if (!sb.updating) sb.appendBuffer(value);
                            reader.read().then(pushFrame);
                        }
                        reader.read().then(pushFrame);
                    })
                })
            } else {
                alert('当前浏览器不支持H264硬解播放');
            }
        </script>
    </body>
    </html>
    ''')

if __name__ == '__main__':
    # 必须开多线程,否则流请求会阻塞其他接口
    app.run(host='0.0.0.0', port=5000, debug=False, threaded=True)

常见问题排查

  • 播放花屏/绿屏:检查编码器是否关闭B帧,确认每个GOP第一帧为IDR关键帧,否则播放器中途接入无法正常解码
  • 延迟过高:调小GOP长度,关闭B帧,把码率控制模式改成CBR,不要用VBR
  • 流卡顿/4G下加载慢:把分辨率降到720p/480p,码率降到500kbps-800kbps,相比MJPEG方案可节省70%以上带宽
  • 接口无响应:确认启动时加了threaded=True参数,不要用Flask默认单线程模式
  • 已有自定义编码逻辑:不需要用OpenCV做二次编码,直接把你编码输出的H264字节数据通过生成器yield返回即可,支持Annex-B格式裸流

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 08:03:22