多碼率自適應即指將指定的音視頻檔案流統一打包產生一個自適應碼流檔案,該自適應碼流檔案包含不同音視頻檔案流的碼率、解析度等資訊,播放器則根據網路頻寬環境自動選擇最適合當前頻寬環境的碼流播放。
目前使用比較廣的多碼率自適應輸出格式為HLS和DASH,ApsaraVideo for VOD目前僅支援HLS多碼率自適應產生。更多資訊,請參見多碼率自適應轉碼。
簡介
ApsaraVideo for VOD服務目前可使用視訊打包模板和字幕打包模板,用於產生可切換不同解析度和不同語言字幕的多碼率自適應檔案。支援通過控制台和API的方式建立多碼率自適應模板。
相比較傳統的單碼率播放,自適應碼率檔案能夠讓播放器可根據終端網路頻寬環境,選擇最適合當前頻寬環境和終端裝置的碼流播放,從而提升播放體驗。視頻打包模板和普通轉碼模板的區別,如下表所示:
區別項 | 視頻打包模板 | 普通轉碼模板 |
參數配置 | 需要配置打包參數(打包類型、寬頻閾值)。 | 無此參數配置。 |
字幕添加 | 可設定壓制字幕及外掛字幕。 | 只能通過API的方式設定壓制字幕。 |
播放效果 | 可根據客戶當前寬頻環境自動選擇碼率進行播放。 | 只能播放指定的碼流。 |
注意事項
視頻打包模板不支援使用標準加密,如果要使用標準加密,請使用普通轉碼模板。
字幕檔案必須和視頻源檔案儲存體在同一個地區,同一個OSS Bucket中。
字幕打包模板不能單獨建立使用,必須與視頻打包模板一同使用。
字幕打包模板中,字幕檔案僅只支援VTT格式。通過API方式配置時需注意,字幕參數覆蓋時,Language參數僅用於檢索需要替換的字幕檔案,而Language本身不會被替換,不存在的字幕語言不能替換。
轉碼服務均為收費項,具體請參見收費標準。
控制台方式配置
建立多碼率自適應的轉碼模板組。
說明如果只需要使用多碼率打包模板,則不需要建立普通轉碼模板,或刪除所有普通轉碼模板,以免產生多餘的轉碼費用。
登入视频点播控制台,在點播控制台左側的導覽列選擇。
在轉碼模板組頁簽,單擊添加轉碼模板組,進入添加轉碼模板頁面。
設定模板組名稱。
在音視頻打包模板下方,單擊添加模板,配置視頻打包模板參數。
其中基礎參數的封裝格式固定為hls,音視頻打包參數的配置說明如下:
打包類型:固定為HLS打包。
頻寬閾值:提供給播放器根據當前網路頻寬環境判斷需要選擇播放的碼流,單位:bps。建議使用推薦設定。
基礎參數、視頻參數、音頻參數、進階參數、條件轉碼參數的配置與普通轉碼模板的配置類似,請參見轉碼模板。
根據實際需求,通過添加模板,來建立多個不同碼率、解析度、清晰度的視頻打包模板。
音視頻打包模板建立完成後,單擊儲存。
發起多碼率轉碼。
在ApsaraVideo for VOD控制台,選擇。
在音/視頻頁面,單擊目標視頻的ApsaraVideo for Media Processing。
處理類型選擇用轉碼模板組處理,轉碼模板組選擇第一步所建立的轉碼模板組,單擊確定,發起ApsaraVideo for Media Processing。

效果展示。
多碼率打包後碼流展示:(2路轉碼流,1路自適應流)
在點播控制台,選擇,單擊目標視頻(上一步經過ApsaraVideo for Media Processing的視頻)的管理,選擇視頻地址頁簽。

