You need to enable JavaScript to run this app.
视频点播

视频点播

复制全文
进阶功能
添加外挂字幕
复制全文
添加外挂字幕

外挂字幕指与视频文件分离的字幕文件,用户可在播放时按需导入。播放器 SDK 支持添加 WebVTT (Web Video Text Tracks) 和 SRT (SubRip Text) 格式的外挂字幕。外挂字幕的优势在于其灵活性,用户可按需选择是否加载字幕以及加载何种语言的字幕,且无需进行视频转码,只需在播放端设置即可显示。本文介绍如何使用播放器 SDK 添加外挂字幕。

前提条件

  • 外挂字幕为高级版或企业版功能。请确保您已购买高级版或企业版 License,购买方式详见License 管理

    注意

    自 1.36.1 版本起,外挂字幕功能由增值服务调整至高级版和企业版。若您集成 1.36.1 之前的版本且想要使用此功能,请升级至最新版本。

  • 如果您通过 Vid 方式播放视频,需要准备字幕文件:
    • 如果您已有单独的字幕文件,可将字幕文件上传至视频点播服务并与 Vid 绑定。具体请见上传字幕文件并绑定 Vid
    • 如果您没有单独的字幕文件,可通过视频点播媒体处理服务生成字幕文件。具体请见智能生成字幕文件

核心流程说明

出于拓展性的考量,播放器 SDK 只返回字幕文本信息,具体的字幕展示需要您结合 UI 控件自行实现。实现外挂字幕功能的核心流程如下:

  1. 播放前配置:在播放器初始化后、调用 play 之前,完成以下所有配置:
    1. 开启功能:通过 setIntOption 方法开启外挂字幕功能及相关优化项。
    2. 设置字幕源(二选一):
      • DirectURL:直接将字幕文件 URL 设置给播放器,适用于对起播速度有要求的场景,如短剧、短视频。
      • Vid + SubtitleToken:与视频点播服务深度集成,开发简单,管理便捷。
    3. 设置字幕回调:调用 setSubInfoCallBack 注册监听器,以接收字幕内容。
  2. 播放中实现:
    1. 渲染字幕:在 onSubInfoCallback 回调中获取 SDK 按时间顺序推送的字幕文本,并将其渲染到您的 UI 控件(如 TextView)上。
    2. 提供交互控制:
      1. 开启/关闭字幕:调用 setIntOption 控制字幕的显示与隐藏。
      2. 切换语言:调用 setIntOption 并传入目标语言的 sub_id 实现切换。
  3. (可选)进阶使用:
    • 字幕预加载:如需提升用户观看视频时字幕的加载速度和成功率,可结合视频预加载策略,在播放前提前缓存字幕文件。此功能需在预加载阶段就指定好视频源和字幕源。
    • 播放过程中动态添加字幕源。

开启外挂字幕功能

参考以下示例代码开启外挂字幕功能:

// 外挂字幕功能总开关,play 前调用
// 0: 关闭外挂字幕功能;1: 开启外挂字幕功能
mVideoEngine.setIntOption(PLAYER_OPTION_ENABLE_OPEN_SUB_THREAD, 1);
// 外挂字幕加载优化开关
// 0: 关闭外挂字幕加载优化;1: 开启外挂字幕加载优化
mVideoEngine.setIntOption(PLAYER_OPTION_ENABLE_OPT_SUB_LOAD_TIME, 1);
// 使用数据加载模块 MDL 加载外挂字幕,提升加载成功率
// 0: 不使用 MDL 加载外挂字幕;1: 使用 MDL 加载外挂字幕
mVideoEngine.setIntOption(PLAYER_OPTION_SUB_ENABLE_MDL, 1);

设置字幕源

播放器 SDK 支持以下两种方式设置字幕源。您需根据实际情况选择。

使用 DirectURL 方式

使用 DirectURL 方式设置字幕源,您需要实现 SubDesInfoModelProvider 协议构建外挂字幕源,参考 JSON 字幕信息示例

说明

若您需要将已经下载到本地设备的离线字幕文件作为字幕源,将 url 设为本地文件路径即可,形如 file:///path/to/your/subtitle.srt

示例代码如下:

