Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions examples/download_playback_video.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Downloads a video from camera from start to end time."""
import os
from configparser import RawConfigParser
from datetime import datetime as dt, timedelta
from reolinkapi import Camera
import requests
import pandas as pd

def read_config(props_path: str) -> dict:
"""Reads in a properties file into variables.

NB! this config file is kept out of commits with .gitignore. The structure of this file is such:
# secrets.cfg
[camera]
ip={ip_address}
username={username}
password={password}
"""
config = RawConfigParser()
assert os.path.exists(props_path), f"Path does not exist: {props_path}"
config.read(props_path)
return config


# Read in your ip, username, & password
# (NB! you'll likely have to create this file. See tests/test_camera.py for details on structure)
config = read_config('camera.cfg')

ip = config.get('camera', 'ip')
un = config.get('camera', 'username')
pw = config.get('camera', 'password')

# Connect to camera
cam = Camera(ip, un, pw)

start = dt.now() - timedelta(minutes=10)
end = dt.now() - timedelta(minutes=9)
channel = 0

files = cam.get_playback_files(start=start, end=end, channel= channel)
print(files)
dl_dir = os.path.join(os.path.expanduser('~'), 'Downloads')
for fname in files:
print(fname)
# Download the mp4
cam.get_file(fname, output_path=os.path.join(dl_dir, fname))
4 changes: 3 additions & 1 deletion reolinkapi/handlers/api_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from reolinkapi.mixins.system import SystemAPIMixin
from reolinkapi.mixins.user import UserAPIMixin
from reolinkapi.mixins.zoom import ZoomAPIMixin
from reolinkapi.mixins.nvrdownload import NvrDownloadAPIMixin


class APIHandler(AlarmAPIMixin,
Expand All @@ -28,7 +29,8 @@ class APIHandler(AlarmAPIMixin,
SystemAPIMixin,
UserAPIMixin,
ZoomAPIMixin,
StreamAPIMixin):
StreamAPIMixin,
NvrDownloadAPIMixin):
"""
The APIHandler class is the backend part of the API, the actual API calls
are implemented in Mixins.
Expand Down
54 changes: 54 additions & 0 deletions reolinkapi/mixins/nvrdownload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from datetime import datetime as dt

class NvrDownloadAPIMixin:
"""API calls for NvrDownload."""
def get_playback_files(self, start: dt, end: dt = dt.now(), channel: int = 0,
streamtype: str = 'sub'):
"""
Get the filenames of the videos for the time range provided.

Args:
start: the starting time range to examine
end: the end time of the time range to examine
channel: which channel to download from
streamtype: 'main' or 'sub' - the stream to examine
:return: response json
"""
search_params = {
'NvrDownload': {
'channel': channel,
'iLogicChannel': 0,
'streamType': streamtype,
'StartTime': {
'year': start.year,
'mon': start.month,
'day': start.day,
'hour': start.hour,
'min': start.minute,
'sec': start.second
},
'EndTime': {
'year': end.year,
'mon': end.month,
'day': end.day,
'hour': end.hour,
'min': end.minute,
'sec': end.second
}
}
}
body = [{"cmd": "NvrDownload", "action": 1, "param": search_params}]
try:
resp = self._execute_command('NvrDownload', body)[0]
except Exception as e:
print(f"Error: {e}")
return []
if 'value' not in resp:
return []
values = resp['value']
if 'fileList' not in values:
return []
files = values['fileList']
if len(files) > 0:
return [file['fileName'] for file in files]
return []