NEWDolby Media Processing APIs are now the Dolby.io Media APIs Learn More >
X

Transcoding Media

The Dolby.io Media Transcode API is designed to convert your media from one format to another. The Transcoding Media page explains the concept in more detail.

This tutorial will show you how to use the API to convert your media to popular formats playable in browsers and on mobile devices.

Getting Started

To get started you'll follow these steps.

  1. Get your API key
  2. Prepare your media
  3. Make a Transcode request
  4. Check the job status
  5. Review media

1. Get Your API Key

To use the Transcode API you need an API key. When you sign up for an account you are able to retrieve your API key from the Dolby.io dashboard. It is a unique identifier that is passed to all API requests as a header called x-api-key.

2. Prepare Your Media

You have a choice for how to make your media available for transcoding:

a. Use your own cloud storage provider.
b. Use our Dolby Media Input API.

a. Use your own cloud storage provider

You will want to consider this option when you move your applications into production. Our services are able to work with many popular cloud storage services such as AWS S3, GCP Cloud Storage, or your own services with basic or token-based authentication.

Additionally, the /media/transcode API allows you to specify your storage bucket URI and its access credentials in a storage block. This method is required when requesting streaming media outputs, such as hls and dash. Refer to section 3.2 and section 3.3 for examples of using a bucket URI with the /media/transcode API.

b. Use our Dolby Media Input API (optional)

The Media Input API was designed to give you a quick way to upload media while evaluating Media Processing services. We can securely store your media temporarily; however, any media you upload will be removed regularly, so the Media Input API shouldn't be used for permanent storage.

Please see the Media Input and Output guide for more details on the various options.

3. Make a Transcode Request

3.1 Simple Transcode (Example: MP4 with H.265 video → MP4 with H.264 video + Thumbnail)

Assumptions:

  • Content to be processed is available locally and is an MP4 with H.265 video
  • Transcoded content is downloaded to a local file after transcoding

The Transcode API requires both inputs and at least one outputs parameter to begin transcoding your media. There are additional parameters that can be used to customize the transcode based on your requirements but we'll keep this example simple.

Regardless of whether you chose to use your own cloud storage or our /media/input service, our API will need to be able to read the media. See the Media Input and Output guide for a more detailed explanation of the various ways you can provide authentication details.

Additionally, the Transcode API provides the capability to read input content from a storage bucket. If you have AWS or GS or AZ storage, you can provide the bucket name and temporary authentication tokens, so that our API can access the files directly from the bucket.

These are all valid source values:

dlb://in/example.mp4
https://dolbyio.s3-us-west-1.amazonaws.com/public/shelby/indoors.original.mp4

Similarly, for the destination parameter of your outputs you can use any location to which our APIs will be able to write. As this is less common, specifying a dlb:// output location will create one on the fly.

import os
import requests

url = "https://api.dolby.com/media/transcode"
headers = {
    "x-api-key": os.environ["DOLBYIO_API_KEY"],
    "Content-Type": "application/json",
    "Accept": "application/json",
}

body = {
    "inputs": [{ "source" : os.environ["DOLBYIO_INPUT"] }],
    "outputs": [
        {
            "id" : "MP4-H.264",
            "destination" : "dlb://out/example_transcoded.mp4",
            "kind" : "mp4",
            "audio" : {
                "codec" : "aac_lc",
                "bitrate_kb": 128
            },
            "video" : {
                "codec" : "h264",
                "width" : 1920,
                "height" : 1080,
                "frame_rate" : 30,
                "bitrate_mode" : "vbr",
                "bitrate_kb" : 24883
            }
        },
        {
            "id" : "thumbnail",
            "destination" : "dlb://out/airplane_thumbnail.jpg",
            "kind" : "jpg",
            "image" : {
                "codec" : "png",
                "height" : 128,
                "width" : 128
            }
        }
    ]
}