final String vid = "YOUR_VIDEO_ID"; // 播放源与 vid 必须一一对应
final String url = "http://www.example.com/h264.mp4";
final String cacheKey = TTVideoEngine.computeMD5(url);
// 1. 构建字幕信息
SubDesInfoModel subtitleModel = null;
try {
    JSONObject subtitleJson = new JSONObject();
    JSONArray list = new JSONArray();

    JSONObject subtitle1 = new JSONObject();
    subtitle1.put("language", "cmn-Hans-CN");
    subtitle1.put("language_id", 1);
    subtitle1.put("url", "YOUR_CHINESE_SUBTITLE_URL");
    subtitle1.put("format", "webvtt");
    subtitle1.put("sub_id", 0);
    list.put(subtitle1);

    JSONObject subtitle2 = new JSONObject();
    subtitle2.put("language", "eng-US");
    subtitle2.put("language_id", 2);
    subtitle2.put("url", "YOUR_ENGLISH_SUBTITLE_URL");
    subtitle2.put("format", "webvtt");
    subtitle2.put("sub_id", 1);
    list.put(subtitle2);

    subtitleJson.put("list", list);
    subtitleModel = new SubDesInfoModel(subtitleJson);
} catch (JSONException e) {
    e.printStackTrace();
}

// 2. 设置播放源
DirectUrlSource directUrlSource = new DirectUrlSource.Builder()
        .setVid(vid)
        .addItem(new DirectUrlSource.UrlItem.Builder()
                .setUrl(url)
                .setCacheKey(cacheKey)
                .build())
        .build();
mVideoEngine.setStrategySource(directUrlSource);

// 3. 设置字幕源
// 必须在设置播放源之后且在 play 之前设置 subtitleModel
if (subtitleModel != null) {
    mVideoEngine.setSubDesInfoModel(subtitleModel);
}

使用 Vid + SubtitleToken 方式

使用 Vid + SubtitleToken 方式设置字幕源的示例代码如下:

说明

您可在应用服务端通过视频点播服务端 SDK 签发字幕鉴权 Token

String vid = "YOUR_VIDEO_ID"; // AppServer 下发
String playAuthToken = "YOUR_PLAYAUTHTOKEN"; // AppServer 下发
String subAuthToken = "YOUR_SUBAUTHTOKEN"; // AppServer 下发

// 1. 创建 Vid 播放源
VidPlayAuthTokenSource vidSource = new VidPlayAuthTokenSource.Builder()
        .setVid(vid)
        .setPlayAuthToken(playAuthToken)
        .build();

// 2. 设置播放源
mVideoEngine.setStrategySource(vidSource);

// 3. 设置字幕鉴权 token
mVideoEngine.setSubAuthToken(subAuthToken);

// 4. 设置回调,在获取到视频信息后,进一步处理字幕
mVideoEngine.setVideoInfoListener(new VideoInfoListener() {
    @Override
    public boolean onFetchedVideoInfo(VideoModel videoModel) {
        // 获取视频数据成功回调
        Log.v("VideoPlay", "onFetchedVideoInfo " + videoModel);
        if (videoModel == null) return false;
        if (mVideoEngine == null) return false;

        // 5. 获取视频包含的所有字幕信息
        List<SubInfo> subInfoList = mVideoEngine.supportedSubInfoList();
        if (subInfoList == null || subInfoList.isEmpty()) {
            return false;
        }

        // 6. 根据语言ID筛选需要的字幕,并将其字幕ID添加到列表中
        //    字幕语言映射表见:https://www.volcengine.com/docs/4/1186356
        List<String> subtitleIds = new ArrayList<>();
        for (SubInfo info : subInfoList) {
            // 例如,筛选出中文和英文字幕
            int languageId = info.getValueInt(VALUE_SUB_INFO_LANGUAGE_ID);
            if (languageId == 1) { // 1 代表中文
                subtitleIds.add("" + info.getValueInt(VALUE_SUB_INFO_ID));
            } else if (languageId == 2) { // 2 代表英文
                subtitleIds.add("" + info.getValueInt(VALUE_SUB_INFO_ID));
            }
 
        }
        String subIds = trans(subtitleIds);

        // 7. 将筛选出的字幕 ID 列表设置给播放器,以便后续加载和显示
        mVideoEngine.setStringOption(PLAYER_OPTION_SUB_IDS, subIds);
        return false;
    }

    String trans(List<String> ids){
        String ans = "";
        for(int i = 0; i < ids.size(); i++){
            ans += ids.get(i);
            if(i < ids.size() - 1){
                ans += ",";
            }
        }
        return ans;
    }
});

设置字幕回调

在调用 play 播放前,调用 setSubInfoCallBack 设置字幕回调及内容。示例代码如下:

