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

Flask结合OpenCV录制10秒摄像头分段视频时长异常如何解决

问题根因
  • 多录制线程共存:每次触发10秒分段时,没有停止上一轮的录制线程,所有存活的录制线程都会持续向自己绑定的视频文件写入帧,导致越早创建的视频积累的帧越多、时长越长,完全符合描述的时长占比异常现象。
  • 视频文件未正常收尾:每段录制结束后没有调用out.release()写入视频索引信息,系统无法正确计算视频时长。
  • 帧率不匹配:录制逻辑中sleep(0.05)对应每秒20帧,但视频写入器配置的是25帧率,实际生成的视频时长会和预期存在偏差。
修复后可运行代码
import cv2
import time
import datetime
import os
import threading
from threading import Thread
from flask import Flask, render_template, request

app = Flask(__name__)
camera = cv2.VideoCapture(0)
# 定义视频分辨率
size = (int(camera.get(cv2.CAP_PROP_FRAME_WIDTH)), int(camera.get(cv2.CAP_PROP_FRAME_HEIGHT)))
rec = False
img = None

def gen_frames():
    global img
    while True:
        success, frame = camera.read()
        if success:
            img = frame
        time.sleep(0.01)

# 录制函数增加独立停止事件
def record(out, stop_event):
    global rec, img
    while rec and not stop_event.is_set():
        if img is not None:
            out.write(img)
        # 匹配25帧率的写入间隔
        time.sleep(0.04)

@app.route('/requests',methods=['POST','GET'])
def tasks():
    global rec
    if request.form.get('rec') == 'Start/Stop Recording':
        rec = not rec
        class TimerClass(threading.Thread):
            def __init__(self):
                threading.Thread.__init__(self)
                self.event = threading.Event()

            def run(self):
                while rec and not self.event.is_set():
                    now=datetime.datetime.now()
                    fourcc = cv2.VideoWriter_fourcc(*'XVID')
                    p = os.path.sep.join(['clips', "vid_{}.avi".format(str(now).replace(":",''))])
                    out = cv2.VideoWriter(p, fourcc, 25.0, size)
                    # 每轮录制的独立停止标志
                    rec_stop = threading.Event()
                    thread = Thread(target = record, args=(out, rec_stop,))
                    thread.start()
                    # 等待10秒分段
                    self.event.wait(10)
                    # 停止当前轮录制线程
                    rec_stop.set()
                    thread.join()
                    # 释放当前视频文件
                    out.release()

            def stop(self):
                self.event.set()

        tmr = TimerClass()
        if rec:
            print("start recording")
            tmr.start()
        else:
            print("stop recording")
            tmr.stop()
            # 停止后等待线程收尾
            tmr.join()

    elif request.method=='GET':
        return render_template('index.html')
    return render_template('index.html')

if __name__ == '__main__':
    # 提前创建存储文件夹
    if not os.path.exists('clips'):
        os.mkdir('clips')
    # 启动帧读取线程
    Thread(target=gen_frames, daemon=True).start()
    app.run(host='0.0.0.0', threaded=True)
关键修改说明
  • 为每轮录制线程增加独立停止事件,10秒时长到后先终止上一轮录制线程,再启动下一轮,避免多线程同时写入
  • 每段录制结束后立即释放视频写入对象,保证视频元数据完整,时长计算正确
  • 调整写入间隔匹配25帧率配置,视频时长精度误差小于0.1秒
  • 补充了存储文件夹自动创建、帧读取线程启动等缺失逻辑,可直接运行
  • 移除了不必要的全局变量,避免变量覆盖导致的异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 02:36:02