播放效果展示:(使用上圖中自適應的地址播放)
在Aliplayer播放器的基礎配置頁,輸入播放地址(使用上圖中視頻地址頁中自適應的地址),在播放預覽頁查看播放效果。
操作步驟
建立用於多碼率自適應的轉碼模板組。
本範例程式碼中列舉了普通轉碼模板配置、多碼率打包模板配置、字幕打包模板配置,可根據實際情況使用。
說明如果只需要使用多碼率打包模板,則不需要建立普通轉碼模板,或刪除所有普通轉碼模板,以免產生多餘的轉碼費用。
/** * 以下為調用樣本 */ public static void main(String[] args) throws ClientException { // 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。 // 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。 // 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。運行程式碼範例前,請配置環境變數ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。 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()); } /** * 添加轉碼模板組配置 */ public static AddTranscodeTemplateGroupResponse addTranscodeTemplateGroup(DefaultAcsClient client) throws Exception { AddTranscodeTemplateGroupRequest request = new AddTranscodeTemplateGroupRequest(); request.setName("grouptest2"); JSONArray transcodeTemplateList = new JSONArray(); //普通轉碼模板配置 transcodeTemplateList.add(buildNormalTranscodeConfig()); //多碼率打包轉碼模板配置 transcodeTemplateList.add(buildVideoPackageConfig()); //字幕打包配置 transcodeTemplateList.add(buildSubtitlePackageConfig()); request.setTranscodeTemplateList(transcodeTemplateList.toJSONString()); System.out.println("request = " + JSONObject.toJSONString(request)); return client.getAcsResponse(request); } /** * 構建需要添加的轉碼模板配置資料 * * @return */ public static JSONObject buildNormalTranscodeConfig() { JSONObject transcodeTemplate = new JSONObject(); //模板類型< Normal: 普通轉碼模板;VideoPackage:視頻流打包模板;SubtitlePackage:字幕打包模板> transcodeTemplate.put("Type","Normal"); //模板名稱 transcodeTemplate.put("TemplateName", "普通轉碼模板mp4"); //清晰度 transcodeTemplate.put("Definition", "HD"); //視頻流轉碼配置 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); //音頻流轉碼配置 JSONObject audio = new JSONObject(); audio.put("Codec", "AAC"); audio.put("Bitrate", "64"); audio.put("Channels", "2"); audio.put("Samplerate", "32000"); transcodeTemplate.put("Audio", audio); //封裝容器 JSONObject container = new JSONObject(); container.put("Format", "mp4"); transcodeTemplate.put("Container", container); //字幕替換設定 JSONObject subtitleSetting = new JSONObject(); JSONArray subtitleList = new JSONArray(); JSONObject subtitle = new JSONObject(); //字幕檔案的OSS地址(不支援https地址) subtitle.put("SubtitleUrl", "http://outin-8db8d2****3e1c9256.oss-cn-shanghai.aliyuncs.com/subtitle/3215879C9F724A43BC84C63BE2AA19AF****.srt"); //字幕內容的編碼格式,取值:auto(自動檢測)、UTF-8、GBK、BIG5 subtitle.put("CharEncode", "UTF-8"); subtitleList.add(subtitle); transcodeTemplate.put("SubtitleList", subtitleList); return transcodeTemplate; } /** * 視頻打包配置 * * @return */ private static JSONObject buildVideoPackageConfig() { JSONObject transcodeTemplate = new JSONObject(); //模板類型< Normal: 普通轉碼模板;VideoPackage:視頻流打包模板;SubtitlePackage:字幕打包模板> transcodeTemplate.put("Type","VideoPackage"); //模板名稱 transcodeTemplate.put("TemplateName", "HLS流暢打包"); //清晰度 transcodeTemplate.put("Definition", "LD"); //視頻流轉碼配置 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); //音頻流轉碼配置 JSONObject audio = new JSONObject(); audio.put("Codec", "AAC"); audio.put("Bitrate", "64"); audio.put("Channels", "2"); audio.put("Samplerate", "32000"); transcodeTemplate.put("Audio", audio); //封裝容器 JSONObject container = new JSONObject(); container.put("Format", "m3u8"); transcodeTemplate.put("Container", container); //封裝容器設定為m3u8,必須設定MuxConfig JSONObject muxConfig = new JSONObject(); JSONObject segment = new JSONObject(); segment.put("Duration", "10");//單位是秒 muxConfig.put("Segment", segment); transcodeTemplate.put("MuxConfig",muxConfig); //打包配置 JSONObject packageSetting = new JSONObject(); //打包類型:取值:HLSPackage (HLS自適應碼率打包) packageSetting.put("PackageType","HLSPackage"); JSONObject packageConfig = new JSONObject(); packageConfig.put("BandWidth","500000"); packageSetting.put("PackageConfig",packageConfig); transcodeTemplate.put("PackageSetting",packageSetting); return transcodeTemplate; } /** * 字幕打包配置 * * @return */ private static JSONObject buildSubtitlePackageConfig() { JSONObject transcodeTemplate = new JSONObject(); //模板類型< Normal: 普通轉碼模板;VideoPackage:視頻流打包模板;SubtitlePackage:字幕打包模板> transcodeTemplate.put("Type","SubtitlePackage"); //模板名稱 transcodeTemplate.put("TemplateName", "多字幕打包"); //清晰度 transcodeTemplate.put("Definition", "HD"); //視頻流轉碼配置 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); //音頻流轉碼配置 JSONObject audio = new JSONObject(); audio.put("Codec", "AAC"); audio.put("Bitrate", "64"); audio.put("Channels", "2"); audio.put("Samplerate", "32000"); transcodeTemplate.put("Audio", audio); //封裝容器 JSONObject container = new JSONObject(); container.put("Format", "m3u8"); transcodeTemplate.put("Container", container); //封裝容器設定為m3u8,必須設定MuxConfig JSONObject muxConfig = new JSONObject(); JSONObject segment = new JSONObject(); segment.put("Duration", "10");//單位是秒 muxConfig.put("Segment", segment); transcodeTemplate.put("MuxConfig",muxConfig); /* 字幕檔案OSS地址(不支援https地址、不支援純CDN網域名稱加速地址) 說明:字幕檔案必須和視頻源檔案在同一個地區(例如:cn-shanghai),並且在同一個Bucket當中 */ //字幕打包模板 JSONObject subtitlePackageConfig = new JSONObject(); subtitlePackageConfig.put("Type","SubtitlePackage"); //字幕打包配置 JSONObject subtitlePackageSetting = new JSONObject(); //打包類型:取值:HLSPackage (HLS自適應碼率打包) subtitlePackageSetting.put("PackageType","HLSPackage"); JSONArray subtitleExtractConfigs = new JSONArray(); //字幕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","中文-test"); //字幕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","英文-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 { // 點播服務接入地區 String regionId = "cn-shanghai"; DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret); DefaultAcsClient client = new DefaultAcsClient(profile); return client; }發起多碼率轉碼。
public static void main(String[] args) { //regionId根據服務接入地址填寫,例:接入服務在上海,則填cn-shanghai String regionId = "cn-shanghai"; // 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。 // 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。 // 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。運行程式碼範例前,請配置環境變數ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。 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()); } } /** * 提起轉碼作業 * 傳入的視訊ID和模板組ID * * @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(); //需要轉碼的視頻ID request.setVideoId(videoId); //轉碼模板組ID request.setTemplateGroupId(templateGroupId); //設定轉碼優先順序(預設層級為6,數字越大,層級越高),範圍是[1-10] request.setPriority("8"); JSONObject overrideParams = buildOverrideParams(); //覆蓋參數 request.setOverrideParams(overrideParams.toJSONString()); return client.getAcsResponse(request); } //以下為打包字幕替換參數構建樣本 public static JSONObject buildOverrideParams() { JSONObject overrideParams = new JSONObject(); //打包字幕替換設定 JSONObject packageSubtitleSetting = new JSONObject(); JSONArray packageSubtitleList = new JSONArray(); JSONObject packageSubtitle = new JSONObject(); //需要替換的打包模板組中字幕模板的ID packageSubtitle.put("SubtitlePackageTemplateId", "69fa6ee58****e8492c76168****"); //Language參數僅用於檢索需要替換的字幕檔案,而Language本身不會被替換,不存在的字幕語言不能替換。 packageSubtitle.put("Language", "cn"); //字幕檔案的OSS地址(不支援https地址),字幕檔案需要與視頻在同一個儲存地區。 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; }效果展示。
多碼率打包後碼流展示:(2路轉碼流,1路自適應流)
在點播控制台,選擇,單擊目標視頻(上一步經過ApsaraVideo for Media Processing的視頻)的管理,選擇視頻地址頁簽。

播放效果展示:(使用上圖中自適應的地址播放)
在Aliplayer播放器的基礎配置頁,輸入播放地址(使用上圖中視頻地址頁中自適應的地址),在播放預覽頁查看播放效果。