Files
pickle_vision/orin/scripts/rtsp_server.py
Ruslan Bakiev 549fd1da9d Initial commit
2026-03-06 09:43:52 +07:00

135 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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://<device-ip>:{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()