python
import cv2
import numpy as np
import time
from datetime import datetime
import gi
import socket
import sys
gi.require_version('Gst', '1.0')
try:
gi.require_version('GstRtspServer', '1.0')
from gi.repository import Gst, GLib, GstRtspServer
except ImportError as e:
print(f"错误:无法导入 GstRtspServer,请确保已安装 gir1.2-gst-rtsp-server-1.0 包\n详细信息: {e}")
sys.exit(1)
import threading
class RTSPServer:
def __init__(self, port=8554, stream_name="test"):
try:
Gst.init(None)
except Exception as e:
print(f"GStreamer初始化失败: {e}")
raise
self.port = port
self.stream_name = stream_name
self.pipeline = None
self.running = False
self.host_ip = self.get_host_ip()
self.appsrc = None # 添加appsrc属性初始化
def get_host_ip(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
s.close()
return ip
except Exception:
return '127.0.0.1'
def start_server(self):
try:
# 创建和设置 pipeline
pipeline_str = (
'appsrc name=source is-live=true format=GST_FORMAT_TIME ! '
'videoconvert ! video/x-raw,format=I420 ! ' # 添加格式转换
'x264enc tune=zerolatency bitrate=500 ! '
'h264parse ! rtph264pay name=pay0 pt=96 ! '
'udpsink host=127.0.0.1 port=5000 sync=false'
)
self.pipeline = Gst.parse_launch(pipeline_str)
self.appsrc = self.pipeline.get_by_name('source')
# 设置 appsrc 属性
self.appsrc.set_property('caps',
Gst.Caps.from_string(
'video/x-raw,format=BGR,width=300,height=100,framerate=30/1'
)
)
# 启动 pipeline
self.pipeline.set_state(Gst.State.PLAYING)
print(f"RTSP流地址: rtsp://{self.host_ip}:{self.port}/{self.stream_name}")
# 创建RTSP服务器管道
launch_str = (
f'( udpsrc port=5000 ! application/x-rtp,media=video,clock-rate=90000,encoding-name=H264,payload=96 ! '
f'rtph264depay ! h264parse ! rtph264pay name=pay0 pt=96 )'
)
# 初始化RTSP服务器
self.server = GstRtspServer.RTSPServer()
self.server.set_service(str(self.port))
# 创建RTSP媒体工厂
factory = GstRtspServer.RTSPMediaFactory()
factory.set_launch(launch_str)
factory.set_shared(True)
# 将媒体工厂添加到服务器
mount_points = self.server.get_mount_points()
mount_points.add_factory(f"/{self.stream_name}", factory)
# 启动服务器
self.server.attach(None)
self.running = True
except Exception as e:
print(f"启动RTSP服务器失败: {e}")
self.stop_server()
raise
def push_frame(self, frame):
if not self.running or not self.appsrc:
return
try:
# 确保时间戳正确
buffer = Gst.Buffer.new_wrapped(frame.tobytes())
buffer.pts = Gst.CLOCK_TIME_NONE
buffer.duration = Gst.CLOCK_TIME_NONE
ret = self.appsrc.emit('push-buffer', buffer)
if ret != Gst.FlowReturn.OK:
print(f"推送帧失败: {ret}")
except Exception as e:
print(f"推送帧时发生错误: {e}")
def stop_server(self):
self.running = False
if self.pipeline:
self.pipeline.set_state(Gst.State.NULL)
def show_time():
try:
rtsp_server = RTSPServer()
rtsp_server.start_server()
img = np.zeros((100, 300, 3), dtype=np.uint8)
while True:
try:
img_copy = img.copy()
current_time = datetime.now().strftime('%H:%M:%S')
cv2.putText(img_copy, current_time, (20, 60),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2)
cv2.imshow('Real-time Clock', img_copy)
rtsp_server.push_frame(img_copy)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
except Exception as e:
print(f"处理帧时发生错误: {e}")
break
except Exception as e:
print(f"程序运行出错: {e}")
finally:
if 'rtsp_server' in locals():
rtsp_server.stop_server()
cv2.destroyAllWindows()
if __name__ == '__main__':
show_time()
功能都正常,就是延时有点严重。