【Flask-9】加载视频流

app.py伪代码:

复制代码
RTSP_URL = rtsp://*.*.*.*:*/video
video_capture = None

def init_video_stream():
    """初始化视频流"""
    global video_capture
    try:
        video_capture = cv2.VideoCapture(RTSP_URL)
        video_capture.set(cv2.CAP_PROP_BUFFERSIZE, 1)
        print("RTSP流初始化成功")
    except Exception as e:
        print(f"RTSP流初始化失败: {e}")

def generate_frames():
    """生成视频帧"""
    while True:
        try:
            if video_capture is None:
                init_video_stream()
                time.sleep(1)
                continue
                
            success, frame = video_capture.read()
            if not success:
                print("读取视频帧失败,尝试重新连接...")
                video_capture.release()
                init_video_stream()
                time.sleep(1)
                continue
                
            # 调整帧大小以提高性能
            frame = cv2.resize(frame, (640, 480))
            
            # 编码为JPEG格式
            ret, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 80])
            if not ret:
                continue
                
            frame_bytes = buffer.tobytes()
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
                   
        except Exception as e:
            print(f"生成视频帧错误: {e}")
            time.sleep(1)

@app.route('/video_feed')
def video_feed():
    """视频流路由"""
    print("------------------------------视频流已加载---------------------------------------")
    return Response(generate_frames(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')


@app.route('/api/set-mode', methods=['POST'])
def set_mode():
    data = request.get_json()
    mode = data.get('mode')
    print(f"视频模式设置为: {mode}")
    return jsonify({'status': 'ok', 'mode': mode})

html页面伪代码:

复制代码
<div class="video-container">
<img src = "" alt = "实时监控" id = "video-stream" style="display: none;"></div>


<div class="display-controls">
    <div class="display-option">
        <input type="radio" id="show-image" name="display-option" checked>
        <label for="show-image">显示图像</label>
    </div>
    <div class="display-option">
        <input type="radio" id="hide-image" name="display-option">
        <label for="hide-image">隐藏图像</label>
    </div>
</div>

javasrcipt伪代码:

复制代码
const video = document.getElementById('video-stream');
let videoStarted = false;

function startVideo(){
    if(!videoStarted){
        video.src = "/video_feed";
        video.style.display = "block";  //显示元素
        videoStarted = true;
    }
    fetch('/api/set-mode',{
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({mode: 'show'})
    });
}


function stopVideo() {
    video.style.display = 'none';
    
    // 发送到后端
    fetch('/api/set-mode', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({mode: 'hide'})
    });
}


// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
    // 初始化图表
    initTrendChart();
    if(document.getElementById('show-image').checked){
        startVideo();
    }
});
相关推荐
星空椰23 分钟前
从零到实战:一套完整的 Python 爬虫技术体系(requests + BeautifulSoup + 正则 + JSON)
爬虫·python·json·beautifulsoup
七颗糖很甜8 小时前
电离层对地基雷达测量精度的影响分析与校正方法
python
AC赳赳老秦8 小时前
知识产权辅助:用 OpenClaw 批量生成专利交底书 / 软著申请材料,自动校验格式与内容合规性
java·人工智能·python·算法·elasticsearch·deepseek·openclaw
小熊Coding9 小时前
Python2D射击冒险闯关游戏2.0版本
python·pygame
小码哥_常9 小时前
告别MySQL!大厂集体转投PostgreSQL,到底藏着什么玄机?
后端
FYKJ_20109 小时前
springboot校园兼职平台--附源码02041
java·javascript·spring boot·python·eclipse·django·php
刀法如飞10 小时前
Go数组去重的20种实现方式,AI时代解决问题的不同思路
后端·算法·go
yanghuashuiyue10 小时前
Deep Agents 框架-CLI
python·langchain·langgraph·deepagents
AI人工智能+电脑小能手10 小时前
【大白话说Java面试题】【Java基础篇】第30题:JDK动态代理和CGLIB动态代理有什么区别
java·开发语言·后端·面试·代理模式
swipe11 小时前
别再把 AI 聊天做成纯文本:从 agui 这个前后端项目,拆解“可感知工具调用”的流式 AI UI
后端·langchain·llm