Python OpenCV — запись видео фиксированного размера из потока RSTP

#python #opencv #rtp

#python #opencv #rtp

Вопрос:

Доброе утро / день / вечер,

Я изучаю, как использовать OpenCV в Python, но я сталкиваюсь с некоторыми проблемами, и я считаю, что мне не хватает какой-то части головоломки.

Настройка

IP-камера (Bosh FLEXIDOME IP micro 5000) и мой ноутбук, подключенный к коммутатору PoE, подключены к моему основному маршрутизатору.

Чего я пытаюсь достичь

Мне нужно записывать видео фиксированной длины с камеры (используя RSTP). Например, запишите 30-секундное видео, сохраните его, начните снова. Я использую VP80, потому что он бесплатен.

Проблема

Я жестко кодирую fps в соответствии со спецификациями камеры. В нем говорится, что он может записывать со скоростью 25 кадров в секунду, поэтому я выбрал это число. Я хочу видео продолжительностью 30 секунд.

Я пробовал два подхода, но основная проблема заключается в том, что цикл захвата кадров python не может работать так быстро, как необходимо, до 25 кадров в секунду.

Подход 1

Я вычисляю количество кадров, которые мне нужно захватить, чтобы получить видео продолжительностью 30 секунд. frames_per_seconds = fps * clip_duration_in_seconds Я зацикливаюсь и захватываю кадры, пока не наберу необходимое количество кадров, и сохраняю видео.

Это дает мне 30 секунд видео (приятно!) за несколько минут (?)

 import cv2
import os
import time
from datetime import datetime
import sys

cap = cv2.VideoCapture('rtsp://192.168.178.157:554/?fmt=3')

width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = 25
size = (width, height)
clip_duration_in_seconds = 5
frames_per_video = clip_duration_in_seconds * fps

if (cap.isOpened()== False): 
    raise("Error opening video stream or file")   
  
   while(True):     
        start = datetime.now().strftime("%d-%m-%Y_%H.%M.%S")
        output_file = f"Output_{start}.mkv"
        out = cv2.VideoWriter(
                output_file, cv2.VideoWriter_fourcc(*'VP80'), fps,
                size)
        frame_count = 0
        while(cap.isOpened() and frame_count < frames_per_video):
            ret, frame = cap.read()
            if ret == True:                
                out.write(frame)  
                frame_count = frame_count   1
            else: 
                raise("Broken stream")
        out.release()
 

Подход 2

С помощью time.time() я проверяю, что прошло 30 секунд. Результатом является промежуток времени 1-3 секунды. Код такой же, как и раньше, но вместо проверки frame_count < frames_per_video я проверяю время.

Вопрос

Я думаю, я мог бы снизить частоту кадров, но это всегда будет отличаться, так как я могу динамически выбирать частоту кадров? Или как я могу изменить реализацию, чтобы перехватить все кадры?

Или я что-то упускаю? Конечная цель — иметь 30-секундные видеоролики, представляющие 30 секунд реального времени.

Спасибо!

Ответ №1:

Предположение о том, что вы видите:

  • VP8 слишком много для вашего компьютера, чтобы кодировать с такой частотой кадров и размером. используйте более простой кодек, возможно, MJPG.
  • возможно, сетевая камера не выдает видео со скоростью 30 кадров в секунду

Получите значение CAP_PROP_POS_MSEC из вашей видеозаписи до / после каждого кадра и посмотрите, имеют ли значения смысл для вас.

Возможно, вам придется работать с временными метками презентации. Это обобщение «кадров в секунду» для видео, которое может иметь кадры в произвольное время. Некоторые камеры меняют частоту кадров, когда для них установлены различные «автоматические» настройки.

OpenCV не является медиа-библиотекой. Его функции чтения и записи видео — это просто удобство. Вам нужны более мощные API.

Рассмотрите возможность использования библиотеки ffmpeg. Это сложный API, я согласен, но это необходимая сложность. Проект «PyAV» правильно переносит ffmpeg в python. Любая другая оболочка python «ffmpeg» просто запускает подпроцесс, который не дает вам никакой информации о временных метках презентации.

Комментарии:

1. Спасибо, я изучу предложения, которые вы мне дали. Что касается PyAV / ffmpeg, основной проблемой является их лицензия. Для коммерческого продукта (например, того, над чем я работаю) он очень строгий, поэтому я не могу его использовать..

2. ffmpeg может использоваться в коммерческих целях: video.stackexchange.com/questions/14802 /…

3. OpenCV использует ffmpeg, поэтому, если вы считаете, что OpenCV безопасен для коммерческого использования (что правильно), это включает в себя все библиотеки, которые он использует. возможно, вам придется упаковать соответствующие лицензии в ваше приложение, чтобы соответствовать, может быть, больше, может быть, меньше.