点播多码率自适应配置

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

说明

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

简介

视频点播服务目前支持视频打包模板和字幕打包模板,用于生成可切换不同分辨率和不同语言字幕的多码率自适应文件。支持通过控制台和API的方式创建多码率自适应模板。

相比较传统的单码率播放,自适应码率文件能够让播放器可根据终端网络带宽环境,选择最适合当前带宽环境和终端设备的码流播放,从而提升播放体验。视频打包模板和普通转码模板的区别,如下表所示:

区别项

视频打包模板

普通转码模板

参数配置

需要配置打包参数(打包类型、宽带阈值)。

无此参数配置。

字幕添加

  • 控制台方式:可设置外挂字幕。

  • API方式:可设置压制字幕及外挂字幕。

只能通过API的方式设置压制字幕。

播放效果

可根据客户当前宽带环境自动选择码率进行播放。

只能播放指定的码流。

注意事项

  • 视频打包模板不支持使用标准加密,如果要使用标准加密,请使用普通转码模板。

  • 字幕文件必须和视频源文件存储在同一个区域,同一个OSS Bucket中。

  • 字幕打包模板不能单独创建使用,必须与视频打包模板一同使用。

  • 字幕打包模板中,字幕文件仅只支持VTT格式。通过API方式配置时需注意,字幕参数覆盖时,Language参数仅用于检索需要替换的字幕文件,而Language本身不会被替换,不存在的字幕语言不能替换。

  • 转码服务均为收费项,具体请参见收费标准

控制台方式配置

  1. 创建多码率自适应的转码模板组。

    说明

    如果只需要使用多码率打包模板,则不需要创建普通转码模板,或删除所有普通转码模板,以免产生多余的转码费用。

    1. 登录视频点播控制台,在点播控制台左侧的导航栏选择配置管理 > 媒体处理配置 > 转码模板组

    2. 在转码模板组页签,单击添加转码模板组,进入添加转码模板页面。

    3. 设置模板组名称。

    4. 视频打包模板下方,单击添加模板,配置视频打包模板参数。

      • 其中基本参数封装格式固定为hls视频打包参数的配置说明如下:

        • 打包类型:固定为HLS打包

        • 带宽阈值:提供给播放器根据当前网络带宽环境判断需要选择播放的码流,单位:bps。建议使用推荐设置。

      • 基本参数视频参数音频参数高级参数条件转码参数的配置与普通转码模板的配置类似,请参见普通转码模板设置

      • 根据实际需求,通过添加模板,来创建多个不同码率、分辨率、清晰度的视频打包模板。

    5. 字幕打包模板下方,单击添加模板,单击字幕打包列表下的添加,配置字幕打包模板。

      根据实际需求,通过添加,来添加多个不同语言类型的字幕,每种类型仅支持一个字幕。

      字幕模板

      字幕模板各参数说明如下:

      参数名称

      描述

      打包类型

      现视频点播只支持HLS打包,因此固定为HLS打包

      语言类型

      字幕的语言类型,例如:cn(中文)ja(日文)en-US(英文)等。

      字幕流名称

      字幕在播放器上显示的名称,仅支持中文、英文、数字、中划线(-)、下划线(_)。

      示例:test

      字幕存储地址

      字幕文件的存储地址,为完整的OSS地址。字幕文件仅支持存储在视频点播分配的系统Bucket上,不支持CDN域名地址和HTTPS地址。

      字幕文件可通过调用CreateUploadAttachedMedia接口上传到视频点播分配的系统Bucket上。

      示例:http://example-bucket-****.oss-cn-shanghai.aliyuncs.com/subtitles/4dba87c2-a787-42cd-8328-2369aeb8****-cn.vtt

      操作

      支持删除操作。

    6. 视频打包模板及字幕打包模板创建完成后,单击保存控制台创建

  2. 发起多码率转码。

    1. 在视频点播控制台,选择媒资库 > 音/视频

    2. 音/视频页面,单击目标视频的媒体处理

    3. 处理类型选择用转码模板组处理,转码模板组选择第一步所创建的转码模板组,单击确定,发起媒体处理。

    002
  3. 效果展示。

    • 多码率打包后码流展示:(2路转码流,1路自适应流)

      在点播控制台,选择媒资库 > 音/视频,单击目标视频(上一步经过媒体处理的视频)的管理,选择视频地址页签。

      效果展示_1
    • 播放效果展示:(使用上图中自适应的地址播放)

      Aliplayer播放器基础配置页,输入播放地址(使用上图中视频地址页中自适应的地址),在播放预览页查看播放效果。

      效果展示_2

API方式配置

  1. 创建用于多码率自适应的转码模板组。

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

    说明

    如果只需要使用多码率打包模板,则不需要创建普通转码模板,或删除所有普通转码模板,以免产生多余的转码费用。

        /**
         * 以下为调用示例
         */
        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;
        }
  2. 发起多码率转码。

         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;
        }
  3. 效果展示。

    • 多码率打包后码流展示:(2路转码流,1路自适应流)

      在点播控制台,选择媒资库 > 音/视频,单击目标视频(上一步经过媒体处理的视频)的管理,选择视频地址页签。

      效果展示_1
    • 播放效果展示:(使用上图中自适应的地址播放)

      Aliplayer播放器基础配置页,输入播放地址(使用上图中视频地址页中自适应的地址),在播放预览页查看播放效果。

      效果展示_2