Media

Transcode Video to YouTube Recommendations

SUMMARY

A getting started guide for how to leverage Dolby.io Media APIs to programmatically transcoded video files to YouTube’s recommended upload encoding settings.


Creativity is just one piece of the puzzle involved in making high quality and engaging YouTube videos. Like most video sharing platforms, YouTube encourages creators to upload high quality videos while also making them as small as possible to provide the best streaming experience for their users. They even provide specific guidelines every creator should follow to ensure their videos are properly configured to be best delivered over the platform.

Videos that don’t follow these guidelines are automatically re-configured by the YouTube algorithm before they are published. However, just because you can upload a misconfigured video doesn’t mean you should. The outcome of the YouTube’s automatic re-configuration might not match your preferences, and you risk having a longer upload time since the algorithm would have to do a lot of work to properly re-configure your video file.

While the technical process of ensuring your videos are in the right format can be very tedious, Dolby.io Media APIs can help you to programmatically reconfigure your videos, and deliver great media at scale. This article aims to provide an in-depth explanation of YouTube’s video transcoding recommendations, and how you can leverage Dolby.io Media APIs to diagnose and correctly format your videos.

Note: To follow along, check out the project in this GitHub repository.

Understanding Your Media Files with Dolby.io

For our scenario, we are going to use the Media Diagnose API to get encoding data about the video file below (the encoding settings for the video does not follow YouTube’s recommendations). Next, we will use the Media Transcode API to convert our video file to an alternate encoding format that meets YouTube’s guidelines.

Link to Video File Used

Before we get started, we need to sign up for a Dolby.io account, create a new application, and grab the Media API key. After signing up for an account, we need to use the Media Input API to upload the media file we want to transcode to Dolby.io server.

Note: Using the Media Input API would only temporarily store your video files for about 24 hours before it is removed. However, you can use your own cloud storage provider for a more persistent solution. You can read more about this here.

import os
import requests
 
# file path to your video file
file_path = os.environ["INPUT_MEDIA_LOCAL_PATH"]
api_key = os.environ["DOLBYIO_API_KEY"]
 
url = "https://api.dolby.com/media/input"
headers = {
    "x-api-key": api_key,
    "Content-Type": "application/json",
    "Accept": "application/json",
}
 
# declare your dlb:// location
# this unique identifier would point to your video file
body = {
    "url": "dlb://in/pre-transcoded-video.mp4",
}
 
response = requests.post(url, json=body, headers=headers)
response.raise_for_status()
data = response.json()
presigned_url = data["url"]
 
# upload your media to the pre-signed url response
print("Uploading {0} to {1}".format(file_path, presigned_url))
with open(file_path, "rb") as input_file:
  requests.put(presigned_url, data=input_file)

Now we have uploaded our video file to Dolby‘s server, we can use the unique identifier from the previous step to make a request to the Diagnose API (/media/diagnose) to figure out the current encoding settings for the video.

import os
import requests
 
# file path to your video file
file_path = os.environ["INPUT_MEDIA_LOCAL_PATH"]
api_key = os.environ["DOLBYIO_API_KEY"]
 
url = "https://api.dolby.com/media/input"
headers = {
    "x-api-key": api_key,
    "Content-Type": "application/json",
    "Accept": "application/json",
}
 
# declare your dlb:// location
# this unique identifier would point to your video file
body = {
    "url": "dlb://in/pre-transcoded-video.mp4",
}
 
response = requests.post(url, json=body, headers=headers)
response.raise_for_status()
data = response.json()
presigned_url = data["url"]
 
# upload your media to the pre-signed url response
print("Uploading {0} to {1}".format(file_path, presigned_url))
with open(file_path, "rb") as input_file:
  requests.put(presigned_url, data=input_file)

The JSON response will include a unique job_id that you’ll need to use to periodically check on the status of media diagnosis job until it is complete. For this example, we are going to check for the status of the processing job every 10 seconds until the job is done. However, you can run your check as frequently as you’d desire or automate this in the future with Webhooks and Callbacks.

