Создание видеостены для RTSP потоков с использованием Python, OpenCV и Flet

GetCoder.ru
Изображение статьи

Узнайте, как создать простую видеостену для одновременного отображения нескольких RTSP потоков с помощью Python. Мы рассмотрим принцип работы программы, плюсы и минусы использования OpenCV для захвата видеопотоков и Flet для создания интерфейса, а также пример настройки многопоточной обработки.

Данный код представляет собой простую видеостену для отображения RTSP (Real-Time Streaming Protocol) потоков. В её основе используется библиотека OpenCV для захвата кадров с видеопотоков и библиотека Flet для создания пользовательского интерфейса. Основная задача программы — получить видео с нескольких RTSP-камер и вывести их в реальном времени на экран.

Установка

  • copy
pip install opencv-python flet numpy pillow

Основные плюсы

  • Параллельная обработка потоков: благодаря использованию потоков, программа может обрабатывать и отображать несколько RTSP потоков одновременно, что позволяет создать видеостену с несколькими камерами.
  • Легкость масштабирования: код легко масштабируется для работы с различным количеством камер, достаточно изменить список RTSP URL-ов.
  • Минимальные зависимости: код использует лишь несколько библиотек (OpenCV, Flet, NumPy), что делает её относительно легковесной и простой в установке.
  • copy
# -*- coding: utf-8 -*- import cv2 import threading import flet as ft import numpy as np import base64 from io import BytesIO import time # Подготовка кадра def image_to_base64(image): _, buffer = cv2.imencode('.jpg', image) img_bytes = BytesIO(buffer) img_base64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8') return img_base64 # Видео поток class rtsp_stream: def __init__(self, rtsp_url, video_widget): self.capture = cv2.VideoCapture(rtsp_url, cv2.CAP_FFMPEG) self.frame = None self.video_widget = video_widget self.running = True self.lock = threading.Lock() def start_stream(self): while self.running: try: ret, frame = self.capture.read() if ret: with self.lock: self.frame = frame except Exception as e: pass time.sleep(0.01) def display_frame(self): while self.running: try: with self.lock: if self.frame is not None: base64_img = image_to_base64(self.frame) self.video_widget.src_base64 = base64_img self.video_widget.update() except Exception as e: pass time.sleep(0.01) def stop(self): self.running = False self.capture.release() # Старт def main(page: ft.Page): page.window.width = 900 page.window.height = 560 page.title = "" # Вводим URL RTSP потоков rtsp_urls = [ "http://158.58.130.148:80/mjpg/video.mjpg", "http://158.58.130.148:80/mjpg/video.mjpg", "http://158.58.130.148:80/mjpg/video.mjpg", "http://158.58.130.148:80/mjpg/video.mjpg" ] # Подготовка внешнего вида video_widgets = [] rv = ft.ResponsiveRow([]) for url in rtsp_urls: video_elem = ft.Image(src="") video_widgets.append(video_elem) var_elem = ft.Container( video_elem, padding=5, col={"sm": 6, "md": 6, "xl": 6}, border = ft.border.all(1, ft.colors.PRIMARY) ) rv.controls.append(var_elem) lv = ft.ListView(expand = 1, spacing = 10, padding = 10) lv.controls.append(rv) page.add(lv) # Создаем объект RTSP потока и запускаем поток захвата кадров for i, widget in enumerate(video_widgets): # Запуск потоков захвата и отображения stream = rtsp_stream(rtsp_urls[i], widget) threading.Thread(target=stream.start_stream, daemon=True).start() threading.Thread(target=stream.display_frame, daemon=True).start() # Остановка потока при закрытии страницы page.on_disconnect = lambda: stream.stop() # Запуск приложения ft.app(target=main)
Исходный код

Заключение

Программа демонстрирует базовую концепцию видеостены, которая обрабатывает несколько RTSP потоков с использованием параллельных потоков для захвата и отображения видео. Несмотря на свою простоту, она является гибким решением для реализации видеонаблюдения или других задач, требующих многопоточного видео.

  • 16.10.2024
  • 71
  • 0

Создание видеостены для RTSP потоков с использованием Python, OpenCV и Flet

Данный код представляет собой простую видеостену для отображения RTSP (Real-Time Streaming Protocol) потоков. В её основе используется библиотека OpenCV для захвата кадров с видеопотоков и библиотека Flet для создания пользовательского интерфейса. Основная задача программы — получить видео с нескольких RTSP-камер и вывести их в реальном времени на экран.

Установка

  • copy
pip install opencv-python flet numpy pillow

Основные плюсы

  • Параллельная обработка потоков: благодаря использованию потоков, программа может обрабатывать и отображать несколько RTSP потоков одновременно, что позволяет создать видеостену с несколькими камерами.
  • Легкость масштабирования: код легко масштабируется для работы с различным количеством камер, достаточно изменить список RTSP URL-ов.
  • Минимальные зависимости: код использует лишь несколько библиотек (OpenCV, Flet, NumPy), что делает её относительно легковесной и простой в установке.
  • copy
# -*- coding: utf-8 -*- import cv2 import threading import flet as ft import numpy as np import base64 from io import BytesIO import time # Подготовка кадра def image_to_base64(image): _, buffer = cv2.imencode('.jpg', image) img_bytes = BytesIO(buffer) img_base64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8') return img_base64 # Видео поток class rtsp_stream: def __init__(self, rtsp_url, video_widget): self.capture = cv2.VideoCapture(rtsp_url, cv2.CAP_FFMPEG) self.frame = None self.video_widget = video_widget self.running = True self.lock = threading.Lock() def start_stream(self): while self.running: try: ret, frame = self.capture.read() if ret: with self.lock: self.frame = frame except Exception as e: pass time.sleep(0.01) def display_frame(self): while self.running: try: with self.lock: if self.frame is not None: base64_img = image_to_base64(self.frame) self.video_widget.src_base64 = base64_img self.video_widget.update() except Exception as e: pass time.sleep(0.01) def stop(self): self.running = False self.capture.release() # Старт def main(page: ft.Page): page.window.width = 900 page.window.height = 560 page.title = "" # Вводим URL RTSP потоков rtsp_urls = [ "http://158.58.130.148:80/mjpg/video.mjpg", "http://158.58.130.148:80/mjpg/video.mjpg", "http://158.58.130.148:80/mjpg/video.mjpg", "http://158.58.130.148:80/mjpg/video.mjpg" ] # Подготовка внешнего вида video_widgets = [] rv = ft.ResponsiveRow([]) for url in rtsp_urls: video_elem = ft.Image(src="") video_widgets.append(video_elem) var_elem = ft.Container( video_elem, padding=5, col={"sm": 6, "md": 6, "xl": 6}, border = ft.border.all(1, ft.colors.PRIMARY) ) rv.controls.append(var_elem) lv = ft.ListView(expand = 1, spacing = 10, padding = 10) lv.controls.append(rv) page.add(lv) # Создаем объект RTSP потока и запускаем поток захвата кадров for i, widget in enumerate(video_widgets): # Запуск потоков захвата и отображения stream = rtsp_stream(rtsp_urls[i], widget) threading.Thread(target=stream.start_stream, daemon=True).start() threading.Thread(target=stream.display_frame, daemon=True).start() # Остановка потока при закрытии страницы page.on_disconnect = lambda: stream.stop() # Запуск приложения ft.app(target=main)
Исходный код

Заключение

Программа демонстрирует базовую концепцию видеостены, которая обрабатывает несколько RTSP потоков с использованием параллельных потоков для захвата и отображения видео. Несмотря на свою простоту, она является гибким решением для реализации видеонаблюдения или других задач, требующих многопоточного видео.