mVideoEngine.setSubInfoCallBack(new SubInfoSimpleCallBack() {
    @Override
    public void onSubPathInfo(String subPathInfoJson, Error error) {
        // vid + subTitleToken 播放,字幕列表信息回调
    }

    @Override
    public void onSubInfoCallback(int code, String infoJson) {
        // 字幕信息回调
        JSONObject jsonObject = new JSONObject(infoJson);
        String subtitle = jsonObject.optString("info");
        textView.setText(subtitle); // 设置给字幕 TextView
    }
        
    @Override
    public void onSubSwitchCompleted(int success, int subId) {
        // 字幕语言切换回调
    }
    
    @Override
    public void onSubLoadFinished(int success) {
        // 字幕文件下载结果回调

    }
});

控制字幕

开启/关闭字幕输出

参考以下示例代码在起播时或者播放过程中控制开启或者关闭字幕输出:

// 字幕开关,起播时或者播放过程中控制打开或者关闭字幕
// 1: 输出字幕;0: 停止输出字幕
mVideoEngine.setIntOption(PLAYER_OPTION_ENABLE_OPEN_SUB, 1);
// 显示字幕 TextView
textView.setVisibility(View.VISIBLE);

切换字幕

参考以下示例代码切换不同语言的字幕:

说明

您需传入字幕语言 ID,详见语言

// 业务端维护字幕 ID 与语言的对应关系,方便扩展
mVideoEngine.setIntOption(PLAYER_OPTION_SWITCH_SUB_ID, sub_id);

进阶使用

字幕预加载

为提升用户观看视频时字幕的加载速度和成功率,可结合视频预加载策略,在播放前提前缓存字幕文件。此功能需在预加载阶段就指定好视频源和字幕源。

说明

预加载阶段

