Adaptive bitrate streaming packages an audio or video file into multiple streams at different bitrates and resolutions and generates a manifest file that lists these streams. A player uses this manifest to dynamically switch between streams based on network conditions, improving the viewing experience.
HLS and DASH are the most widely used formats for adaptive bitrate streaming. ApsaraVideo VOD currently supports generating adaptive bitrate streams only in HLS format. For more information, see Adaptive bitrate transcoding.
Introduction
ApsaraVideo VOD provides video packaging templates and subtitle packaging templates to generate adaptive bitrate streaming files that let viewers switch between different resolutions and subtitle languages. You can create these templates by using the ApsaraVideo VOD console or by calling API operations.
Compared with traditional single-bitrate playback, adaptive bitrate streaming allows a player to select the most suitable stream based on the viewer's network conditions and device. This significantly improves the viewing experience. The following table describes the differences between a video packaging template and a regular transcoding template.
|
Item |
Video packaging template |
Regular transcoding template |
|
Parameter configuration |
Requires packaging parameters such as packaging type and bandwidth threshold. |
These parameters are not required. |
|
Adding subtitles |
You can add embedded subtitles and sidecar subtitles. |
You can add embedded subtitles only by calling an API operation. |
|
Playback experience |
The player automatically selects a stream for playback based on the network bandwidth. |
Only the specified stream can be played. |
Usage notes
-
Video packaging templates do not support standard encryption. To use standard encryption, you must use a regular transcoding template.
-
The subtitle file and the source video file must be stored in the same region and the same OSS bucket.
-
A subtitle packaging template cannot be created or used alone. It must be used with a video packaging template.
-
Subtitle packaging templates support only the VTT format. When overriding subtitle parameters via an API call, the
Languageparameter is used only to identify the subtitle file to replace; the language value itself is not modified. You cannot replace a subtitle for a language that does not already exist. -
Transcoding is a paid service. For more information, see Pricing.
Configure adaptive bitrate streaming in the console
-
Create a transcoding template group for adaptive bitrate streaming.
NoteIf you only need a video packaging template, you are not required to create a regular one. To avoid unnecessary transcoding fees, you can delete any unneeded regular transcoding templates.
-
Log on to the ApsaraVideo VOD console. In the left-side navigation pane, choose Configuration Management > Media Processing > Transcoding Template Groups.
-
On the Transcoding Template Groups tab, click Create Transcoding Template Group.
-
Specify a name for the template group.
-
In the Audio and Video Packaging Template section, click Add Template and configure the video packaging template.
-
In the Basic Information section, Encapsulation Format is fixed to HLS. The parameters in the Video Packaging Parameters section are described as follows:
-
Packaging Type: This parameter is fixed to HLS packaging.
-
Bandwidth Threshold: Specifies the bandwidth that the player uses to determine which stream to play based on the current network conditions. Unit: bps. We recommend that you use the recommended settings.
-
-
The Basic Information, Video Parameters, Audio Parameters, and Advanced Parameters sections are configured the same way as a regular transcoding template. For more information, see Transcoding templates.
-
If needed, click Add Template to create multiple video packaging templates with different bitrates, resolutions, and definitions.
-
-
After you create the video packaging template, click Save.
-
-
Initiate adaptive bitrate transcoding.
-
In the ApsaraVideo VOD console, choose Media Files > Audio/Video.
-
On the Audio/Video page, find the video you want to process and click Processing in the Actions column.
-
Set Use Transcoding Template Group to Use Transcoding Template Group. Select the transcoding template group that you created in the previous step and click OK to start the media processing job.
-
-
View the result.
-
View the packaged streams (two transcoded streams and one adaptive stream)
In the ApsaraVideo VOD console, choose Media Files > Audio/Video. Find the processed video, click Manage, and then click the Video URL tab.
The Video URL tab displays four entries: Original File (MP4, 1920×1080, 293.17 MB), HD (M3U8, private encryption, 1280×720, 48.24 MB), Fluent (M3U8, 640×360, 14.55 MB), and Adaptive (M3U8).
-
View the playback result (play the adaptive stream)
On the Basic Configuration tab of ApsaraVideo Player, enter the adaptive stream URL from the Video URL tab, and then click the Preview tab to view the playback.
On the right side of the video player, expand the Subtitles panel. After you select the test subtitle track, the corresponding English subtitles appear at the bottom of the video screen.
-
Procedure
-
Create a transcoding template group for adaptive bitrate streaming.
The sample code shows how to configure a regular transcoding template, a video packaging template, and a subtitle packaging template. Use the configurations that are relevant to your scenario.
NoteIf you only need a video packaging template, you are not required to create a regular one. To avoid unnecessary transcoding fees, you can delete any unneeded regular transcoding templates.
/** * The following code provides an example on how to call the API operation. */ public static void main(String[] args) throws ClientException { // The AccessKey pair of an Alibaba Cloud account has permissions to call all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. // We strongly recommend that you do not store the AccessKey ID and AccessKey secret in your project code. Otherwise, the AccessKey pair may be leaked, which threatens the security of all your resources. // This example shows how to use environment variables to obtain the AccessKey pair for identity verification. Before you run the sample code, configure the ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables. DefaultAcsClient client = initVodClient(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")); AddTranscodeTemplateGroupResponse response = new AddTranscodeTemplateGroupResponse(); try { response = addTranscodeTemplateGroup(client); System.out.println("TranscodeTemplateGroupId = " + response.getTranscodeTemplateGroupId()); } catch (Exception e) { System.out.println("ErrorMessage = " + e.getLocalizedMessage()); } System.out.println("RequestId = " + response.getRequestId()); } /** * Add a transcoding template group. */ public static AddTranscodeTemplateGroupResponse addTranscodeTemplateGroup(DefaultAcsClient client) throws Exception { AddTranscodeTemplateGroupRequest request = new AddTranscodeTemplateGroupRequest(); request.setName("grouptest2"); JSONArray transcodeTemplateList = new JSONArray(); // Configure a regular transcoding template. transcodeTemplateList.add(buildNormalTranscodeConfig()); // Configure a video packaging template. transcodeTemplateList.add(buildVideoPackageConfig()); // Configure a subtitle packaging template. transcodeTemplateList.add(buildSubtitlePackageConfig()); request.setTranscodeTemplateList(transcodeTemplateList.toJSONString()); System.out.println("request = " + JSONObject.toJSONString(request)); return client.getAcsResponse(request); } /** * Build the configuration data for the transcoding template to be added. * * @return */ public static JSONObject buildNormalTranscodeConfig() { JSONObject transcodeTemplate = new JSONObject(); // The type of the template. Valid values: Normal (regular transcoding template), VideoPackage (video packaging template), and SubtitlePackage (subtitle packaging template). transcodeTemplate.put("Type","Normal"); // The name of the template. transcodeTemplate.put("TemplateName", "regular_transcoding_template_mp4"); // The definition. transcodeTemplate.put("Definition", "HD"); // The video stream transcoding configuration. JSONObject video = new JSONObject(); video.put("Width", 1280); //video.put("Height", 720); video.put("Bitrate", 1500); video.put("Fps", 25); //video.put("Remove", false); video.put("Codec", "H.264"); video.put("Gop", "250"); video.put("LongShortMode", false); transcodeTemplate.put("Video", video); // The audio stream transcoding configuration. JSONObject audio = new JSONObject(); audio.put("Codec", "AAC"); audio.put("Bitrate", "64"); audio.put("Channels", "2"); audio.put("Samplerate", "32000"); transcodeTemplate.put("Audio", audio); // The container format. JSONObject container = new JSONObject(); container.put("Format", "mp4"); transcodeTemplate.put("Container", container); // The subtitle replacement settings. JSONObject subtitleSetting = new JSONObject(); JSONArray subtitleList = new JSONArray(); JSONObject subtitle = new JSONObject(); // The OSS URL of the subtitle file. HTTPS URLs are not supported. subtitle.put("SubtitleUrl", "http://outin-8db8d2****3e1c9256.oss-cn-shanghai.aliyuncs.com/subtitle/3215879C9F724A43BC84C63BE2AA19AF****.srt"); // The character encoding of the subtitle content. Valid values: auto (automatic detection), UTF-8, GBK, and BIG5. subtitle.put("CharEncode", "UTF-8"); subtitleList.add(subtitle); transcodeTemplate.put("SubtitleList", subtitleList); return transcodeTemplate; } /** * The video packaging configuration. * * @return */ private static JSONObject buildVideoPackageConfig() { JSONObject transcodeTemplate = new JSONObject(); // The type of the template. Valid values: Normal (regular transcoding template), VideoPackage (video packaging template), and SubtitlePackage (subtitle packaging template). transcodeTemplate.put("Type","VideoPackage"); // The name of the template. transcodeTemplate.put("TemplateName", "HLS_LD_packaging"); // The definition. transcodeTemplate.put("Definition", "LD"); // The video stream transcoding configuration. JSONObject video = new JSONObject(); video.put("Width", 1280); //video.put("Height", 720); video.put("Bitrate", 1500); video.put("Fps", 25); //video.put("Remove", false); video.put("Codec", "H.264"); video.put("Gop", "250"); video.put("LongShortMode", false); transcodeTemplate.put("Video", video); // The audio stream transcoding configuration. JSONObject audio = new JSONObject(); audio.put("Codec", "AAC"); audio.put("Bitrate", "64"); audio.put("Channels", "2"); audio.put("Samplerate", "32000"); transcodeTemplate.put("Audio", audio); // The container format. JSONObject container = new JSONObject(); container.put("Format", "m3u8"); transcodeTemplate.put("Container", container); // If the container format is set to M3U8, you must configure MuxConfig. JSONObject muxConfig = new JSONObject(); JSONObject segment = new JSONObject(); segment.put("Duration", "10");// Unit: seconds. muxConfig.put("Segment", segment); transcodeTemplate.put("MuxConfig",muxConfig); // The packaging configuration. JSONObject packageSetting = new JSONObject(); // The packaging type. Set the value to HLSPackage for HLS adaptive bitrate packaging. packageSetting.put("PackageType","HLSPackage"); JSONObject packageConfig = new JSONObject(); packageConfig.put("BandWidth","500000"); packageSetting.put("PackageConfig",packageConfig); transcodeTemplate.put("PackageSetting",packageSetting); return transcodeTemplate; } /** * The subtitle packaging configuration. * * @return */ private static JSONObject buildSubtitlePackageConfig() { JSONObject transcodeTemplate = new JSONObject(); // The type of the template. Valid values: Normal (regular transcoding template), VideoPackage (video packaging template), and SubtitlePackage (subtitle packaging template). transcodeTemplate.put("Type","SubtitlePackage"); // The name of the template. transcodeTemplate.put("TemplateName", "multi_subtitle_packaging"); // The definition. transcodeTemplate.put("Definition", "HD"); // The video stream transcoding configuration. JSONObject video = new JSONObject(); video.put("Width", 1280); //video.put("Height", 720); video.put("Bitrate", 1500); video.put("Fps", 25); //video.put("Remove", false); video.put("Codec", "H.264"); video.put("Gop", "250"); video.put("LongShortMode", false); transcodeTemplate.put("Video", video); // The audio stream transcoding configuration. JSONObject audio = new JSONObject(); audio.put("Codec", "AAC"); audio.put("Bitrate", "64"); audio.put("Channels", "2"); audio.put("Samplerate", "32000"); transcodeTemplate.put("Audio", audio); // The container format. JSONObject container = new JSONObject(); container.put("Format", "m3u8"); transcodeTemplate.put("Container", container); // If the container format is set to M3U8, you must configure MuxConfig. JSONObject muxConfig = new JSONObject(); JSONObject segment = new JSONObject(); segment.put("Duration", "10");// Unit: seconds. muxConfig.put("Segment", segment); transcodeTemplate.put("MuxConfig",muxConfig); /* The OSS URL of the subtitle file. HTTPS URLs and CDN-accelerated domain names are not supported. Note: The subtitle file must be in the same region and OSS bucket as the source video file, for example, cn-shanghai. */ // The subtitle packaging template. JSONObject subtitlePackageConfig = new JSONObject(); subtitlePackageConfig.put("Type","SubtitlePackage"); // The subtitle packaging settings. JSONObject subtitlePackageSetting = new JSONObject(); // The packaging type. Set the value to HLSPackage for HLS adaptive bitrate packaging. subtitlePackageSetting.put("PackageType","HLSPackage"); JSONArray subtitleExtractConfigs = new JSONArray(); // Subtitle 1 JSONObject subtitleExtractConfig = new JSONObject(); JSONArray subtitleUrlList = new JSONArray(); subtitleUrlList.add("http://outin-bfefbb9****e1c7426.oss-cn-shanghai.aliyuncs.com/subtitle/260447BA31D24F9E9E7752BF73F1319B****.vtt"); subtitleExtractConfig.put("SubtitleUrlList",subtitleUrlList); subtitleExtractConfig.put("Language","cn"); subtitleExtractConfig.put("Format","vtt"); subtitleExtractConfig.put("Name","Chinese-test"); // Subtitle 2 JSONObject subtitleExtractConfig2 = new JSONObject(); JSONArray subtitleUrlList2 = new JSONArray(); subtitleUrlList2.add("http://outin-bfefbb9****3e1c7426.oss-cn-shanghai.aliyuncs.com/subtitle/661C67325E0543F0BB8CA7AAB756E6D8****.vtt"); subtitleExtractConfig2.put("SubtitleUrlList",subtitleUrlList2); subtitleExtractConfig2.put("Language","en-US"); subtitleExtractConfig2.put("Format","vtt"); subtitleExtractConfig2.put("Name","English-test"); subtitleExtractConfigs.add(subtitleExtractConfig); subtitleExtractConfigs.add(subtitleExtractConfig2); subtitlePackageSetting.put("SubtitleExtractConfigList",subtitleExtractConfigs); transcodeTemplate.put("PackageSetting",subtitlePackageSetting); return transcodeTemplate; } public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException { // The region where ApsaraVideo VOD is activated. String regionId = "cn-shanghai"; DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); DefaultAcsClient client = new DefaultAcsClient(profile); return client; } -
Initiate adaptive bitrate transcoding.
public static void main(String[] args) { // Set regionId based on the access point of your service. For example, if you access the service from Shanghai, set the value to cn-shanghai. String regionId = "cn-shanghai"; // The AccessKey pair of an Alibaba Cloud account has permissions to call all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. // We strongly recommend that you do not store the AccessKey ID and AccessKey secret in your project code. Otherwise, the AccessKey pair may be leaked, which threatens the security of all your resources. // This example shows how to use environment variables to obtain the AccessKey pair for identity verification. Before you run the sample code, configure the ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables. DefaultProfile profile = DefaultProfile.getProfile(regionId, System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")); IAcsClient client = new DefaultAcsClient(profile); String videoId = "76913816d****8e57e8c2952"; String templateId = "4733b3a5****ae36ac22d34"; try { SubmitTranscodeJobsResponse response = submitTranscodeJobs(client,videoId,templateId); } catch (ServerException e) { e.printStackTrace(); } catch (ClientException e) { System.out.println("ErrCode:" + e.getErrCode()); System.out.println("ErrMsg:" + e.getErrMsg()); System.out.println("RequestId:" + e.getRequestId()); } } /** * Submits a transcoding job. * The video ID and template group ID are passed. * * @param client * @param videoId * @param templateGroupId * @return * @throws Exception */ public static SubmitTranscodeJobsResponse submitTranscodeJobs(DefaultAcsClient client, String videoId, String templateGroupId) throws Exception { SubmitTranscodeJobsRequest request = new SubmitTranscodeJobsRequest(); // The ID of the video to be transcoded. request.setVideoId(videoId); // The ID of the transcoding template group. request.setTemplateGroupId(templateGroupId); // The priority of the transcoding job. Default value: 6. A larger value indicates a higher priority. Valid values: 1 to 10. request.setPriority("8"); JSONObject overrideParams = buildOverrideParams(); // The override parameters. request.setOverrideParams(overrideParams.toJSONString()); return client.getAcsResponse(request); } // The following code provides an example on how to build override parameters for subtitle replacement. public static JSONObject buildOverrideParams() { JSONObject overrideParams = new JSONObject(); // The override settings for packaged subtitles. JSONObject packageSubtitleSetting = new JSONObject(); JSONArray packageSubtitleList = new JSONArray(); JSONObject packageSubtitle = new JSONObject(); // The ID of the subtitle template to be overridden in the transcoding template group. packageSubtitle.put("SubtitlePackageTemplateId", "69fa6ee58****e8492c76168****"); // The Language parameter is used only to locate the subtitle file that you want to replace. The language value itself is not replaced. The replacement fails if the specified language does not exist. packageSubtitle.put("Language", "cn"); // The OSS URL of the subtitle file. HTTPS URLs are not supported. The subtitle file must be in the same region as the video. packageSubtitle.put("SubtitleUrl", "http://outin-bfefbb9****3e1c7426.oss-cn-shanghai.aliyuncs.com/subtitle/043956117D0C475EAB0CE8C4F7294221****.vtt"); packageSubtitleList.add(packageSubtitle); packageSubtitleSetting.put("PackageSubtitleList", packageSubtitleList); overrideParams.put("PackageSubtitleSetting", packageSubtitleSetting); return overrideParams; } -
View the result.
-
View the packaged streams (two transcoded streams and one adaptive stream)
In the ApsaraVideo VOD console, choose Media Files > Audio/Video. Find the processed video, click Manage, and then click the Video URL tab.
The Video URL tab displays four entries: Original File (MP4, 1920×1080, 293.17 MB), HD (M3U8, private encryption, 1280×720, 48.24 MB), Fluent (M3U8, 640×360, 14.55 MB), and Adaptive (M3U8).
-
View the playback result (play the adaptive stream)
On the Basic Configuration tab of ApsaraVideo Player, enter the adaptive stream URL from the Video URL tab, and then click the Preview tab to view the playback.
On the right side of the video player, expand the Subtitles panel. After you select the test subtitle track, the corresponding English subtitles appear at the bottom of the video screen.
-