import os
import requests
import time
 
url = "https://api.dolby.com/media/diagnose"
headers = {
    "x-api-key": os.environ["DOLBYIO_API_KEY"],
    "Content-Type": "application/json",
    "Accept": "application/json"
}
 
# the job_id returned from the last step
params = {
    "job_id" : os.environ["DOLBYIO_JOB_ID"],
}
 
while True:
    response = requests.get(url, params=params, headers=headers)
        response.raise_for_status()
        job_status = response.json()["status"]
 
    if (job_status and job_status == "Success"):
            # the media_info property contains the encoding settings for the video
      print(response.json()["results"]["media_info"])
      break
    else:
      print(job_status)
            # wait for 10 seconds before making another request
      time.sleep(10)

If you are following along with the example video in this article, the media_info property from the response should return the JSON object below. It contains encoding details about the video and audio container in your media file.

{
   "container":{
      "kind":"mp4",
      "duration":10.542,
      "bitrate":16595963,
      "size":21869330
   },
   "audio":{
      "codec":"aac",
      "channels":1,
      "sample_rate":44100,
      "duration":10.542,
      "bitrate":96000
   },
   "video":{
      "codec":"hevc",
      "frame_rate":60,
      "height":2160,
      "width":3840,
      "duration":10.542,
      "bitrate":16550114
   }
}

Transcoding Media Files with Dolby.io

Now we know the encoding settings for our video, we can compare them to YouTube’s recommendations and make the necessary adjustments by making a request to the Media Transcode API.

The output property in the request payload below will contain a similar JSON object to the media_info for the audio and video encoding settings. It will also specify the destination to store the transcoded media and the container type for the media. We will start off by only specifying the destination and container kind properties, and then take a step-by-step approach to construct the audio and video encoding settings with YouTube’s recommendation. You can find the full request code sample here if you want to skip ahead.

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" : "dlb://in/pre-transcoded-video.mp4" }],
    "outputs": [{
            "destination" : "dlb://out/transcoded-video.mp4",
            "kind" : "mp4",
            "audio" : { },
            "video" : { }
        }]
}
 
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"])

Transcoding Audio

The second object in the media_info attribute contains the audio properties for our video file.

Audio codec makes audio storage and distribution easier by compressing and decompressing audio data. It encodes and compresses audio data before transmission, and decodes the compressed data on arrival. The sample video in this article uses the AAC-LC codec. AAC-LC codec is the best audio codec for live streaming and YouTube highly recommends media files use it. However, the audio channels and bitrate audio properties for the sample video do not follow YouTube’s guidelines.

Audio channels represent the sources through which audio data is transmitted from one to another. Mono audio channels have a single source transmission. However, stereo channels reproduces sound using two channels to imitate natural human hearing. Stereo channels are the industry standard and YouTube also recommends them. They are high quality and have practically replaced single channel audio. As such, we need to change our channel property value from 1 (mono) to 2 (stereo).

"outputs":[
   {
      "destination":"dlb://out/transcoded-video.mp4",
      "kind":"mp4",
      "audio":{
         "channels":2
      },
      "video":{
          
      }
   }
]

YouTube also recommends that audio with stereo channels should have a 384 kbps bitrate. The bitrate of an audio file impacts its quality. Increasing an audio’s bitrate generally increases its quality. However, any bitrate around 320kbps is ideal in most cases. The bitrate returned in the media_info object is approximately 64kbps (converting bytes per second to kilobytes per second). Therefore, we need to change the value to 384 kbps (or 384000 bps).

"outputs":[
   {
      "destination":"dlb://out/transcoded-video.mp4",
      "kind":"mp4",
      "audio":{
         "channels":2,
         "bitrate":384000
      },
      "video":{
          
      }
   }
]

Transcoding Video

Similar to audio codec, video codec handles the encoding and decoding of compressed video data. The codec format for our video is hevc (also referred to as H265). While this format achieves better compression rate than other codec formats, YouTube recommends using H264 because the H265 codec uses a lot of processing power.