try:
    response = requests.post(url, json=body, headers=headers)
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    raise Exception(response.text)
print(response.json()["job_id"])
const axios = require("axios").default
const config = {
    method: "post",
    url: "https://api.dolby.com/media/transcode",
    headers: {
        "x-api-key": process.env.DOLBYIO_API_KEY,
        "Content-Type": "application/json",
        Accept: "application/json",
    },
    data: {
        inputs : [ {source: "dlb://in/example.mp4"} ],
        outputs: [
            {
                id: "MP4-H.264",
                destination: "dlb://out/example_transcoded.mp4",
                kind: "mp4",
                audio: {
                    codec: "aac_lc",
                    bitrate_kb: 128
                },
                video: {
                    codec: "h264",
                    width: 1920,
                    height: 1080,
                    frame_rate: 30,
                    bitrate_mode: vbr,
                    bitrate_kb: 24883
                }
            },
            {
                id: "thumbnail",
                destination: "dlb://out/airplane_thumbnail.jpg",
                kind: "jpg",
                image: {
                    codec: "png",
                    width: 128,
                    height: 128
                }
            }
        ]
    }
}
axios(config)
    .then(function(response) {
        console.log(response.data.job_id)
    })
    .catch(function(error) {
        console.log(error)
    })
#!/bin/bash

curl -X POST "https://api.dolby.com/media/transcode" \
    --header "x-api-key: $DOLBYIO_API_KEY" \
    --data '{
        "inputs": [{"source": "dlb://in/example.mp4"}],
        "outputs": [
            {
                "id" : "MP4-H.264",
                "destination" : "dlb://out/example_transcoded.mp4",
                "kind" : "mp4",
                "audio" : {
                    "codec" : "aac_lc",
                    "bitrate_kb": 128
                },
                "video" : {
                    "codec" : "h264",
                    "width" : 1920,
                    "height" : 1080,
                    "frame_rate" : 30,
                    "bitrate_mode" : "vbr",
                    "bitrate_kb" : 24883
                }
            },
            {
                "id" : "thumbnail",
                "destination" : "dlb://out/airplane_thumbnail.jpg",
                "kind" : "jpg",
                "image" : {
                    "codec" : "png",
                    "width" : 128,
                    "height" : 128
                }
            }
        ]
    }'

3.2 Simple Transcode with cloud output storage (Example: MP4 → MP4 + Thumbnail)

Assumption:

  • Content to be processed is available locally

In order to use a cloud storage provider, along with the inputs and at least one outputs parameter, a storage entry must be provided with its associated parameters.

For inputs, follow example 3.1, while for outputs, follow the example given below. If you have AWS or GS or AZ storage, you can provide the bucket name and temporary authentication tokens, so that our API can write the files directly to the bucket.

The storage parameter may include separate buckets for inputs and outputs if desired. The id of any storage bucket should match the id of the source parameter for input media or of the destination parameter for transcoded outputs.

Here is an example:

import os
import requests

url = "https://api.dolby.com/media/transcode"
headers = {
    "x-api-key": os.environ["DOLBYIO_API_KEY"],
    "Content-Type": "application/json",
    "Accept": "application/json",
}

body = {
    "inputs": [{ "source" : os.environ["DOLBYIO_INPUT"] }],
    "outputs": [
        {
            "id" : "MP4-H.264",
            "destination" : {
                "id" : "s3",
                "filename" :  "airplane_transcoded.mp4"
            },
            "kind" : "mp4",
            "audio" : {
                "codec" : "aac_lc",
                "bitrate_kb": 128
            },
            "video" : {
                "codec" : "h264",
                "width" : 1920,
                "height" : 1080,
                "frame_rate" : 30,
                "bitrate_mode" : "vbr",
                "bitrate_kb" : 24883
            }
        },
        {
            "id" : "thumbnail",
            "destination" : {
                "id" : "s3",
                "filename" :  "airplane_thumbnail.jpg"
            },
            "kind" : "jpg",
            "image" : {
                "codec" : "png",
                "width" : 128,
                "height" : 128
            }
        }
    ],
    "storage" : [
        {
            "id" : "s3",
            "bucket" : {
                "url" : "s3://my-storage-bucket/output/",
                "auth" : {
                    "key": "my-auth-key",
                    "secret": "my-secret-key"
                }
            }
        }
    ]
}

