Refactor Rtsp client
This commit is contained in:
@@ -1,85 +1,47 @@
|
|||||||
import socket
|
import os
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy
|
|
||||||
import socks
|
|
||||||
|
|
||||||
|
|
||||||
class RtspClient:
|
class RtspClient:
|
||||||
|
|
||||||
def __init__(self, ip, username, password, port=554, profile="main", **kwargs):
|
def __init__(self, ip, username, password, port=554, profile="main", use_udp=True, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param ip:
|
:param ip: Camera IP
|
||||||
:param username:
|
:param username: Camera Username
|
||||||
:param password:
|
:param password: Camera User Password
|
||||||
:param port: rtsp port
|
:param port: RTSP port
|
||||||
:param profile: "main" or "sub"
|
:param profile: "main" or "sub"
|
||||||
|
:param use_upd: True to use UDP, False to use TCP
|
||||||
:param proxies: {"host": "localhost", "port": 8000}
|
:param proxies: {"host": "localhost", "port": 8000}
|
||||||
"""
|
"""
|
||||||
|
capture_options = 'rtsp_transport;'
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
self.port = port
|
self.port = port
|
||||||
self.sockt = None
|
|
||||||
self.url = "rtsp://" + self.username + ":" + self.password + "@" + self.ip + ":" + str(
|
|
||||||
self.port) + "//h264Preview_01_" + profile
|
|
||||||
self.proxy = kwargs.get("proxies")
|
self.proxy = kwargs.get("proxies")
|
||||||
|
self.url = "rtsp://" + self.username + ":" + self.password + "@" + \
|
||||||
|
self.ip + ":" + str(self.port) + "//h264Preview_01_" + profile
|
||||||
|
if use_udp:
|
||||||
|
capture_options = capture_options + 'udp'
|
||||||
|
else:
|
||||||
|
capture_options = capture_options + 'tcp'
|
||||||
|
|
||||||
def __enter__(self):
|
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = capture_options
|
||||||
self.sockt = self.connect()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
self.sockt.close()
|
|
||||||
|
|
||||||
def connect(self) -> socket:
|
|
||||||
try:
|
|
||||||
sockt = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
sockt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
if self.proxy is not None:
|
|
||||||
sockt.set_proxy(socks.SOCKS5, self.proxy["host"], self.proxy["port"])
|
|
||||||
sockt.connect((self.ip, self.port))
|
|
||||||
return sockt
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
def get_frame(self) -> bytearray:
|
|
||||||
try:
|
|
||||||
self.sockt.send(str.encode(self.url))
|
|
||||||
data = b''
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
r = self.sockt.recv(90456)
|
|
||||||
if len(r) == 0:
|
|
||||||
break
|
|
||||||
a = r.find(b'END!')
|
|
||||||
if a != -1:
|
|
||||||
data += r[:a]
|
|
||||||
break
|
|
||||||
data += r
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
continue
|
|
||||||
nparr = numpy.fromstring(data, numpy.uint8)
|
|
||||||
frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
|
|
||||||
return frame
|
|
||||||
except Exception as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
def preview(self):
|
def preview(self):
|
||||||
""" Blocking function. Opens OpenCV window to display stream. """
|
""" Blocking function. Opens OpenCV window to display stream. """
|
||||||
self.connect()
|
win_name = self.ip
|
||||||
win_name = 'RTSP'
|
cap = cv2.VideoCapture(self.url, cv2.CAP_FFMPEG)
|
||||||
cv2.namedWindow(win_name, cv2.WINDOW_AUTOSIZE)
|
ret, frame = cap.read()
|
||||||
cv2.moveWindow(win_name, 20, 20)
|
|
||||||
|
|
||||||
while True:
|
while ret:
|
||||||
cv2.imshow(win_name, self.get_frame())
|
cv2.imshow(win_name, frame)
|
||||||
# if self._latest is not None:
|
|
||||||
# cv2.imshow(win_name,self._latest)
|
ret, frame = cap.read()
|
||||||
if cv2.waitKey(25) & 0xFF == ord('q'):
|
if (cv2.waitKey(1) & 0xFF == ord('q')):
|
||||||
break
|
break
|
||||||
cv2.waitKey()
|
|
||||||
|
cap.release()
|
||||||
cv2.destroyAllWindows()
|
cv2.destroyAllWindows()
|
||||||
cv2.waitKey()
|
|
||||||
|
|||||||
@@ -30,16 +30,15 @@ class RecordingAPIMixin:
|
|||||||
###########
|
###########
|
||||||
# RTSP Stream
|
# RTSP Stream
|
||||||
###########
|
###########
|
||||||
def open_video_stream(self, profile: str = "main") -> Image:
|
def open_video_stream(self, profile: str = "main", proxies=None) -> None:
|
||||||
"""
|
"""
|
||||||
profile is "main" or "sub"
|
'https://support.reolink.com/hc/en-us/articles/360007010473-How-to-Live-View-Reolink-Cameras-via-VLC-Media-Player'
|
||||||
https://support.reolink.com/hc/en-us/articles/360007010473-How-to-Live-View-Reolink-Cameras-via-VLC-Media-Player
|
:param profile: profile is "main" or "sub"
|
||||||
:param profile:
|
:param proxies: Default is none, example: {"host": "localhost", "port": 8000}
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
with RtspClient(ip=self.ip, username=self.username, password=self.password,
|
rtsp_client = RtspClient(
|
||||||
proxies={"host": "127.0.0.1", "port": 8000}) as rtsp_client:
|
ip=self.ip, username=self.username, password=self.password, proxies=proxies)
|
||||||
rtsp_client.preview()
|
rtsp_client.preview()
|
||||||
|
|
||||||
def get_snap(self, timeout: int = 3, proxies=None) -> Image or None:
|
def get_snap(self, timeout: int = 3, proxies=None) -> Image or None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user