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