try:
    response = requests.post(url, json=body, headers=headers)
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    raise Exception(response.text)
print(response.json()["job_id"])
const axios = require("axios").default
const config = {
    method: "post",
    url: "https://api.dolby.com/media/transcode",
    headers: {
        "x-api-key": process.env.DOLBYIO_API_KEY,
        "Content-Type": "application/json",
        Accept: "application/json",
    },
    data: {
        inputs : [ {source: "dlb://in/example.mp4"} ],
        outputs: [
            {
                id: "MP4-H.264",
                destination: {
                    id : "s3",
                    filename :  "airplane_transcoded.mp4"
                },
                kind: "mp4",
                audio: {
                    codec: "aac_lc",
                    bitrate_kb: 128
                },
                video: {
                    codec: "h264",
                    width: 1920,
                    height: 1080,
                    frame_rate: 30,
                    bitrate_mode: vbr,
                    bitrate_kb: 24883
                }
            },
            {
                id: "thumbnail",
                destination: {
                    id : "s3",
                    filename :  "airplane_thumbnail.jpg"
                },
                kind: "jpg",
                image: {
                    codec: "png",
                    width: 128,
                    height: 128
                }
            }
        ],
        storage: [
            {
                id: "s3",
                bucket: {
                    url: "s3://my-storage-bucket/output/",
                    auth: {
                        key: "my-auth-key",
                        secret: "my-secret-key"
                    }
                }
            }
        ]
    }
}
axios(config)
    .then(function(response) {
        console.log(response.data.job_id)
    })
    .catch(function(error) {
        console.log(error)
    })
#!/bin/bash

curl -X POST "https://api.dolby.com/media/transcode" \
    --header "x-api-key: $DOLBYIO_API_KEY" \
    --data '{
        "inputs: [{"source": "dlb://in/example.mp4"}],
        "outputs": [
            {
                "id" : "MP4-H.264",
                "destination" : {
                    "id" : "s3",
                    "filename" :  "airplane_transcoded.webm"
                },
                "kind" : "mp4",
                "audio" : {
                    "codec" : "aac_lc",
                    "bitrate_kb": 128
                },
                "video" : {
                    "codec" : "h264",
                    "width" : 1920,
                    "height" : 1080,
                    "frame_rate" : 30,
                    "bitrate_mode" : "vbr",
                    "bitrate_kb" : 24883
                }
            },
            {
                "id" : "thumbnail",
                "destination" : {
                    "id" : "s3",
                    "filename" :  "airplane_thumbnail.jpg"
                },
                "kind" : "jpg",
                "image" : {
                    "codec" : "png",
                    "width" : 128,
                    "height": 128
                }
            }
        ],
        "storage" : [
            {
                "id" : "s3",
                "bucket" : {
                    "url" : "s3://my-storage-bucket/output/",
                    "auth" : {
                        "key": "my-auth-key",
                        "secret": "my-secret-key"
                    }
                }
            }
        ]
    }'

3.3 Streaming output written to a cloud storage bucket

Assumptions:

  • Input media is available in a cloud storage bucket
  • Transcoded media and streaming manifest are to be written to the same bucket
  • Access keys provided for the bucket are temporary and valid for the duration of the request

In order to use a cloud storage provider, along with the inputs and at least one outputs parameter, a storage entry must be provided with its associated parameters.

As shown in section 3.2, if you have AWS or GS or AZ storage, you can provide the bucket name and temporary authentication tokens, so that our API can read and write the files directly to the bucket.

If the file to be transcoded is on S3 at s3://my-storage-bucket/folder-1/file-1.mp4, then the storage bucket would have the url "s3://my-storage-bucket/folder-1/", and the input source would have the filename "file-1.mp4". Both storage and the input source would share an id, such as "s3_input".

Here is an example:

import os
import requests

url = "https://api.dolby.com/media/transcode"
headers = {
    "x-api-key": os.environ["DOLBYIO_API_KEY"],
    "Content-Type": "application/json",
    "Accept": "application/json",
}

