#!/usr/bin/env python3 """ RTSP Server для стриминга с CSI камеры на Jetson Orin. Использует GStreamer RTSP Server. """ import os import gi gi.require_version('Gst', '1.0') gi.require_version('GstRtspServer', '1.0') from gi.repository import Gst, GstRtspServer, GLib # Инициализация GStreamer Gst.init(None) # Параметры из environment WIDTH = os.environ.get('CAMERA_WIDTH', '1920') HEIGHT = os.environ.get('CAMERA_HEIGHT', '1080') FPS = os.environ.get('CAMERA_FPS', '30') RTSP_PORT = os.environ.get('RTSP_PORT', '8554') def create_pipeline(): """ Создаёт GStreamer pipeline для CSI камеры. Пробуем разные источники в порядке приоритета. """ # Вариант 1: nvarguscamerasrc (CSI камера на Jetson) с NVIDIA hardware encoder # Используем nvv4l2h264enc для аппаратного кодирования без EGL csi_pipeline = ( f'nvarguscamerasrc ! ' f'video/x-raw(memory:NVMM),width={WIDTH},height={HEIGHT},framerate={FPS}/1,format=NV12 ! ' f'nvv4l2h264enc bitrate=4000000 preset-level=1 insert-sps-pps=true ! ' f'h264parse ! ' f'rtph264pay name=pay0 pt=96' ) # Вариант 2: v4l2src (USB камера) с NVIDIA hardware encoder v4l2_pipeline = ( f'v4l2src device=/dev/video0 ! ' f'video/x-raw,width={WIDTH},height={HEIGHT},framerate={FPS}/1 ! ' f'nvvidconv ! video/x-raw(memory:NVMM),format=NV12 ! ' f'nvv4l2h264enc bitrate=4000000 preset-level=1 insert-sps-pps=true ! ' f'h264parse ! ' f'rtph264pay name=pay0 pt=96' ) # Вариант 3: тестовый источник с software encoder (fallback) test_pipeline = ( f'videotestsrc is-live=true ! ' f'video/x-raw,width={WIDTH},height={HEIGHT},framerate={FPS}/1 ! ' f'videoconvert ! ' f'x264enc tune=zerolatency bitrate=4000 speed-preset=ultrafast ! ' f'rtph264pay name=pay0 pt=96' ) # Пробуем CSI камеру сначала try: test = Gst.parse_launch(csi_pipeline.replace('rtph264pay name=pay0 pt=96', 'fakesink')) test.set_state(Gst.State.PLAYING) # Даём время на инициализацию import time time.sleep(2) state = test.get_state(Gst.CLOCK_TIME_NONE) test.set_state(Gst.State.NULL) if state[1] == Gst.State.PLAYING: print("Using CSI camera (nvarguscamerasrc)") return csi_pipeline except Exception as e: print(f"CSI camera not available: {e}") # Пробуем USB камеру if os.path.exists('/dev/video0'): print("Using USB camera (v4l2src)") return v4l2_pipeline # Fallback на тестовый источник print("No camera found, using test source") return test_pipeline class RTSPServer: def __init__(self): self.server = GstRtspServer.RTSPServer() self.server.set_service(RTSP_PORT) # Создаём factory для стрима factory = GstRtspServer.RTSPMediaFactory() pipeline = create_pipeline() print(f"Pipeline: {pipeline}") factory.set_launch(f'( {pipeline} )') factory.set_shared(True) # Добавляем mount point mount_points = self.server.get_mount_points() mount_points.add_factory('/stream', factory) # Запускаем сервер self.server.attach(None) print(f"\n{'='*50}") print(f"RTSP Server started!") print(f"Stream URL: rtsp://:{RTSP_PORT}/stream") print(f"{'='*50}\n") def main(): import signal import sys server = RTSPServer() loop = GLib.MainLoop() def signal_handler(sig, frame): print("Shutting down...") loop.quit() sys.exit(0) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) print("RTSP server running. Waiting for connections...") sys.stdout.flush() try: loop.run() except Exception as e: print(f"Error in main loop: {e}") sys.exit(1) if __name__ == '__main__': main()