blinkpy
blinkpy copied to clipboard
Support for downloading videos from USB storage
Is your feature request related to a problem? Please describe. As far as I understand, download_videos() only downloads videos from the cloud server. Despite check_new_videos() is telling me "True" and there are in fact new videos on the local USB storage, they are not being downloaded.
Describe the solution you'd like A feature should be implemented like download_videos_usb() to download the video files from attached USB storage.
Yeah I agree that needs to be added. As of right now, I don't think the API endpoint for local storage has been uncovered so we'd need that before anything could be added to the library
I was bored and did a little traffic snooping last night. Found 2 new endpoints while looking at videos on my sync module:
Send an empty (0 byte) POST to {blink.urls.base_url}/api/v1/accounts/{blink.account_id}/networks/{network}/sync_modules/{sync_module_id}/local_storage/manifest/request
(sync_module_id gets returned from blink.sync.attributes)
This should return a JSON "id" (the request_id)
Poll api.request_command_status
with the request_id (I check every 2 sec) until "complete": true
comes back.
Then, do a GET to {blink.urls.base_url}/api/v1/accounts/{blink.account_id}/networks/{network}/sync_modules/{sync_module_id}/local_storage/manifest/request/{request_id}
and you'll get a JSON of clip IDs off the sync module.
To download a clip:
Another blank (0 byte) POST to this endpoint: {blink.urls.base_url}/api/v1/accounts/{blink.account_id}/networks/{network}/sync_modules/{sync_module_id}/local_storage/manifest/{manifest_id}/clip/request/{clip_id}
(clip_id's are from the local manifest)
This should return another request "id"
Just like above, poll api.request_command_status
with that id until "complete": true
comes back.
Download the MP4 with GET {blink.urls.base_url}/api/v1/accounts/{blink.account_id}/networks/{network}/sync_modules/{sync_module_id}/local_storage/manifest/{manifest_id}/clip/request/{clip_id}
I have some bad python running right now, slowly uploading the 600 videos from my local sync module, up to the servers, and then downloading them back. =)
Is this supported now - it seems Jul 26 release became 0.19.2 - not 0.20.0 Is there an example on how to get the file from USB?
Wow, great job @technoweenie314. I would love to know how you captured these, I had zero luck with Pi-ITM
I added a PR for supporting this functionality. I didn't see the above message until now. Oh well, reverse engineering is fun anyhow.
This is awesome, thanks @technoweenie314 for reverse engineering and @perdue for re-reverse engineering and implementing :)
I was able to figure out, by pure guess work, that replacing "request" with "delete" in the (0 byte) POST with the {clip_id} can also be used to delete the clip from local storage.
Here is some very crude code to download and delete videos one-by-one from the sync module, this will save me having to painfully go through the Blink app everyday to clear out the videos:
print("Going through syncs...")
for name, sync in blink.sync.items():
print(name)
#print(sync.attributes)
#print(sync._local_storage)
totalItems = len(sync._local_storage["manifest"])
itemNumber = 1
for manifestItem in sync._local_storage["manifest"]:
manifestItem.prepare_download(blink)
urlForVideo = blink.urls.base_url+manifestItem.url()
cameraName = manifestItem._camera_name
fileName = cameraName + manifestItem._created_at.strftime("%Y%m%d-%H%M%S") + ".mp4"
fileName = fileName.replace("/", "-")
print(str(itemNumber)+"/"+str(totalItems)+": "+fileName)
media = blink.cameras[cameraName].get_video_clip(urlForVideo)
if media.status_code == 200:
with open(path+fileName, "wb") as clip_file:
copyfileobj(media.raw, clip_file)
urlForDelete = urlForVideo
urlForDelete = urlForDelete.replace("request", "delete")
blink.auth.session.send(blink.auth.prepare_request(urlForDelete, blink.auth.header, None, "post"))
else:
print(media)
itemNumber = itemNumber+1
time.sleep(10)
Can someone please explain how to use with asyncio?