body = {
    "inputs": [
        { 
            "source" :  {
                "id" : "s3_input",
                "filename" : "media_file1.mp4"
            }
        }
    ],
    "outputs": [
        {
            "id" : "vid_1080p",
            "destination" : {
                "id" : "s3_output",
                "filename" :  "airplane_1080p.mp4"
            },
            "kind" : "mp4",
            "audio" : "remove",
            "video" : {
                "codec" : "h265",
                "width" : 1920,
                "height" : 1080,
                "frame_rate" : 30,
                "bitrate_mode" : "vbr",
                "bitrate_kb" : 7800
            }
        },
        {
            "id" : "vid_720p",
            "destination" : {
                "id" : "s3_output",
                "filename" :  "airplane_720p.mp4"
            },
            "kind" : "mp4",
            "audio" : "remove",
            "video" : {
                "codec" : "h265",
                "width" : 1280,
                "height" : 720,
                "frame_rate" : 30,
                "bitrate_mode" : "vbr",
                "bitrate_kb" : 4500
            }
        },
        {
            "id" : "vid_480p",
            "destination" : {
                "id" : "s3_output",
                "filename" :  "airplane_480p.mp4"
            },
            "kind" : "mp4",
            "audio" : "remove",
            "video" : {
                "codec" : "h265",
                "width" : 640,
                "height" : 480,
                "frame_rate" : 30,
                "bitrate_mode" : "vbr",
                "bitrate_kb" : 1100
            }
        },
        {
            "id" : "aud_hi",
            "destination" : {
                "id" : "s3_output",
                "filename" :  "airplane_audio_hi.mp4"
            },
            "kind" : "mp4",
            "video" : "remove",
            "audio" : {
                "codec" : "aac_lc",
                "bitrate_kb" : 384,
                "channels" : 6
            }
        },
        {
            "id" : "aud_lo",
            "destination" : {
                "id" : "s3_output",
                "filename" :  "airplane_audio_lo.mp4"
            },
            "kind" : "mp4",
            "video" : "remove",
            "audio" : {
                "codec" : "aac_lc",
                "bitrate_kb" : 96,
                "channels" : 2
            }
        },
        {
            "id" : "hls_out",
            "destination" : {
                "id" : "s3_output",
                "filename" :  "airplane_manifest.m3u8"
            },
            "kind" : "hls",
            "segment_duration_sec" : 6
        }
    ],
    "storage" : [
        {
            "id" : "s3_input",
            "bucket" : {
                "url" : "s3://my-storage-bucket/input/",
                "auth" : {
                    "key": "my-auth-key",
                    "secret": "my-secret-key"
                }
            }
        },
        {
            "id" : "s3_output",
            "bucket" : {
                "url" : "s3://my-storage-bucket/output/",
                "auth" : {
                    "key": "my-auth-key",
                    "secret": "my-secret-key"
                }
            }
        }
    ]
}

try:
    response = requests.post(url, json=body, headers=headers)
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    raise Exception(response.text)
print(response.json()["job_id"])
const axios = require("axios").default
const config = {
    method: "post",
    url: "https://api.dolby.com/media/transcode",
    headers: {
        "x-api-key": process.env.DOLBYIO_API_KEY,
        "Content-Type": "application/json",
        Accept: "application/json",
    },
    data: {
        inputs : [ 
            {
                source: {
                    id : "s3_input",
                    filename : "media_file1.mp4"
                }
            } 
        ],
        outputs: [
            {
                id : "vid_1080p",
                destination : {
                    id : "s3_output",
                    filename :  "airplane_1080p.mp4"
                },
                kind : "mp4",
                audio : "remove",
                video : {
                    codec : "h265",
                    width : 1920,
                    height : 1080,
                    frame_rate : 30,
                    bitrate_mode : "vbr",
                    bitrate_kb : 7800
                }
            },
            {
                id : "vid_720p",
                destination : {
                    id : "s3_output",
                    filename :  "airplane_720p.mp4"
                },
                kind : "mp4",
                audio : "remove",
                video : {
                    codec : "h265",
                    width : 1280,
                    height : 720,
                    frame_rate : 30,
                    bitrate_mode : "vbr",
                    bitrate_kb : 4500
                }
            },
            {
                id : "vid_480p",
                destination : {
                    id : "s3_output",
                    filename :  "airplane_480p.mp4"
                },
                kind : "mp4",
                audio : "remove",
                video : {
                    codec : "h265",
                    width : 640,
                    height : 480,
                    frame_rate : 30,
                    bitrate_mode : "vbr",
                    bitrate_kb : 1100
                }
            },
            {
                id : aud_hi,
                destination : {
                    id : "s3_output",
                    filename :  "airplane_audio_hi.mp4"
                },
                kind : "mp4",
                video : "remove",
                audio : {
                    codec : "aac_lc",
                    bitrate_kb : 384,
                    channels : 6
                }
            },
            {
                id : "aud_lo",
                destination : {
                    id : "s3_output",
                    filename :  "airplane_audio_lo.mp4"
                },
                kind : "mp4",
                video : "remove",
                audio : {
                    codec : "aac_lc",
                    bitrate_kb : 96,
                    channels : 2
                }
            },
            {
                id : "hls_out",
                destination : {
                    id : "s3_output",
                    filename :  "airplane_manifest.m3u8"
                },
                kind : "hls",
                segment_duration_sec : 6
            }
        ],
        storage: [
            {
                id : "s3_input",
                bucket : {
                    url : "s3://my-storage-bucket/input/",
                    auth : {
                        key: "my-auth-key",
                        secret: "my-secret-key"
                    }
                }
            },
            {
                id: "s3_output",
                bucket: {
                    url: "s3://my-storage-bucket/output/",
                    auth: {
                        key: "my-auth-key",
                        secret: "my-secret-key"
                    }
                }
            }
        ]
    }
}
axios(config)
    .then(function(response) {
        console.log(response.data.job_id)
    })
    .catch(function(error) {
        console.log(error)
    })
