Dolby
  • Up and Running
  • Amazon Web Services
  • Sources
  • Hybrik JSON
  • Video Filters
  • Audio Filters
  • Working with Audio
  • Task Modifiers
  • Package Task
  • HLS and DASH Packaging
  • Advanced HLS Packaging
  • DRM
  • Analysis & Quality Control
  • Dolby Technologies
  • Additional Tasks
  • Hybrik Versions
  • QC Player
  • Machine Performance Analysis

    Advanced HLS Packaging Tutorial

    Hybrik supports bundling additional audio and captioning tracks within an HLS package. This is useful for supporting multiple language tracks, surround sound tracks, descriptive audio tracks, closed captions, and multiple language subtitles.

    In this tutorial, we’ll build on the example job from the HLS and DASH Packaging Tutorial by adding an additional Italian-language audio track, as well closed as an English closed captioning track from an SCC file. This tutorial draws on the audio mapping features described in the Audio Mapping and Alternate Audio tutorial , as well as Asset Complex from the Stitching Tutorial.

    You can follow along with our example jobs: Advanced HLS examples.

    Adding Alternate Audio Tracks Using Asset Complex

    The HLS standard allows you to supply multiple audio tracks in the manifest, providing alternate language audio, descriptive audio for the visually impaired, or surround sound formats. In this example, we will use an asset_complex to combine elements from two files - the main video file and a secondary file with an alternate audio track. We’ll use audio channel mapping to select the audio channels from each source file and assign them to output tracks, formatting them for the transcode Task. Then we’ll add outputs to the transcode Task to encode high and low bitrate renditions of the additional audio track, and we’ll group the language tracks together so that they’re listed correctly in the HLS manifest.

    The first source in the asset_components array contains the video track and primary English audio track. We’ve added a contents array to select the video track and audio track, mapping the first audio track of the source file to the first audio track of the output that will be sent to the transcode Task. Track numbers are zero-indexed.

    {
      "component_uid": "audio_video",
      "kind": "name",
      "name": "{{source_name}}",
      "location": {
        "storage_provider": "s3",
        "path": "{{source_path}}"
      },
      "contents": [
        {
          "kind": "video"
        },
        {
          "kind": "audio",
          "map": [
            {
              "input": {
                "track": 0
              },
              "output": {
                "track": 0
              }
            }
          ]
        }
      ]
    },
    

    The next source contains the alternate audio track - in our example, an Italian language track. The first audio track from this file is mapped to the second audio track of the output to the transcode Task.

    { 
      "component_uid": "audio_it",
      "kind": "name",
      "name": "{{audio_it_name}}",
      "location": {
        "storage_provider": "s3",
        "path": "{{audio_it_path}}"
      },
      "contents": [
        {
          "kind": "audio",
          "map": [
            {
              "input": {
                "track": 0
              },
              "output": {
                "track": 1
              }
            }
          ]
        }
      ]
    }, 
    

    Transcoding and Packaging Alternate Audio Tracks

    In the Transcode Task, we’ve modified the primary audio renditions, setting the language to english and selecting the first audio track from the asset_complex as the source, since we now have multiple audio tracks. We’ve also added the en language tag to the filename for easier file management.

    {
      "file_pattern": "{source_basename}_audio_en_64kbps{default_extension}",
      "existing_files": "replace",
      "container": {
        "kind": "fmp4",
        "segment_duration": 6
      },
      "audio": [
        {
          "channels": 2,
          "codec": "aac_lc",
          "sample_rate": 48000,
          "bitrate_kb": 64,
          "layer_id": "audio_low",
          "language": "english",
          "source": [
            {
              "track": 0
            }
          ]
        }
      ]
    },
    {
      "file_pattern": "{source_basename}_audio_en_128kbps{default_extension}",
      "existing_files": "replace",
      "container": {
        "kind": "fmp4",
        "segment_duration": 6
      },
      "audio": [
        {
          "channels": 2,
          "codec": "aac_lc",
          "sample_rate": 48000,
          "bitrate_kb": 128,
          "layer_id": "audio_high",
          "language": "english",
          "source": [
            {
              "track": 0
            }
          ]
        }
      ]
    }
    

    We’ve also added two new outputs for the low and high bitrate renditions of the Italian language track. The language is set to italian, and we’ve selected the second audio track from the asset_complex as the source. We’ve also added the it language tag to the filename.

    {
      "file_pattern": "{source_basename}_audio_it_64kbps{default_extension}",
      "existing_files": "replace",
      "container": {
        "kind": "fmp4",
        "segment_duration": 6
      },
      "audio": [
        {
          "channels": 2,
          "codec": "aac_lc",
          "sample_rate": 48000,
          "bitrate_kb": 64,
          "layer_id": "audio_low",
          "language": "italian",
          "source": [
            {
              "track": 1
            }
          ]
        }
      ]
    },
    {
      "file_pattern": "{source_basename}_audio_it_128kbps{default_extension}",
      "existing_files": "replace",
      "container": {
        "kind": "fmp4",
        "segment_duration": 6
      },
      "audio": [
        {
          "channels": 2,
          "codec": "aac_lc",
          "sample_rate": 48000,
          "bitrate_kb": 128,
          "layer_id": "audio_high",
          "language": "italian",
          "source": [
            {
              "track": 1
            }
          ]
        }
      ]
    }
    

    Crucially, we’ve set the layer_id of each Italian audio encode to match the layer_id of its English-language counterpart; this ensures the Italian and English outputs will be grouped together for each rendition during the package Task, enabling the player to switch between the two tracks. The video renditions whose layer_affinities include audio_high will be assigned any audio tracks with a layer_id that is also set to audio_high - in this case, the English and Italian 128kbps audio renditions.

    Adding Closed Captions using Asset Complex

    We’re going to add a closed captioning track to our HLS package by specifying an SCC caption file as a component in the asset_complex. The caption data from the SCC file will be embedded in the transcoded video files as a CEA-608/708 text track, and we’ll tag that track in the package Task to ensure it’s listed in the manifest.

    First, we’ll add the closed caption file to the asset_complex:

    {
      "kind": "name",
      "component_uid": "captions",
      "name": "",
      "location": {
        "storage_provider": "s3",
        "path": ""
      },
      "contents": [
        {
          "kind": "closed_caption",
          "payload": {
            "format": "scc"
          }
        }
      ]
    }
    

    Next, we’ll explicitly specify in the transcode targets that we are enabling CEA-608 captions. This will encode the captions into our video files. In the case of h.264 here, the captions will be encoded as SCTE 128 SEI data.

    ...
        "video": {
            "codec": "h264",
            "bitrate_mode": "cbr",
            "use_scene_detection": false,
            "bitrate_kb": 400,
            "vbv_buffer_size_kb": 400,
            "profile": "main",
            "level": "3.0",
            "height": 360,
            "par": "1:1",
            "layer_affinities": [
                "audio_low"
            ],
            "closed_captions": {
                "enable_cea608": true
            }
        }
    },
    

    In the package Task, the closed captions will be auto-detected and added to the manifest

    Adding Subtitles

    If you want to instead add subtitles (eg, an SRT or a VTT), you can specify that in the source similar to how we added the scc file:

    { 
        "component_uid": "subs",
        "kind": "name",
        "name": "{{subtitle_name}}",
        "location": {
            "storage_provider": "s3",
            "path": "{{subtitle_path}}"
        },
        "contents": [
            {
                "kind": "subtitle",
                "payload": {
                    "format": "webvtt",
                    "language": "eng"
                }
            }
        ]
    }
    

    Then, we add a an additional vtt target in our transcode task:

    {
        "file_pattern": "{source_basename}_subs.vtt",
        "existing_files": "replace",
        "container": {
            "kind": "webvtt"
        },
        "subtitle": [
            {
                "kind": "webvtt"
            }
        ]
    }
    

    For multiple subtitle languages, we repeat the process.

    Examples

    • Advanced HLS example with CCs and Alternate Language Audio
    • Advanced HLS example with subtitles and Alternate Language