Python Tutorial 7: Camera Media List

9 minute read

This document will provide a walk-through tutorial to use the Python requests package to send Open GoPro HTTP commands to the GoPro, specifically to get the media list and perform operations on it (downloading pictures, videos, etc.)

It is required that you have first completed the Connecting to Wifi and Sending WiFi Commands tutorials.

This tutorial only considers sending these commands as one-off commands. That is, it does not consider state management / synchronization when sending multiple commands. This will be discussed in a future tutorial.

Requirements

It is assumed that the hardware and software requirements from the connect tutorial are present and configured correctly.

The scripts that will be used for this tutorial can be found in the Tutorial 7 Folder.

Just Show me the Demo(s)!!

If you just want to run the demo, you can find Python scripts for each of the concepts in this tutorial in the Open GoPro GitHub repo.

Python >= 3.8.x must be used as specified in the requirements
Each of the scripts for this tutorial can be found in this directory of the repo: demos/python/tutorial/tutorial_modules/tutorial_7_camera_media_list/
You must be connected to the camera via WiFi in order to run these scripts. You can do this by manually to the SSID and password listed on your camera or by leaving the Establish Connection to WiFi AP script from Tutorial 5 running in the background.

You can downloading a file from your camera with HTTP over WiFi using the following script:

$ python wifi_media_download_file.py

See the help for parameter definitions:

$ python wifi_media_download_file.py --help
usage: wifi_media_download_file.py [-h]

Find a photo on the camera and download it to the computer.

optional arguments:
  -h, --help  show this help message and exit

You can downloading the GPMF for a media file from your camera with HTTP over WiFi using the following script:

$ python wifi_media_get_gpmf.py

See the help for parameter definitions:

$ python wifi_media_get_gpmf.py --help
usage: wifi_media_get_gpmf.py [-h]

Get the GPMF for a media file.

optional arguments:
  -h, --help  show this help message and exit

You can downloading the screennail (higher resolution thumbnail) for a media file from your camera with HTTP over WiFi using the following script:

$ python wifi_media_get_screennail.py

See the help for parameter definitions:

$ python wifi_media_get_screennail.py --help
usage: wifi_media_get_screennail.py [-h]

Get the screennail for a media file.

optional arguments:
  -h, --help  show this help message and exit

You can downloading the thumbnail for a media file from your camera with HTTP over WiFi using the following script:

$ python wifi_media_get_thumbnail.py

See the help for parameter definitions:

$ python wifi_media_get_thumbnail.py --help
usage: wifi_media_get_thumbnail.py [-h]

Get the thumbnail for a media file.

optional arguments:
  -h, --help  show this help message and exit

Setup

We must first connect to The GoPro’s WiFi Access Point (AP) as was discussed in the Connecting to Wifi tutorial.

Get Media List

