Цикличная запись видео с камеры. Трансляция видеопотока с использованием Flask + OpenCV

Подскажите как можно реализовать запись видео в фоновом режиме при старте программы?

Хочу чтоб видео сохранялись в директорию /hove/videos/ в формате mp4 и кодеком avc1 по 100Мб.

сейчас мой код выглядит так:

import cv2
import textwrap
from pyzbar import pyzbar
from luma.core.interface.serial import i2c
from luma.oled.device import ssd1306
from luma.core.render import canvas
from PIL import ImageFont
import os
from concurrent.futures import ThreadPoolExecutor
import threading
import time
 
app = Flask(__name__)
 
# Initialize OLED display
serial = i2c(port=0, address=0x3C)
device = ssd1306(serial)
 
# Set font
font = ImageFont.truetype("arial.ttf", 11)
 
# Create a lock for synchronizing access to the display
display_lock = threading.Lock()
 
# Create a thread pool executor
executor = ThreadPoolExecutor()
 
def display_text(barcode_data):
    # Split the barcode data into multiple lines
    lines = textwrap.wrap(barcode_data, width=20)
 
    # Calculate the starting position for the first line
    x = 0
    y = 0
 
    # Display each line on the OLED display
    with canvas(device) as draw:
        for line in lines:
            draw.text((x, y), line, font=font, fill="white")
            # Adjust the vertical position for the next line
            y += 11
    time.sleep(3)
    device.clear()
 
def generate_frames():
    camera = cv2.VideoCapture("/dev/video0")
    if not camera.isOpened():
        print("Cannot open camera")
        exit()
 
    # Adjust video resolution
    camera.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
    camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
 
    # Adjust frame rate
    camera.set(cv2.CAP_PROP_FPS, 15)
 
    # Load Haar Cascade for face detection
    cascade_path = '/usr/local/share/haar-cascade-files/haarcascade_frontalface_default.xml'
    face_cascade = cv2.CascadeClassifier(cascade_path)
 
    while True:
        success, frame = camera.read()
        if not success:
            break
        else:
            # Barcode recognition
            barcodes = pyzbar.decode(frame)
 
            for barcode in barcodes:
                # Obtain barcode coordinates
                x, y, w, h = barcode.rect
 
                # Draw bounding box rectangle on the frame
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
 
            # Display barcode information
            for barcode in barcodes:
                # Get barcode data
                barcode_data = barcode.data.decode("utf-8")
 
                # Display the barcode information using a thread pool executor
                executor.submit(display_text, barcode_data)
 
            try:
                # Convert frame to grayscale
                gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
 
                # Detect faces using Haar Cascade
                faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
 
                # Draw bounding box around faces
                for (x, y, w, h) in faces:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
 
                ret, buffer = cv2.imencode('.jpg', frame)
                frame = buffer.tobytes()
                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
 
            except cv2.error:
                # Handle OpenCV error here
                print("OpenCV error")
                exit()
 
def video_record():
    camera = cv2.VideoCapture("/dev/video0")
    fourcc = cv2.VideoWriter_fourcc(*'avc1')
    file_size_limit = 100 * 1024 * 1024  # 100MB file size limit
    video_filename = None
    video_writer = None
 
    while True:
        success, frame = camera.read()
        if not success:
            break
 
        if video_writer is None or video_filename is None or os.path.getsize(video_filename) >= file_size_limit:
            # Close the previous video writer
            if video_writer is not None:
                video_writer.release()
 
            # Generate new filename with date and time
            current_datetime = time.strftime("%Y-%m-%d_%H-%M-%S")
            video_filename = f"/home/videos/video_{current_datetime}.mp4"
 
            # Create new video writer
            video_writer = cv2.VideoWriter(video_filename, fourcc, 7, (320, 240))
 
        video_writer.write(frame)
 
        # Release the camera
    camera.release()
 
    # Release the video writer
    if video_writer is not None:
        video_writer.release()
 
@app.route('/')
def index():
    return render_template('index.html')
 
@app.route('/video_feed', methods=['OPTIONS', 'GET'])
def video_feed():
    return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
 
if __name__ == '__main__':
    executor.submit(video_record)
    app.run(host='0.0.0.0', port=8083, debug=True)

но озникает ошибка:

Unable to stop the stream: Device or resource busy
VIDEOIO(cvCreateFileCapture_Images (filename)): raised C++ exception:

basic_string::substr: __pos (which is 140) > this->size() (which is 0)

Подскажите пожалуйста как добиться записи видео в фоновом режиме?

  • Версия Python 3.6
  • Версия OpenCV 3.3
  • ОС Ubuntu 20.04.6 Для Orange PI PC.

Ответы (0 шт):