#!/bin/bash

curl -X POST "https://api.dolby.com/media/transcode" \
    --header "x-api-key: $DOLBYIO_API_KEY" \
    --data '{
        "inputs: [{"source": "dlb://in/example.mp4"}],
        "outputs": [
            {
                "id" : "MP4-H.264",
                "destination" : {
                    "id" : "s3",
                    "filename" :  "airplane_transcoded.webm"
                },
                "kind" : "mp4",
                "audio" : {
                    "codec" : "aac_lc",
                    "bitrate_kb": 128
                },
                "video" : {
                    "codec" : "h264",
                    "width" : 1920,
                    "height" : 1080,
                    "frame_rate" : 30,
                    "bitrate_mode" : "vbr",
                    "bitrate_kb" : 24883
                }
            },
            {
                "id" : "thumbnail",
                "destination" : {
                    "id" : "s3",
                    "filename" :  "airplane_thumbnail.jpg"
                },
                "kind" : "jpg",
                "image" : {
                    "codec" : "png",
                    "width" : 128,
                    "height": 128
                }
            }
        ],
        "storage" : [
            {
                "id" : "s3",
                "bucket" : {
                    "url" : "s3://my-storage-bucket/output/",
                    "auth" : {
                        "key": "my-auth-key",
                        "secret": "my-secret-key"
                    }
                }
            }
        ]
    }'

The JSON response will include a unique job_id that you'll need to use to check on the status of media transcoding.

{"job_id":"b49955b4-9b64-4d8b-a4c6-2e3550472a33"}

You can explore the /media/transcode API Reference to learn more about other options to customize the behavior of the media transcoding.

4. Check the Job Status

It will take a few moments for the API to transcode your file. You'll need to check the status of the job. You can learn more about this in the How It Works section of the Introduction.

For this GET /media/transcode request you'll need to use the job id returned from the previous step. In these examples, it is specified as an environment variable that you'll need to set or replace in the code samples.

import os
import requests
from pprint import pprint

job_id = os.environ["DOLBYIO_JOB_ID"]

url = "https://api.dolby.com/media/transcode"
headers = {
    "x-api-key": os.environ["DOLBYIO_API_KEY"],
    "Content-Type": "application/json",
    "Accept": "application/json",
}

params = {
    "job_id": job_id,
}

try:
    response = requests.get(url, params=params, headers=headers)
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    raise Exception(response.text)
pprint(response.json())
const axios = require("axios").default

const config = {
  method: "get",
  url: "https://api.dolby.com/media/transcode",
  headers: {
    "x-api-key": process.env.DOLBYIO_API_KEY,
    "Content-Type": "application/json",
    Accept: "application/json",
  },
  params: {
    job_id: process.env.DOLBYIO_JOB_ID,
  },
}

axios(config)
  .then(function(response) {
    console.log(JSON.stringify(response.data, null, 4))
  })
  .catch(function(error) {
    console.log(error)
  })
