Почему видео, записанное через OpenCV, получается с поврежденными данными?

<b>Как можно реализовать возможность включения и выключения записи видео через callback в коде на OpenCV? </b> <br/> <pre><code class="python">def callback():
    if not config.IS_REC:
        print("[INFO] Запись начата")
        config.IS_REC = True

        cap = cv2.VideoCapture(0)
        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))

        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        config.OUTPUT = cv2.VideoWriter(f'videos/g.mp4', fourcc, 30, (width, height), isColor=True)
    else:
        print(f"[INFO] Запись закончена. Файл сохранился в папку videos")
        config.IS_REC = False

        config.OUTPUT.release()
        config.OUTPUT = None</code></pre> <br/> <br/> При этом, несмотря на то что в коде, кажется, нет ошибок и всё работает, файл в итоге оказывается поврежденным. Я пробовал изменять расширение файла и fourcc, но это не помогло. Можете подсказать, в чем может заключаться проблема? Я просмотрел множество статей и видео, но так и не смог разобраться. Буду признателен за помощь.
  • 19 декабря 2024 г. 15:33
Ответы на вопрос 1
Проблема с повреждением видеофайлов, записанных с использованием OpenCV, может быть связана с несколькими факторами. 

### Возможные проблемы и их решения:

1. **Неправильное завершение записи**: В OpenCV важно корректно завершить запись, вызвав метод `release()` для объекта `VideoWriter`, иначе файл может быть поврежден. Убедитесь, что этот метод вызывается при выключении записи.

2. **Закрытие видеопотока**: Часто существует некорректное управление объектом `VideoCapture`. Если вы начинаете запись через `VideoCapture` в функции `callback()`, не забудьте закрыть его, когда запись завершена. Можно использовать `cap.release()` для этого.

3. **Формат и кодек**: Убедитесь, что выбранный вами кодек поддерживает режим записи, который вы используете (изменение `fourcc` может помочь). Например, попробуйте использовать `cv2.VideoWriter_fourcc(*'XVID')` или `cv2.VideoWriter_fourcc(*'MJPG')`.

### Реализация кнопки включения/выключения записи

В приведенном вами коде при каждом вызове функции `callback()` объект `cap` создается заново, и это может вызвать проблемы с синхронизацией. Лучше всего инициализировать `cap` один раз глобально и использовать его для записи. 

Пример исправленного кода:

```python
import cv2

class Config:
    IS_REC = False
    OUTPUT = None

config = Config()

cap = cv2.VideoCapture(0)
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')

def callback():
    if not config.IS_REC:
        print("[INFO] Запись начата")
        config.IS_REC = True
        config.OUTPUT = cv2.VideoWriter(f'videos/g.mp4', fourcc, 30, (width, height), isColor=True)
    else:
        print(f"[INFO] Запись закончена. Файл сохранился в папку videos")
        config.IS_REC = False
        config.OUTPUT.release()
        config.OUTPUT = None

while True:
    ret, frame = cap.read()
    if not ret:
        break

    if config.IS_REC:
        config.OUTPUT.write(frame)

    cv2.imshow('frame', frame)

    # Здесь добавьте вашу логику для обработки нажатия клавиш для вызова callback()
    key = cv2.waitKey(1) & 0xFF
    if key == ord('r'):  # например, 'r' для начала/остановки записи
        callback()
    elif key == ord('q'):  # 'q' для выхода
        break

# Освобождение ресурсов
cap.release()
if config.OUTPUT is not None:
    config.OUTPUT.release()
cv2.destroyAllWindows()
```

### Обратите внимание:
- **Одна переменная `cap`**: Теперь объект `VideoCapture` создается один раз вне функции `callback()`.
- **Глобальные настройки**: Изменение состояния записи теперь больше не требует повторной инициализации видеопотока.
- **Обработка нажатий клавиш**: Добавлен простой механизм для управления записью через нажатия клавиш. Вы можете настроить это по своему усмотрению.

Эти изменения помогут вам избежать повреждения выходного видеофайла и упростят управление записью.
Похожие вопросы