多码率自适应即指将指定的音视频文件流统一打包生成一个自适应码流文件,该自适应码流文件包含不同音视频文件流的码率、分辨率等信息,播放器则根据网络带宽环境自动选择最适合当前带宽环境的码流播放。

说明 说明 目前使用比较广的多码率自适应输出格式为HLS和DASH,视频点播目前仅支持HLS多码率自适应生成。更多信息,请参见多码率开发指南

多码率打包模板和普通转码模板的区别,如下表所示。

区别项 多码率打包模板 普通转码模板
配置 需要配置打包参数(打包类型、宽带阈值) 无此参数配置
字幕添加 可设置压制字幕及外挂字幕 只能添加压制字幕
播放 可根据客户当前宽带环境自动选择码率进行播放 只能播放指定的码流

注意事项

  • 使用多码率打包模板,不支持标准加密。
  • 字幕文件必须和视频源文件在同一个区域,同一个bucket中。
  • 打包模板中字幕只支持vtt格式,并且字幕参数覆盖时,需注意,Language参数仅用于检索需要替换的字幕文件,而Language本身不会被替换,不存在的字幕语言不能替换。

接入流程

  1. 多码率打包模板的创建

    多码率打包模板的创建方式有两种。

    • 控制台创建控制台创建
    • API创建

      本示例代码中列举了普通转码模板配置、多码率打包模板配置、字幕打包模板配置,可根据实际情况使用。

          /**
           * 以下为调用示例
           */
          public static void main(String[] args) throws ClientException {
              DefaultAcsClient client = initVodClient("<Your AccessKeyId>", "<Your AccessKeySecret>");
              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;
          }
      说明
      • 如果只需要使用多码率打包模板,则不需要创建普通转码模板。
      • 多码率打包模板不支持使用标准加密,如果要使用标准加密,请使用普通转码模板。
  2. 发起多码率转码
    说明 发起转码前需先创建出多码率打包转码模板,创建方法参考第一步。
    • 控制台发起控制台发起
    • API发起
           public static void main(String[] args) {
             //regionId根据服务接入地址填写,例:接入服务在上海,则填cn-shanghai
             String regionId = "cn-shanghai";
              DefaultProfile profile = DefaultProfile.getProfile(regionId, "<accessKeyId>", "<accessSecret>");
              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;
          }
  3. 效果展示
    • 多码率打包后码流展示:(3路转码流,1路自适应流)效果展示_1
    • 播放效果展示:(使用上图中自适应的地址播放)效果展示_2