Цикличная запись видео с камеры. Трансляция видеопотока с использованием 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.