"outputs":[
   {
      "destination":"dlb://out/transcoded-video.mp4",
      "kind":"mp4",
      "audio":{
         "channels":2,
         "bitrate":384000
      },
      "video":{
         "codec":"H264"
      }
   }
]

Our video bitrate is the last property that doesn’t follow YouTube guidelines. As previously mentioned, the bitrate affects the quality of media files. A higher video bitrate leads to better video quality. YouTube’s video bitrate recommendation depends on the resolution and frame rate of the video. From the diagnosis data, we can see that our video’s frame rate and resolution is 60 fps and 1920 x 1080 (often referred to as 2160p) accordingly. Given this information, YouTube recommends that our video bitrate should be 68 Mbps for Standard Dynamic Range (SDR) videos or 85 Mbps for High Dynamic Range (HDR) upload.

TypeVideo Bitrate, Standard Frame Rate (24, 25, 30)Video Bitrate, High Frame Rate (48, 50, 60)
2160p (4K)35 – 45 Mbps53 – 68 Mbps
1440p (2K)16 Mbps24 Mbps
1080p8 Mbps12 Mbps
720p5 Mbps7.5 Mbps
480p2.5 Mbps4 Mbps
360p1 Mbps1.5 Mbps
Recommended video bitrate for SDR uploads

"outputs":[
   {
      "destination":"dlb://out/transcoded-video.mp4",
      "kind":"mp4",
      "audio":{
         "channels":2,
         "bitrate":384000
      },
      "video":{
         "codec":"H264",
         "bitrate":68000
      }
   }
]

After adding the encoding settings, the final request to the Transcode API should look like this:

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" : "dlb://in/pre-transcoded-video.mp4" }],
    "outputs": [
            {
                    "destination" : "dlb://out/transcoded-video.mp4",
                    "kind" : "mp4",
                    "audio" : {
                        "channels" : 2,
                        "bitrate": 384000,
                    },
                    "video" : {
                        "codec":"H264",
                  "bitrate":68000
                    }
            }]
}
 
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"])

Sending the request should return the processing job id, and we can programmatically check the status of the job like we did in the Diagnose API example.

import os
import requests
import time
 
url = "https://api.dolby.com/media/transcode"
headers = {
    "x-api-key": os.environ["DOLBYIO_API_KEY"],
    "Content-Type": "application/json",
    "Accept": "application/json"
}
 
# replace with the job_id returned from the request
params = {
    "job_id" : os.environ["DOLBYIO_JOB_ID"],
}
 
while True:
    response = requests.get(url, params=params, headers=headers)
        response.raise_for_status()
        job_status = response.json()["status"]
 
    if (job_status and job_status == "Success"):
            # the media_info property contains the encoding settings for the video
      print(response.json())
      break
    else:
      print(job_status)
            # wait for 10 seconds before making another request
      time.sleep(10)

Once the job has been complete we can download and review the transcoded video file using the Dolby.io destination URL that we set to point to it. (dlb://out/transcoded-video.mp4). We also need to set the output path which is where the transcoded video file would be downloaded to on your local machine or the cloud.

import shutil
import requests
 
# change to download location
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/transcoded-video.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)

Conclusion

This article demonstrates a single use-case of how you can leverage Dolby.io suite of Media APIs to frictionlessly analyze and programmatically transcode your media files to an alternate encoding format recommended suitable for distribution on the YouTube platform. However, there is so much more you can accomplish with our APIs and you should definitely check out our documentation to learn more. You can also view the full code sample for the scenario described in this article here.

Leave a Comment

Emmanuel Ndubuisi

Developer Relations

Get Started

Drive real-time interactions and engagement with sub-second latency

We are more than just a streaming solutions provider; we are a technology partner helping you build a streaming ecosystem that meets your goals. Get started for free and as you grow, we offer aggressive volume discounts protecting your margins.

Developer Resources

Explore learning paths and helpful resources as you begin development with Dolby.io.

Copy link
Powered by Social Snap