#!/bin/bash

curl -X GET "https://api.dolby.com/media/transcode?job_id=$DOLBYIO_JOB_ID" \
    --header "x-api-key: $DOLBYIO_API_KEY"

While the job is still in progress, you will be able to see the status and progress values returned.

{
  "path": "/media/transcode",
  "status": "Running",
  "progress": 42
}

If you re-run and call again after a period of time you'll see the status changes and the output you originally specified will be ready for download.

{
  "path": "/media/transcode",
  "progress": 100,
  "result": {},
  "status": "Success"
}

5. Download and Review Media

Once media transcoding is complete, the file will be PUT in the output location specified when the job was started. For example for the use case in section 3.2 and section 3.3, the transcoded output is already available in the s3 bucket provided. For the use case in section 3.1, you can download the transcoded file (dlb://out/example_transcoded.mp4) using the /media/output API. It takes the url as the only parameter.

import os
import shutil
import requests

output_path = os.environ["OUTPUT_MEDIA_LOCAL_PATH"]

url = "https://api.dolby.com/media/output"
headers = {
    "x-api-key": os.environ["DOLBYIO_API_KEY"],
    "Content-Type": "application/json",
    "Accept": "application/json",
}

args = {
    "url": "dlb://out/example_transcoded.mp4",
}

with requests.get(url, params=args, headers=headers, stream=True) as response:
    response.raise_for_status()
    response.raw.decode_content = True
    print("Downloading from {0} into {1}".format(response.url, output_path))
    with open(output_path, "wb") as output_file:
        shutil.copyfileobj(response.raw, output_file)
const fs = require("fs")
const axios = require("axios").default

const output_path = process.env.OUTPUT_MEDIA_LOCAL_PATH

const config = {
  method: "get",
  url: "https://api.dolby.com/media/output",
  headers: {
    "x-api-key": process.env.DOLBYIO_API_KEY,
    "Content-Type": "application/json",
    "Accept": "application/json",
  },
  responseType: "stream",
  params: {
    url: "dlb://out/airplane_transcoded.mp4",
  },
}

axios(config)
  .then(function(response) {
    response.data.pipe(fs.createWriteStream(output_path))
    response.data.on("error", function(error) {
      console.log(error)
    })
    response.data.on("end", function() {
      console.log("File downloaded!")
    })
  })
  .catch(function(error) {
    console.log(error)
  })
# You specify the `-L` because the service will redirect you to a cloud storage location. 
# You shouldn't try to retrieve directly from the cloud storage as the location may change, 
# so use **/media/output** with the shortcut instead. 
# The `-O` is to just output the file to your local system with the same filename.

curl  -X GET https://api.dolby.com/media/output?url="dlb://out/airplane-transcoded.mp4" \
      -O -L \
      --header "x-api-key: $DOLBYIO_API_KEY"

Recommendations

The /media/transcode API is complex, and this section gives recommendations for different use cases.

1 Single input - single output transcode

  • Use a pre-signed URL for inputs[0].source and outputs[0].destination. For this use case the Transcode API does not need access to storage buckets.
  • Locally stored files are ok too, but you need to use the /media/input API to first upload the file to dolby.io and then use the /media/output API to download the transcoded file. Refer to Section 2 and Section 5 above for more details.

2 Single input - multiple output transcode

  • Use a pre-signed URL or a local file for inputs[0].source as above.
  • Use a pre-signed URL or a dlb:// URL for each outputs.destination. If you use dlb:// locations, you need to use the /media/output API to download the transcoded files. Refer to Section 5 above for more details.

3 Single input - HLS / DASH output

  • Use a pre-signed URL or a local file for inputs[0].source as above.
  • A storage bucket location is required for outputs.destination. The /media/transcode API needs access to the bucket in order to create multiple files required for HLS and DASH.

Limitations

1 Transcoding to HLS and DASH

  • All the bitrate ladders to be included in the HLS and DASH manifest must be explicitly requested as different outputs.
  • /media/transcode requires access to a cloud storage bucket to write HLS and DASH outputs. Pre-signed URLs and dlb:// URLs cannot be used as outputs when HLS or DASH is requested.
  • Only mp4 outputs are supported when one of the requested outputs is HLS or DASH.

Did this page help you?