DirectUrl 模式
  1. 在初始化 SDK 前,开启预加载策略 V2 版本,并启用预加载策略。

    // 开启预加载策略 V2 版本
    StrategyManager.setVersion(StrategyManager.VERSION_2);
    // 初始化播放器 SDK
    Env.init(/* 省略初始化代码 */);
    // 开启并使用预加载策略
    TTVideoEngine.enableEngineStrategy(STRATEGY_TYPE_PRELOAD, STRATEGY_SCENE_SMALL_VIDEO);
    
  2. 构建字幕源和播放源。

    private void setPreloadDirectURLSubtitleResource(){
        // 1. 创建字幕源 Model
        SubDesInfoModel subtitleModel = null;
        // 建议使用 JSONObject 构建 JSON 字符串,避免手动拼接导致格式错误
        try {
            JSONObject subtitleJson = new JSONObject();
            JSONArray list = new JSONArray();
    
            JSONObject subtitle1 = new JSONObject();
            subtitle1.put("language", "cmn-Hans-CN");
            subtitle1.put("language_id", 1);
            subtitle1.put("url", "YOUR_CHINESE_SUBTITLE_URL");
            subtitle1.put("format", "webvtt");
            subtitle1.put("sub_id", 0);
            list.put(subtitle1);
    
            JSONObject subtitle2 = new JSONObject();
            subtitle2.put("language", "eng-US");
            subtitle2.put("language_id", 2);
            subtitle2.put("url", "YOUR_ENGLISH_SUBTITLE_URL");
            subtitle2.put("format", "webvtt");
            subtitle2.put("sub_id", 1);
            list.put(subtitle2);
    
            subtitleJson.put("list", list);
            subtitleModel = new SubDesInfoModel(subtitleJson);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    
        int subtitleId = 1; // 预加载的字幕 ID
        String vid = "YOUR_VIDEO_ID_1";
        String videoUrl = "YOUR_VIDEO_URL_1";
        String videoCacheKey = TTVideoEngine.computeMD5(videoUrl);
        // 2. 在播放源中设置字幕源 Model
        source1 = new DirectUrlSource.Builder()
                .setVid(vid)
                .addItem(new DirectUrlSource.UrlItem.Builder()
                        .setUrl(videoUrl)
                        .setCacheKey(videoCacheKey)
                        .build())
                .setSubtitleModel(subtitleModel)
                .setSubtitleId(0)
                .build();
        videoUrl = "YOUR_VIDEO_URL_2";
        vid = "YOUR_VIDEO_ID_2";
        videoCacheKey = TTVideoEngine.computeMD5(videoUrl);
        source2 = new DirectUrlSource.Builder()
                .setVid(vid)
                .addItem(new DirectUrlSource.UrlItem.Builder()
                        .setUrl(videoUrl)
                        .setCacheKey(videoCacheKey)
                        .build())
                .setSubtitleModel(subtitleModel)
                .setSubtitleId(1)
                .build();
                
        // 3. 设置预加载策略
        StrategyPreloadConfig config = new StrategyPreloadConfig.Builder()
                .setCount(2)
                .setSize(800000)
                .setStartBufferLimit(15)
                .setStopBufferLimit(5)
                .build();
        StrategyManager.instance().setCustomPreloadConfig(config);
        
        // 4. 创建播放源列表
        List<StrategySource> list = new ArrayList<>();
        list.add(source1);
        list.add(source2);
        TTVideoEngine.setStrategySources(list);
        
        // 5. 给播放器添加播放当前播放源
        ttVideoEngine.setStrategySource(source1);
        ttVideoEngine.setSubDesInfoModel(subtitleModel);
        ttVideoEngine.setIntOption(PLAYER_OPTION_SWITCH_SUB_ID, 0);
    }
    

Vid 模式
  1. 在初始化 SDK 前,开启预加载策略 V2 版本,并启用预加载策略。

    // 开启预加载策略 V2 版本
    StrategyManager.setVersion(StrategyManager.VERSION_2);
    // 初始化播放器 SDK
    Env.init(/* 省略初始化代码 */);
    // 开启并使用预加载策略
    TTVideoEngine.enableEngineStrategy(STRATEGY_TYPE_PRELOAD, STRATEGY_SCENE_SMALL_VIDEO);
    
    // 设置预加载任务工厂,用于预加载策略内部构建预加载任务
    StrategyManager.instance().setPreloadTaskFactory(new PreloadTaskFactory() {
        @Override
        public PreloaderVidSubtitleItem createSubtitleVidItem(VidPlayAuthTokenSource vidSource, long preloadSize) {
            final PreloaderVidSubtitleItem item = PreloadTaskFactory.super.createSubtitleVidItem(vidSource, preloadSize);
            item.setFetchEndListener(new PreloaderVidSubtitleItemFetchListener() {
            
                @Override
                public void onGetPlayInfoResult(VideoModel videoModel, Error error) {
                    // 若支持用户切换视频清晰度,需要通过 item.setResolution 方法重新设置清晰度,覆盖 VidPlayAuthTokenSource 中的清晰度
                    
                    if (videoModel == null) return;
                    
                    Resolution resolution = Resolution.High; // 480P
                    resolution = TTVideoEngine.findDefaultResolution(videoModel, resolution);
    
                    final VideoInfo videoInfo = videoModel.getVideoInfo(resolution, false);
                    if (videoInfo == null) return;
                    item.setResolution(videoInfo.getResolution());
                }
    
                @Override
                public void onGetSubtitleInfoResult(SubDesInfoModel subDesInfoModel, Error error) {
                    // 若下发多个语言的字幕文件,则需要根据语言来查找对应的字幕 id,通过 item.setSubtitleId 设置后才能预加载对应语言字幕
                    
                    if (subDesInfoModel == null) return;
    
                    final List<SubModelProvider> subInfos = subDesInfoModel.getSubModelList();
                    if (subInfos == null || subInfos.isEmpty()) return;
                    
                    // 语言 ID 枚举参考官网文档:https://www.volcengine.com/docs/4/1186356
                    final int languageId = 1; // 用户默认选中字幕语言,比如:中文
                    Integer subtitleId = findPreloadSubtitleIdByLanguageId(subInfos, languageId);
                    if (subtitleId != null) {
                        item.setSubtitleId(subtitleId);
                    }
                }
            });
            return item;
        }
    });
    
  2. 构造用于预加载的 Vid 播放源时,除了视频的 vidplayAuthToken,还需提供字幕鉴权 token。

    //preload为true时设置使用预加载,id用于选择播放哪个视频
    private void setVidSubtitleResource(boolean preload, int id){
        String vid = "填写第一个视频的vid"; // AppServer 下发
        String playAuthToken = "添加第一个视频的播放token"; // AppServer 下发
        String subAuthToken = "添加第一个视频的字幕token"; // AppServer 下发
        String vid1 = "填写第二个视频的vid"; // AppServer 下发
        String playAuthToken1 = "添加第二个视频的播放token"; // AppServer 下发
        String subAuthToken1 = "添加第二个视频的字幕token"; // AppServer 下发
        final Resolution resolution = Resolution.High;
    
        // 设置 Vid 播放源
        VidPlayAuthTokenSource vidPATSource = new VidPlayAuthTokenSource.Builder()
                .setVid(vid)
                .setPlayAuthToken(playAuthToken)
                .setResolution(resolution)
                .setSubtitleAuthToken(subAuthToken)
                .build();
        VidPlayAuthTokenSource vidPATSource1 = new VidPlayAuthTokenSource.Builder()
                .setVid(vid1)
                .setPlayAuthToken(playAuthToken1)
                .setResolution(resolution)
                .setSubtitleAuthToken(subAuthToken1)
                .build();
    
    
        if(preload){
            //设置预加载策略
            StrategyPreloadConfig config = new StrategyPreloadConfig.Builder()
                    .setCount(2)
                    .setSize(800000)
                    .setStartBufferLimit(15)
                    .setStopBufferLimit(5)
                    .build();
            StrategyManager.instance().setCustomPreloadConfig(config);
            List<StrategySource> list = new ArrayList<>();
            list.add(vidPATSource);
            list.add(vidPATSource1);
            //添加预加载播放源列表
            TTVideoEngine.setStrategySources(list);
        }
    
        if(id == 1){
            ttVideoEngine.setStrategySource(vidPATSource);
            ttVideoEngine.setSubAuthToken(subAuthToken);
        }else{
            ttVideoEngine.setStrategySource(vidPATSource1);
            ttVideoEngine.setSubAuthToken(subAuthToken1);
        }
    
        // 设置播放源获取成功回调
        ttVideoEngine.setVideoInfoListener(new VideoInfoListener() {
            @Override
            public boolean onFetchedVideoInfo(VideoModel videoModel) {
                // 获取视频数据成功回调
                Log.v("RunjieTest", "onFetchedVideoInfo " + videoModel);
                if (videoModel == null) return false;
                if (ttVideoEngine == null) return false;
    
                // 请求中、英字幕文件的 ID 数组
                List<String> subtitleIds = new ArrayList<>();
                // 获取当前所有字幕语言的接口
                List<SubInfo> subInfoList = ttVideoEngine.supportedSubInfoList();
                // 字幕语言映射表见:https://www.volcengine.com/docs/4/1186356
                if (subInfoList != null && subInfoList.size() > 0) {
                    for (SubInfo info : subInfoList) {
                        if (info.getValueInt(VALUE_SUB_INFO_LANGUAGE_ID) == 1) {
                            subtitleIds.add(""+info.getValueInt(VALUE_SUB_INFO_ID)); // CN
                        } else if (info.getValueInt(VALUE_SUB_INFO_LANGUAGE_ID) == 2) {
                            subtitleIds.add(""+info.getValueInt(VALUE_SUB_INFO_ID)); // EN
                        }
                    }
                }
                String subIds = trans(subtitleIds); // 省略实现,将 subtitleIds 转为逗号分割的字符串,如:"1111,2222"
                // 传入字幕语言 ID 列表
                ttVideoEngine.setStringOption(PLAYER_OPTION_SUB_IDS, subtitleIds.get(0));
                return false;
            }
        });
    }
    

播放阶段

  1. 使用字幕预加载必须要开启数据加载模块 MDL 来加载外挂字幕。

    // 0: 不使用 MDL 加载外挂字幕;1: 使用 MDL 加载外挂字幕
    mVideoEngine.setIntOption(PLAYER_OPTION_SUB_ENABLE_MDL, 1);
    
  2. 指定播放的字幕 ID。确保播放时设置的字幕 ID 与预加载播放源中的字幕 ID 一致。

    mVideoEngine.setIntOption(PLAYER_OPTION_SWITCH_SUB_ID, sub_id);
    
  3. 监听命中回调:通过 VideoEngineInfoListener 监听 USING_MDL_HIT_CACHE_SIZE_SUBTITLE 事件。通过判断 cacheSize 是否大于 0,可以确认是否命中了字幕缓存。若未命中,请检查预加载任务是否成功,以及播放和预加载的 subtitleId 是否匹配。

    // TTVideoEngine 实例设置监听
    mVideoEngine.setVideoEngineInfoListener(new VideoEngineInfoListener() {
        @Override
        public void onVideoEngineInfos(VideoEngineInfos videoEngineInfos) {
            if (videoEngineInfos == null) {
                return;
            }
            
            // 字幕缓存命中监听
            if (videoEngineInfos.getKey().equals(USING_MDL_HIT_CACHE_SIZE_SUBTITLE)) {
                // 起播命中缓存判断
                String taskKey = videoEngineInfos.getUsingMDLPlayTaskKey();// 使用的 key 信息
                long cacheSize = videoEngineInfos.getUsingMDLHitCacheSize();// 命中缓存文件 size
                
                // cacheSize > 0, 表示命中缓存
                // cacheSize = 0, 未命中缓存,请排查预加载任务是否成功,如果字幕描述信息中包含多个字幕语言,请查看播放和预加载的 subtitleId 是否一致
            }
        }
    });
    

播放过程中动态添加字幕源

在播放过程中,可以通过 addAdditionSubModelswitchAdditionSubModel 方法动态地添加新的字幕源并按需切换。

说明

动态添加字幕源自 1.47.1.10 起支持。

仅添加字幕源

// 初始化JSON字幕信息
try {
    JSONObject subJson = new JSONObject();
    subJson.put("sub_id", 1); //(必填)字幕 ID,用于在播放器中区分不同的字幕
    subJson.put("language", "cmn-Hans-CN");//(必填)字幕语言
    subJson.put("language_id", 1);//(必填)语言 ID
    subJson.put("url","https://example.srt"); //(必填)字幕文件 URL
    subJson.put("format", "srt");//(必填)字幕格式,支持 webvtt 和 srt
    // 添加字幕信息
    ttVideoEngine.addAdditionSubModel(new SubModel(subJson));
} catch (JSONException e) {
    e.printStackTrace();
}  

// 添加字幕源后,不会主动展示,您需要调用以下接口传入字幕对应的sub_id展示添加后的字幕
ttVideoEngine.setIntOption(PLAYER_OPTION_SWITCH_SUB_ID, sub_id);

添加字幕源并直接展示

// 初始化 JSON 字幕信息
try {
    JSONObject subJson = new JSONObject();
    subJson.put("sub_id", 1); //(必填)字幕 ID,用于在播放器中区分不同的字幕,需要保证字幕ID的唯一性
    subJson.put("language", "cmn-Hans-CN");//(必填)字幕语言
    subJson.put("language_id", 1);//(必填)语言 ID
    subJson.put("url","https://example.srt"); //(必填)字幕文件 URL
    subJson.put("format", "srt");//(必填)字幕格式,支持 webvtt 和 srt
    // 添加字幕源,并且切换到展示该字幕
    ttVideoEngine.switchAdditionSubModel(new SubModel(subJson));
} catch (JSONException e) {
    e.printStackTrace();
}

参考信息

JSON 字幕信息说明

JSON 字幕信息包含以下字段:

字段

说明

sub_id

(必填)字幕 ID,用于在播放器中区分不同的字幕。

  • 如果您从视频点播服务获取字幕,可使用视频点播服务下发的字幕数据中的 SubtitleId 字段。
  • 如果您是自行拼装字幕 JSON,可以使用 Index 标识来区分字幕。

language_id

(必填)语言 ID。取值详见语言。您需要自行维护字幕 ID 与语言 ID 的映射关系。

language

(必填)语言。取值详见语言

url

(必填)字幕文件 URL。

format

(必填)字幕格式,支持 webvttsrt

示例如下:

{
  "list": [
    {
      "language": "rus-RU",
      "language_id": 6,
      "url": "https://example.volcengine.com/cbebedaade0947ce51a*******17f0b13/6087d12f/video/tos/cn/tos-cn-o-0004/52ce3882d70941d5b660913cbd83d969/",
      "format": "webvtt",
      "sub_id": 328934091
    },
    {
      "language": "cmn-Hans-CN",
      "language_id": 1,
      "url": "https://example.volcengine.com/93adb942***bdfce8cb/6087d12f/video/tos/***a4122dac42d69e8233a4dfda82fe/",
      "format": "webvtt",
      "sub_id": 429984091
    },
    {
      "language": "cmn-Hans-CN|eng-US",
      "language_id": 5,
      "url": "https://***.com/d782d36702***7b9719/6087d12f/video/tos/***5f0d106146a19ad566b967211091/",
      "format": "webvtt",
      "sub_id": 829987091
    }
  ]
}
最近更新时间:2025.11.12 15:04:54
这个页面对您有帮助吗?
有用
有用
无用
无用