Downloading MP4


#1

Product: Mambo
Product version: 3.0.26
SDK version: 3.14.0
Use of libARController: YES
SDK platform: Android
Reproducible with the official app: No

I am attempting to list (and eventually download over WiFi) saved videos from a Mambo Drone with attached FPV camera, there is an SD card inserted into the FPV camera. I am running this code to get a list of media on the device using the SDK:

(Code is Kotlin)

fun fetchMediaList(callback: (List<ARMediaObject>) -> Unit) {
        thread {
            val mediaList: ArrayList<ARMediaObject> = ArrayList()
            val mediasDownloader: ARDataTransferMediasDownloader = dataTransferManager.arDataTransferMediasDownloader

            if (mediasDownloader != null) {
                val mediaListCount = mediasDownloader.getAvailableMediasSync(false)
                (0 until mediaListCount).forEach { i ->
                    val currentMedia = mediasDownloader.getAvailableMediaAtIndex(i)
                    val currentARMediaObject = ARMediaObject()
                    currentARMediaObject.updateDataTransferMedia(context.resources, currentMedia)
                    mediaList.add(currentARMediaObject)
                }
            }

            mediaList.trimToSize()
            runOnUiThread { callback(mediaList) }
        }
    }

When this code runs it only returns a list of JPGs taken by the under-body onboard camera. Similarly, when I FTP into the drone from my desktop and list the contents available I only get JPGs. However, if I remove the SD card and read it on my desktop, all of my MP4 are available.

Am I missing something simple here? I hacked together that code following the guidance outlined here: https://developer.parrot.com/docs/bebop/?java#taking-a-picture

When I use the FreeFlight application I see and can download the MP4s so I presume that I am missing something simple here, but I can’t track down what it is.

When I use the SDK sample Activities I can only fetch JPGs.


#2

An Update for The Interested

It appears that the Mambo’s MiniCam attachment does not, in fact, use the FTP interface described in the documentation.
Instead it uses a combination of RESTful HTTP calls and sockets to query and transfer data.

If you connect to the drone’s wifi and send a GET request to 192.168.99.3:8888/api/v1/medias you will receive a JSON blob in response. It will look something like this:

$ curl http://192.168.99.3:8888/api/v1/medias

{  
  "resource":[  
       {  
          "path":"\/data\/0\/record_0000_0002.mp4",
          "type":"video",
          "minicam":{  
             "socket_dl_available":true,
             "socket_dl_path":"\/socket\/0\/record_0000_0002.mp4"
          },
          "resolution":"720p",
          "format":"mp4",
          "size":1559544
       },
       {  
          "path":"\/data\/4\/record_0000_0002.jpg",
          "type":"thumbnail",
          "minicam":{  
             "socket_dl_available":true,
             "socket_dl_path":"\/socket\/4\/record_0000_0002.jpg"
          },
          "format":"jpg"
       },
       {  
          "path":"rtsp:\/\/192.168.99.2:554\/0\/record_0000_0002.mp4",
          "type":"streaming",
          "resolution":"720p",
          "format":"mp4"
       }
    ],
    "type":"video",
    "uid":"0-record_0000_0002.mp4",
    "date":"20181024171600"
  },

  ... // More JSON objects

]

Then you have some options. You can stream the stored mp4 directly over rtsp, ie:

$ ffplay rtsp://192.168.99.2:554/0/record_0000_0002.mp4

You can get the thumbnail associated with the video by sending a GET request, ie:

$ curl http://192.168.99.3:8888/data/4/record_0000_0002.jpg -o my-thumbnail.jpg

or, and this is where things get a bit different, you can query for an IP address to a socket that will spit out an mp4 file for you. So if you do something like:

$ curl http://192.168.99.3:8888/socket/0/record_0000_0002.mp4

You will get another JSON response that will look something like this: { "ip": "192.168.99.1", "port": 49158 }
If you take that and perform a request against it like this:

$ nc 192.168.99.1 49158 > my-video.mp4

(These appear to close pretty quickly, so you have to make this request almost immediately after requesting the above address object)

you will receive what appears to be an mp4 encoded binary. Unfortunately, at this point I am stuck again because all of the mp4s I try to grab in this way appear to be corrupted in some way that I can’t suss out, so if anyone has any advice on that piece I would LOVE to hear it.

EDIT: an update on my update:

It appears that 4 unexpected bytes were being thrown in front of the mp4 file when using the method outlined above. No idea why. SO if you’re using the above method try something like this when downloading the mp4 instead:

$ nc 192.168.99.1 49158 | tail -c +5 > my-video.mp4

Edit to my edit to my update:

I am an idiot. You don’t need to do all of the raw socket stuff that I outlined above, you can just go to the path indicated in the original resource object, ala:

$ curl http://192.168.99.3:8888/data/0/record_0000_0002.mp4 -o my-easier-to-download.mp4"

Do you ever forget how to read?