Skip to content

Commit 806bbc3

Browse files
authored
Merge pull request #46 from axlan/streaming-dependancy-extra
Move streaming dependencies to their own "extra"
2 parents 5ac45d8 + 98acbde commit 806bbc3

File tree

3 files changed

+69
-49
lines changed

3 files changed

+69
-49
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ Install the package via PyPi
4848
Install from GitHub
4949

5050
pip install git+https://github.com/ReolinkCameraAPI/reolinkapipy.git
51+
52+
If you want to include the video streaming functionality you need to include the streaming "extra" dependencies
53+
54+
pip install 'reolinkapi[streaming]'
5155

5256
## Contributors
5357

reolinkapi/mixins/stream.py

+56-45
Original file line numberDiff line numberDiff line change
@@ -5,48 +5,59 @@
55
from io import BytesIO
66

77
import requests
8-
from PIL.Image import Image, open as open_image
9-
10-
from reolinkapi.utils.rtsp_client import RtspClient
11-
12-
13-
class StreamAPIMixin:
14-
""" API calls for opening a video stream or capturing an image from the camera."""
15-
16-
def open_video_stream(self, callback: Any = None, proxies: Any = None) -> Any:
17-
"""
18-
'https://support.reolink.com/hc/en-us/articles/360007010473-How-to-Live-View-Reolink-Cameras-via-VLC-Media-Player'
19-
Blocking function creates a generator and returns the frames as it is spawned
20-
:param callback:
21-
:param proxies: Default is none, example: {"host": "localhost", "port": 8000}
22-
"""
23-
rtsp_client = RtspClient(
24-
ip=self.ip, username=self.username, password=self.password, proxies=proxies, callback=callback)
25-
return rtsp_client.open_stream()
26-
27-
def get_snap(self, timeout: float = 3, proxies: Any = None) -> Optional[Image]:
28-
"""
29-
Gets a "snap" of the current camera video data and returns a Pillow Image or None
30-
:param timeout: Request timeout to camera in seconds
31-
:param proxies: http/https proxies to pass to the request object.
32-
:return: Image or None
33-
"""
34-
data = {
35-
'cmd': 'Snap',
36-
'channel': 0,
37-
'rs': ''.join(random.choices(string.ascii_uppercase + string.digits, k=10)),
38-
'user': self.username,
39-
'password': self.password,
40-
}
41-
parms = parse.urlencode(data).encode("utf-8")
42-
43-
try:
44-
response = requests.get(self.url, proxies=proxies, params=parms, timeout=timeout)
45-
if response.status_code == 200:
46-
return open_image(BytesIO(response.content))
47-
print("Could not retrieve data from camera successfully. Status:", response.status_code)
48-
return None
49-
50-
except Exception as e:
51-
print("Could not get Image data\n", e)
52-
raise
8+
9+
try:
10+
from PIL.Image import Image, open as open_image
11+
12+
from reolinkapi.utils.rtsp_client import RtspClient
13+
14+
15+
class StreamAPIMixin:
16+
""" API calls for opening a video stream or capturing an image from the camera."""
17+
18+
def open_video_stream(self, callback: Any = None, proxies: Any = None) -> Any:
19+
"""
20+
'https://support.reolink.com/hc/en-us/articles/360007010473-How-to-Live-View-Reolink-Cameras-via-VLC-Media-Player'
21+
Blocking function creates a generator and returns the frames as it is spawned
22+
:param callback:
23+
:param proxies: Default is none, example: {"host": "localhost", "port": 8000}
24+
"""
25+
rtsp_client = RtspClient(
26+
ip=self.ip, username=self.username, password=self.password, proxies=proxies, callback=callback)
27+
return rtsp_client.open_stream()
28+
29+
def get_snap(self, timeout: float = 3, proxies: Any = None) -> Optional[Image]:
30+
"""
31+
Gets a "snap" of the current camera video data and returns a Pillow Image or None
32+
:param timeout: Request timeout to camera in seconds
33+
:param proxies: http/https proxies to pass to the request object.
34+
:return: Image or None
35+
"""
36+
data = {
37+
'cmd': 'Snap',
38+
'channel': 0,
39+
'rs': ''.join(random.choices(string.ascii_uppercase + string.digits, k=10)),
40+
'user': self.username,
41+
'password': self.password,
42+
}
43+
parms = parse.urlencode(data).encode("utf-8")
44+
45+
try:
46+
response = requests.get(self.url, proxies=proxies, params=parms, timeout=timeout)
47+
if response.status_code == 200:
48+
return open_image(BytesIO(response.content))
49+
print("Could not retrieve data from camera successfully. Status:", response.status_code)
50+
return None
51+
52+
except Exception as e:
53+
print("Could not get Image data\n", e)
54+
raise
55+
except ImportError:
56+
class StreamAPIMixin:
57+
""" API calls for opening a video stream or capturing an image from the camera."""
58+
59+
def open_video_stream(self, callback: Any = None, proxies: Any = None) -> Any:
60+
raise ImportError('''open_video_stream requires streaming extra dependencies\nFor instance "pip install reolinkapi[streaming]"''')
61+
62+
def get_snap(self, timeout: float = 3, proxies: Any = None) -> Optional['Image']:
63+
raise ImportError('''open_video_stream requires streaming extra dependencies\nFor instance "pip install reolinkapi[streaming]"''')

setup.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@ def find_version(*file_paths):
2626
AUTHOR = 'Benehiko'
2727
LICENSE = 'GPL-3.0'
2828
INSTALL_REQUIRES = [
29-
'numpy==1.19.4',
30-
'opencv-python==4.4.0.46',
31-
'Pillow==8.0.1',
3229
'PySocks==1.7.1',
3330
'PyYaml==5.3.1',
3431
'requests>=2.18.4',
3532
]
33+
EXTRAS_REQUIRE = {
34+
'streaming': [
35+
'numpy==1.19.4',
36+
'opencv-python==4.4.0.46',
37+
'Pillow==8.0.1',
38+
],
39+
}
3640

3741

3842
here = os.path.abspath(os.path.dirname(__file__))
@@ -53,5 +57,6 @@ def find_version(*file_paths):
5357
url=URL,
5458
license=LICENSE,
5559
install_requires=INSTALL_REQUIRES,
56-
packages=find_packages(exclude=['examples', 'tests'])
60+
packages=find_packages(exclude=['examples', 'tests']),
61+
extras_require=EXTRAS_REQUIRE
5762
)

0 commit comments

Comments
 (0)