You need to enable JavaScript to run this app.
导航
播放源过期自动刷新
最近更新时间:2025.06.27 19:31:42首次发布时间:2025.06.27 18:02:20
我的收藏
有用
有用
无用
无用

本文介绍如何实现播放源过期自动刷新功能。当视频的 CDN 播放地址(URL)因安全策略(如签名验证)而具有时效性时,此功能可以在 URL 过期后自动获取新的有效地址,从而保证视频的持续流畅播放,避免因地址失效导致的播放中断。

说明

如需实现此功能,请集成 iOS 播放器 SDK 1.42.2.6 或以上版本。

前提条件

在为客户端实现播放源过期自动刷新功能前,您需要确保完成以下操作:

  1. 确认 CDN URL 的签名算法并获取签名密钥:
    • 若您使用视频点播 CDN,请前往视频点播控制台获取签名密钥并参考 URL 鉴权概述签名 Demo 了解签名算法。
      Image
    • 若您使用第三方云厂商的 CDN,请联系您的服务提供商获取对应域名的 CDN 签名密钥和签名算法。
  2. 在应用服务端部署刷新 URL 的接口。该接口接收一个已过期的 URL 作为请求参数,并返回一个新的有效 URL 及新 URL 的过期时间戳。服务端接口示例:
    • 请求方法:GET /api/refreshUrl
    • 请求参数:expiredUrl(已过期的 URL)
    • 返回结果:
    {
        "url": "https://www.example.com/1.mp4", // 刷新后的地址
        "expireInMS": 1705392219000 // 新地址的过期时间戳(毫秒)
    }
    

整体流程

Image

实现步骤

  1. 创建一个类并实现 TTVideoURLRefreshFetcher 协议。在该协议的 refreshNewUrls:oldUrl:complateBlock:errorBlock:cancelBlock: 方法中,请求您的应用服务端提供的刷新 URL 接口。

    @interface CustomRefreshFetcher ()
    
    @property (nonatomic, assign) BOOL isLoading;
    
    @end
    
    @implementation CustomRefreshFetcher
    
    #pragma mark - TTVideoURLRefreshFetcher
    
    - (void)refreshNewUrls:(NSString * _Nonnull)cacheKey
                    oldUrl:(NSString * _Nonnull)oldUrl
             complateBlock:(TTVideoURLRefreshCompleteBlock)complateBlock
                errorBlock:(TTVideoURLRefreshErrorBlock)errorBlock
               cancelBlock:(TTVideoURLRefreshCancelBlock)cancelBlock
        // 该回调会被多次出发,这里做一个兼容处理
        if (self.isLoading) {
            return;
        }
        self.isLoading = YES;
        
        // 这里为请求新的 URL 示例代码,业务需要根据自身业务替换这部分逻辑
        [self.networkClient fech:oldUrl success: ^(id response) {
            // 地址刷新成功
            NSString *newUrl = [response newUrl];
            // 注意单位是毫秒
            NSString *expireTimeInMs = [response expireTime]; 
            !complateBlock ?: complateBlock(newUrl, expireTimeInMs);
            self.isLoading = NO;
        } failure: ^(NSError *error) {
            // 地址刷新失
            !errorBlock ?: errorBlock(error);
            self.isLoading = NO;
        } cancel: ^() {
            // 用户取消请求,比如退出播放页. 调用 cancelBlock,SDK 内部释放资源
            !cancelBlock ?: cancelBlock();
            self.isLoading = NO;
        }];
    }
    
    // 播放器 SDK 请求取消刷新
    - (void)cancel {
        // 请实现取消请求逻辑
        [self.networkClient cancelRequest];
    }
    
    @end
    
  2. 创建 TTVideoEngineUrlSource 播放源时,将其 enableFallbackRefresh 属性设置为 YES,开启播放源过期自动刷新功能。

    - (void)play {
        // 构建播放源
        NSString *url = @"http://test.mp4"; // 播放器地址
        NSString *cacheKey = @"cache key";  // 缓存 cache key,建议使用 url的 md5 值
        TTVideoEngineUrlSource *source = [[TTVideoEngineUrlSource alloc] initWithUrl:url cacheKey:cacheKey];
        source.enableFallbackRefresh = YES; // 开启播放源过期自动刷新功能
    
        // 如果是 HLS 播放源,建议开启如下 option
        [self.videoEngine setOptionForKey:VEKKeyIsEnableSegError value:@(YES)];
    
        // 实现播放地址刷新的 protocol, 注意 refreshFetcher 要定义成全局变量,避免使用局部变量被提前释放导致自刷新不生效
        self.refreshFetcher = [[CustomRefreshFetcher alloc] init];
        self.videoEngine.urlRefreshFetcher = self.refreshFetcher;
    
        // 设置播放源
        [self.videoEngine setVideoEngineVideoSource:source];
    
        // 播放
        [self.videoEngine play];
    }
    
  3. (可选)为 HLS 播放源自定义 CacheKey:如果 HLS 视频 TS 分片的 URL 包含签名,需要通过设置 TTVideoEngineHLSProxyDelegate 并实现 generateFileKey:hlsFileKey:infos: 协议方法,来自定义 TS 文件的 cacheKey 生成规则。

    /*
     * 为 HLS 源自定义 CacheKey,非 HLS 源不用调用 CacheSettings.getInstance().setGenerateFileKeyCallback 方法。
     * 针对 HLS,TS 地址的 cacheKey 生成规则是播放器内部生成的,规则是 md5(pathOf(tsUrl));
     * 对于 TS 地址签算在 path 中的情况,为保证 cacheKey 的唯一性,需要业务通过下面接口自定义 TS cacheKey 的生成规则。
     */
    // 1. 设置 HLSProxy 协议
    [TTVideoEngine setHLSProxyDelegate:self];
    
    // 2. 实现 HLSProxy 协议,根据业务自身需求,自定义 TS 缓存 Key, 其中 url 为 TS 地址,hlsFileKey 为 M3U8 文件 key
    - (NSString * _Nullable)generateFileKey:(NSString *_Nonnull)url 
                                hlsFileKey:(NSString *_Nonnull)hlsFileKey 
                                     infos:(NSDictionary *_Nullable)infos {
        
    }