Now that we are are connected via WiFi, we will get the media list using the same procedure to send HTTP commands as in the previous tutorial.

  • We get the media list via the Get Media List command. This command will return a JSON structure of all of the media files (pictures, videos) on the camera with corresponding information about each media file.

    Let’s first build the endpoint:

    url = GOPRO_BASE_URL + "/gopro/media/list"
    

    Now we send the GET request and check the response for errors. Any errors will raise an exception.

    response = requests.get(url)
    response.raise_for_status()
    

    Lastly, we print the response’s JSON data (nicely formatted with indent 4 using the json module):

    logger.info(f"Response: {json.dumps(response.json(), indent=4)}")
    

    Go to the next tab for examples of viewing and parsing the response.

  • The response will log as such (abbreviated for brevity):

    INFO:root:Getting the media list: sending http://10.5.5.9:8080/gopro/media/list
    INFO:root:Command sent successfully
    INFO:root:Response: {
        "id": "2510746051348624995",
        "media": [
            {
                "d": "100GOPRO",
                "fs": [
                    {
                        "n": "GOPR0987.JPG",
                        "cre": "1618583762",
                        "mod": "1618583762",
                        "s": "5013927"
                    },
                    {
                        "n": "GOPR0988.JPG",
                        "cre": "1618583764",
                        "mod": "1618583764",
                        "s": "5009491"
                    },
                    {
                        "n": "GOPR0989.JPG",
                        "cre": "1618583766",
                        "mod": "1618583766",
                        "s": "5031861"
                    },
                    {
                        "n": "GX010990.MP4",
                        "cre": "1451608343",
                        "mod": "1451608343",
                        "glrv": "806586",
                        "ls": "-1",
                        "s": "10725219"
                    },
    

    The media list format is defined in the Open GoPro Specification. We won’t be rehashing that here but will provide examples below of using the media list.

    One common functionality is to get the list of media file names, which can be done as such:

    print([x["n"] for x in media_list["media"][0]["fs"]])
    

    That is, access the list at the fs tag at the first element of the media tag, then make a list of all of the names (n tag of each element) in the fs list.

Media List Operations

Whereas all of the WiFi commands described until now have returned JSON responses, most of the media list operations return binary data. From an HTTP perspective, the behavior is the same. However, the GET response will contain a large binary chunk of information so we will loop through it with the requests library as such, writing up to 8 kB at a time:

diskOpen GoPro user deviceGoProPC connected to WiFi APloop[write until complete]Get Media List (GET)Media List (HTTP 200 OK)Command Request (GET)Binary Response (HTTP 200 OK)write <= 8KdiskOpen GoPro user deviceGoPro

Download Media File

The next command we will be sending is Download Media. Specifically, we will be downloading a photo. The camera must have at least one photo in its media list in order for this to work.

First, we get the media list as in Get Media List . Then we search through the list of file names in the media list looking for a photo (i.e. a file whose name ends in .jpg). Once we find a photo, we proceed:

media_list = get_media_list()

photo: Optional[str] = None
for media_file in [x["n"] for x in media_list["media"][0]["fs"]]:
    if media_file.lower().endswith(".jpg"):
        logger.info(f"found a photo: {media_file}")
        photo = media_file
        break

Now let’s build the endpoint to download the photo whose name we just found:

url = GOPRO_BASE_URL + f"videos/DCIM/100GOPRO/{photo}"
The endpoint will start with “videos” for both photos and videos

Next we send the GET request and check the response for errors. Any errors will raise an exception.

with requests.get(url, stream=True) as request:
    request.raise_for_status()

Lastly, we iterate through the binary content in 8 kB chunks, writing to a local file:

file = photo.split(".")[0] + ".jpg"
with open(file, "wb") as f:
    logger.info(f"receiving binary stream to {file}...")
    for chunk in request.iter_content(chunk_size=8192):
        f.write(chunk)

This will log as such:

INFO:root:found a photo: GOPR0987.JPG
INFO:root:Downloading GOPR0987.JPG
INFO:root:Sending: http://10.5.5.9:8080/videos/DCIM/100GOPRO/GOPR0987.JPG
INFO:root:receiving binary stream to GOPR0987.jpg...

Once complete, the GOPR0987.jpg file will be available from where the demo script was called.

Get Media GPMF

The next command we will be sending is Get Media GPMF. More information about GPMF can be found here. Specifically, we will be downloading the GPMF for a photo. The camera must have at least one photo in its media list in order for this to work.

First, we get the media list as in Get Media List . Then we search through the list of file names in the media list looking for a photo (i.e. a file whose name ends in .jpg). Once we find a photo, we proceed:

media_list = get_media_list()

photo: Optional[str] = None
for media_file in [x["n"] for x in media_list["media"][0]["fs"]]:
    if media_file.lower().endswith(".jpg"):
        logger.info(f"found a photo: {media_file}")
        photo = media_file
        break

Now let’s build the endpoint to download the GPMF for the photo whose name we just found:

url = GOPRO_BASE_URL + f"/gopro/media/gpmf?path=100GOPRO/{photo}"

Next we send the GET request and check the response for errors. Any errors will raise an exception.

with requests.get(url, stream=True) as request:
    request.raise_for_status()

Lastly, we iterate through the binary content in 8 kB chunks, writing to a local file:

file = photo.split(".")[0] + ".jpg"
with open(file, "wb") as f:
    logger.info(f"receiving binary stream to {file}...")
    for chunk in request.iter_content(chunk_size=8192):
        f.write(chunk)

This will log as such:

INFO:root:found a photo: GOPR0987.JPG
INFO:root:Getting the GPMF for GOPR0987.JPG
INFO:root:Sending: http://10.5.5.9:8080/gopro/media/gpmf?path=100GOPRO/GOPR0987.JPG
INFO:root:receiving binary stream to GOPR0987.gpmf...

Once complete, the GOPR0987.gpmf file will be available from where the demo script was called.

Get Media Screennail

The next command we will be sending is Get Media Screennail . Specifically, we will be getting the screennail for a photo. The camera must have at least one photo in its media list in order for this to work.

There is a separate command (shown below) to get a media “thumbnbail”

First, we get the media list as in Get Media List . Then we search through the list of file names in the media list looking for a photo (i.e. a file whose name ends in .jpg). Once we find a photo, we proceed:

media_list = get_media_list()

photo: Optional[str] = None
for media_file in [x["n"] for x in media_list["media"][0]["fs"]]:
    if media_file.lower().endswith(".jpg"):
        logger.info(f"found a photo: {media_file}")
        photo = media_file
        break

Now let’s build the endpoint to download the screennail for the photo whose name we just found:

url = GOPRO_BASE_URL + f"/gopro/media/screennail?path=100GOPRO/{photo}"

Next we send the GET request and check the response for errors. Any errors will raise an exception.

with requests.get(url, stream=True) as request:
    request.raise_for_status()

Lastly, we iterate through the binary content in 8 kB chunks, writing to a local file:

file = photo.split(".")[0] + ".jpg"
with open(file, "wb") as f:
    logger.info(f"receiving binary stream to {file}...")
    for chunk in request.iter_content(chunk_size=8192):
        f.write(chunk)

This will log as such:

INFO:root:found a photo: GOPR0987.JPG
INFO:root:Getting the screennail for GOPR0987.JPG
INFO:root:Sending: http://10.5.5.9:8080/gopro/media/screennail?path=100GOPRO/GOPR0987.JPG
INFO:root:receiving binary stream to GOPR0987_screennail.jpg...

Once complete, the GOPR0987_screennail.jpg file will be available from where the demo script was called.

Get Media Thumbnail

The next command we will be sending is Get Media thumbnail . Specifically, we will be getting the thumbnail for a photo. The camera must have at least one photo in its media list in order for this to work.

There is a separate command (shown above) to get a media “screennail”

First, we get the media list as in Get Media List . Then we search through the list of file names in the media list looking for a photo (i.e. a file whose name ends in .jpg). Once we find a photo, we proceed:

media_list = get_media_list()

photo: Optional[str] = None
for media_file in [x["n"] for x in media_list["media"][0]["fs"]]:
    if media_file.lower().endswith(".jpg"):
        logger.info(f"found a photo: {media_file}")
        photo = media_file
        break

Now let’s build the endpoint to download the thumbnail for the photo whose name we just found:

url = GOPRO_BASE_URL + f"/gopro/media/thumbnail?path=100GOPRO/{photo}"

Next we send the GET request and check the response for errors. Any errors will raise an exception.

with requests.get(url, stream=True) as request:
    request.raise_for_status()

Lastly, we iterate through the binary content in 8 kB chunks, writing to a local file:

file = photo.split(".")[0] + ".jpg"
with open(file, "wb") as f:
    logger.info(f"receiving binary stream to {file}...")
    for chunk in request.iter_content(chunk_size=8192):
        f.write(chunk)

This will log as such:

INFO:root:found a photo: GOPR0987.JPG
INFO:root:Getting the thumbnail for GOPR0987.JPG
INFO:root:Sending: http://10.5.5.9:8080/gopro/media/thumbnail?path=100GOPRO/GOPR0987.JPG
INFO:root:receiving binary stream to GOPR0987_thumbnail.jpg...

Once complete, the GOPR0987_thumbnail.jpg file will be available from where the demo script was called.

Troubleshooting

See the previous tutorial’s troubleshooting section.

Good Job!

Congratulations 🤙

You can now query the GoPro’s media list and retrieve binary information for media file. This is currently last tutorial. Stay tuned for more 👍

At this point you should be able to start creating a useful example using the Open GoPro Interface. For some inspiration check out some of the demos.

Updated: