Multimedia

General multimedia handling

Multimedia metadata is stored in couch, using CommCareMultimedia and its subclasses: CommCareImage, CommCareAudio, etc.

Each file is stored once, regardless of how many applications or domains use it. This is enforced via the by_hash view, which stores a hash of each multimedia file’s content. When new multimedia is uploaded, the contents are hashed and looked up to determine wheether or not to create a new document. See CommCareMultimedia.get_by_data and its calling code in places like BaseProcessFileUploadView.process_upload.

These documents are never deleted.

Multimedia in applications

The app’s multimedia_map

The biggest use case for multimedia in CommCare is displaying multimedia in applications. The application’s multimedia_map property stores information about where it uses multimedia.

multimedia_map is a dict where each key is a path and each value is a dict corresponding to an HQMediaMapItem. The map has one entry for every path, also called a reference, in the application. If an application uses the same image as an icon for two forms, it will have two entries in the map, unless a user has edited the app so that both forms use the same path.

Sample multimedia_map entry:

"jr://file/commcare/image/module0_en.jpg": {
    "doc_type": "HQMediaMapItem",
    "media_type": "CommCareImage",
    "multimedia_id": "7f14f2dc29fa7c406dc1b0d40603e742",
    "unique_id": "b6ee70e5e61ea550b26d36cc185dde23",
    "version": 17
}

The path is auto-generated by HQ based on where the file is being used. It can be manually edited - everywhere that a multimedia file can be uploaded, its path can be edited. There is also a tool to edit multimedia paths in bulk via Excel.

The doc_type is always HQMediaMapItem.

The media_type is CommCareMultimedia or one of its subclasses.

The multimedia_id is the id of the corresponding CommCareMultimedia document.

The unique_id is a hash of the concatenated multimedia id and path at the time the item was created. That means this id will be unique within the multimedia map, but will not be globally unique.

The version is the app version where the multimedia was added or most recently changed. The version can be None for applications that are unbuilt, and then any blank versions will be assigned when a new build is made. More on this below.

Versioning multimedia

CommCare (on mobile) uses the version to determine when to re-download an updated multimedia file. The version will always be an app version. This correspondence isn’t necessary; all the phone checks is if the current version is greater than the version already on the phone - if so, the phone will re-download the multimedia. This logic is based on the logic used to download updated forms.

The version is updated (set to the latest app version) in the following situations:

  • Multimedia is added to the app.

  • The content of multimedia is changed, by using the “Replace” button in the uploader. This also causes the multimedia id to change. It typically does not change the unique*id, because set*media*versions looks up the path in the previous version of the app and uses that item’s unique id. However, it may change the unique*id for form question media, because form questions include a random string at the end of their path which changes when a user uploads a new file.

  • The path alone is changed using the “Manage Multimedia Paths” bulk uploader. This does not change the unique id, even though the path changes.

  • The path and content are changed together in the UI. This also replaces the multimedia id and re-generates the unique id.

Linked apps

Linked apps, when pulled, copy the multimedia map directly from the upstream app, so all the attributes of each item will match those in the upstream app. Because linked apps are always pulled from a released version of an upstream app, each item should have a version set.

media_suite.xml

The media suite contains a list of media elements, one for each value in the multimedia map.

<media path="../../commcare/image">
    <resource descriptor="Image File: FILENAME" id="media-UNIQUE_ID-FILENAME" version="VERSION">
        <location authority="local">PATH</location>
        <location authority="remote">
            URL
        </location>
    </resource>
</media>
  • FILENAME is originally generated by HQ and will be fairly readable, something like module0_en.jpg, and may be modified by users.

  • PATH will be the path to the file on the device, so similar to the path used as a key in the multimedia map, though in a format like ./commcare/image/module0*en.jpg rather than the jr://commcare/image/module0*en.jpg format used in the map.

  • UNIQUE_ID and VERSION are from the multimedia map.

  • URL is the url to access the file on the server and incorporates the media type, multimedia id, and filename, e.g., http://www.commcarehq.org/hq/multimedia/file/CommCareImage/7f14f2dc29fa7c406dc1b0d40603e742/module0_en.jpg.

If the same file is uploaded to two different paths, it will be included twice on the device, but on the server it will be stored only once and will have only one CommCareMultimedia document. Although there will be two different URLs in the media suite, they will point to the same page: HQ only uses the multimedia id to identify the file, it ignores the URL’s filename suffix.