{"id":1390,"date":"2017-07-20T20:40:17","date_gmt":"2017-07-21T03:40:17","guid":{"rendered":"https:\/\/partofthething.com\/thoughts\/?p=1390"},"modified":"2021-05-08T15:22:04","modified_gmt":"2021-05-08T22:22:04","slug":"downloading-files-from-an-amcrest-security-camera-with-python","status":"publish","type":"post","link":"https:\/\/partofthething.com\/thoughts\/downloading-files-from-an-amcrest-security-camera-with-python\/","title":{"rendered":"Downloading files from an Amcrest security camera with Python"},"content":{"rendered":"<p>UPDATE 2021: This was fun but nowadays I have to direct people to a <a href=\"https:\/\/github.com\/tchellomello\/python-amcrest\/blob\/master\/examples\/get-files.py\">more complete python solution here.<\/a><\/p>\n<p>I got a few Amcrest Wifi security cameras for my mom&#8217;s house at her request. They&#8217;re pretty nice overall (My only complaint is that the web-interface doesn&#8217;t fully support Linux). I set one up to save a jpg snapshot to memory every minute and then flew across the country. When I wanted to access them, I couldn&#8217;t just put the SD-card in a computer or anything, and clicking all 14,000 of them seemed like a pain, so I decided to figure out how to get them with a Python script.<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/893aPy6OK6o\" allowfullscreen=\"allowfullscreen\" frameborder=\"0\"><\/iframe><\/p>\n<p><!--more--><\/p>\n<p>Most of the information you need to know to do this is in the <a href=\"https:\/\/s3.amazonaws.com\/amcrest-files\/AMCREST_CGI_SDK_API.pdf\">Amcrest CGI SDK API Documentation<\/a>. With that, I was able to figure out how to list the file names of all the jpgs on the disk and then download them one by one to my local drive.<\/p>\n<p>To get a listing of file names you have to first set up authentication, create a Media File Finder instance, and save the number that is returned<\/p>\n<pre class=\"toolbar-delay:false striped:false nums:false nums-toggle:false scroll:false lang:default decode:true\" title=\"Getting a file finder\">import os\nimport requests\nfrom requests.auth import HTTPBasicAuth\nauth = HTTPBasicAuth('admin','yourpassword')\nfactory = requests.get('http:\/\/yourip\/cgi-bin\/mediaFileFind.cgi?action=factory.create',auth=auth) \nfactory = factory.text.split('=')[1]<\/pre>\n<p>Then, you have to do a search for a bunch of files (optionally within a date range). Here I am looking for all jpgs made on July 15th:<\/p>\n<pre class=\"toolbar-delay:false striped:false nums:false nums-toggle:false scroll:false lang:default decode:true\" title=\"Searching for files\">requests.get('http:\/\/yourip\/cgi-bin\/mediaFileFind.cgi?action=findFile&amp;object={}&amp;condition.Channel=0&amp;condition.StartTime=2017-7-15%2000:01:00&amp;condition. EndTime=2017-7-15%2023:59:00&amp;condition.Types[0]=jpg'.format(factory), auth=auth)<\/pre>\n<p>The <code>%20<\/code>\u00a0 things are just the code for a space. Note that we had to pass the number from the factory above here for this to work. Ok! Now we should be able to list the files found. At first I tried doing this without dealing with cookies and I was able to list files but I could not get them to download even though I was using the same commands used by the web interface. I decided to use the Firefox Developer tools to watch the network while downloading files from there. I noticed some authentication cookies that I thought might help, so I just copied and pasted them into the code (cheating a bit, but whatever).<\/p>\n<pre class=\"lang:default decode:true\" title=\"my cookie\"> cookies = {'DHLangCookie30':'English', 'DhWebClientSessionID':'1234567890', 'DhWebCookie':'long goofy string'}\n<\/pre>\n<p>Then, to list and download a file, I used this:<\/p>\n<pre class=\"lang:default decode:true\" title=\"Getting the next file info\">files = requests.get('http:\/\/yourip\/cgi-bin\/mediaFileFind.cgi?action=findNextFile&amp;object={}&amp;count=1'.format(factory),auth=auth, cookies=cookies)\nfiles = files.text.strip()\nfor line in files.iter_lines():\n    line = line.decode()\n    if 'FilePath' in line:\n        path = line.split('=')[1]\n        cmd = 'http:\/\/yourip\/RPC_Loadfile'+path\n        print('Running: ['+cmd+']')\n        resp = requests.get(cmd, auth=auth, cookies=cookies)\n        with open('-'.join(cmd.split(os.path.sep)[-6:]), 'wb') as out:\n            out.write(resp.content)\n        print(resp.status_code)\n\nok = requests.get('http:\/\/yourip\/cgi-bin\/mediaFileFind.cgi?action=close&amp;object={}'.format(factory),auth=auth)<\/pre>\n<p>Totally worked! The loop over files.iter_lines just searches through the like 15 lines of information that come out for each file for the one that has the path on it. I did some name mangling in the open line to strip off the root folder names from the camera path so I just had a nice file name in my directory, such as: `17-07-10-001-jpg-17-48-07[R][0@0][0].jpg`<\/p>\n<p>So this got me all my files from my vacation. I transferred 2GB of photos by running this in a loop (with security provided by a VPN on the router). It would be better if I could grab those cookies directly from the script instead of cheating with the web browser so if you know how to do that with <code>requests<\/code>, let me know.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>UPDATE 2021: This was fun but nowadays I have to direct people to a more complete python solution here. I got a few Amcrest Wifi security cameras for my mom&#8217;s house at her request. They&#8217;re pretty nice overall (My only complaint is that the web-interface doesn&#8217;t fully support Linux). I set one up to save &hellip; <a href=\"https:\/\/partofthething.com\/thoughts\/downloading-files-from-an-amcrest-security-camera-with-python\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Downloading files from an Amcrest security camera with Python<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":""},"categories":[3,75,72],"tags":[],"class_list":["post-1390","post","type-post","status-publish","format-standard","hentry","category-computers","category-home-automation","category-photography"],"_links":{"self":[{"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/posts\/1390","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/comments?post=1390"}],"version-history":[{"count":13,"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/posts\/1390\/revisions"}],"predecessor-version":[{"id":2101,"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/posts\/1390\/revisions\/2101"}],"wp:attachment":[{"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/media?parent=1390"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/categories?post=1390"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/partofthething.com\/thoughts\/wp-json\/wp\/v2\/tags?post=1390"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}