【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();
    }
});
相关推荐
霸道流氓气质1 小时前
SpringBoot中使用字典驱动的动态路由示例
java·spring boot·后端
jiang_changsheng1 小时前
Conda 的默认环境创建优先级。
linux·windows·python
FriendshipT2 小时前
Ultralytics:解读C2fCIB模块
人工智能·pytorch·python·深度学习·目标检测
用户69371750013842 小时前
Kimi K3 综合能力处于全球第一梯队
android·前端·后端
c_lb72882 小时前
2026年AI量化学习流程,从表达开发走到分层验证
人工智能·python
s180579163622 小时前
低成本GEO优化技巧
人工智能·python
anno2 小时前
Agent 新手 Skill 优先级指南:从第一套必装工作流,到专业能力补全
前端·后端
anno2 小时前
别再把文档“一刀切”:用 LangChain.js 做好 RAG 的第一公里
前端·后端
用户713874229002 小时前
claude_rules 深度解析:Claude Code 的模块化路径作用域规则
后端
卡卡罗特AI2 小时前
曾经狂推的 Superpowers,今天我终于把它卸载了! 臃肿,Token吞金兽!
后端·chatgpt·ai编程