You need to enable JavaScript to run this app.
导航

雪碧图

最近更新时间2024.04.26 15:18:24

首次发布时间2024.04.26 15:18:24

点播 SDK 支持在拖拽进度条或执行 Seek 操作时,通过查看视频缩略图快速预览指定进度的视频内容。进度条缩略图预览功能基于视频雪碧图实现。雪碧图是由多帧截图拼接而成的一张大图,具有以下好处:

  • 图片体积小:将许多小图合并到一张大图中,可以减少图片文件的大小。

  • 请求次数少:通过图片整合,减少用户对服务器的请求次数,从而提高页面打开速度。

以下为一张雪碧图示例。该雪碧图中共包含 13 张缩略图。

基于上述雪碧图的进度条缩略图预览效果如下:

前提条件

获取雪碧图信息

通过 videoEngine:fetchedVideoModel: 回调获取雪碧图信息 TTVideoEngineThumbInfo。示例代码如下:

- (void)videoEngine:(TTVideoEngine *)videoEngine fetchedVideoModel:(TTVideoEngineModel *)videoModel {
    // 获取雪碧图的信息,目前返回雪碧图为一个数组,这里取数组第一个值即可
    TTVideoEngineThumbInfo *firstThumbInfo = videoModel.videoInfo.bigThumbs.firstObject;
    self.thumbInfo = firstThumbInfo;
}

以下为 TTVideoEngineThumbInfo 示例。详细参数说明请见 ThumbInfoList

// 本示例中视频时长 270 秒。Interval 为 10,表示每 10 秒截取一张缩略小图,一共截取 27 张,由 CaptureNum 表示。
// 每张雪碧大图包含 5*5 = 25 张缩略小图,所以需要 2 张雪碧大图。
// 两张雪碧大图的 URL 可从 StoreUrls 参数中获取。
[{
        "CaptureNum": 27,
        "StoreUrls": ["http://vod-demo-cover.volccdn.com/tos-cn-v-c91ba9/622ceb0b7f5b41afadf0fd9eb7572971_1639039860~tplv-vod-noop.image", 
                      "http://vod-demo-cover.volccdn.com/tos-cn-v-c91ba9/26d92b1fdbc74599a713b1c3c2bc3824_1639039860~tplv-vod-noop.image"],
        "CellWidth": 242,
        "CellHeight": 136,
        "ImgXLen": 5,
        "ImgYLen": 5,
        "Interval": 10,
        "Format": "jpg"
}]

参考以下示例代码获取雪碧图参数的值:

  • 对于 1.41.2 及以上版本,可直接通过 TTVideoEngineModel property 获取:

    @interface TTVideoEngineThumbInfo : NSObject<NSSecureCoding>
    
    // 缩略小图总个数。
    @property (nonatomic, assign) NSInteger imageNum; 
    // 每张缩略小图的宽,单位为 pixel。
    @property (nonatomic, assign) NSInteger imageXSize;
    // 每张缩略小图的高,单位为 pixel。
    @property (nonatomic, assign) NSInteger imageYSize;
    // 雪碧大图中每行包含的缩略小图数量。
    @property (nonatomic, assign) NSInteger imageXLen;
    // 雪碧大图中每列包含的缩略小图数量。
    @property (nonatomic, assign) NSInteger imageYLen;
    // 相邻缩略小图的时间间隔,单位为秒。
    @property (nonatomic, assign) CGFloat interval;
    // 雪碧大图格式。
    @property (nonatomic, nullable, copy) NSString *fext;
    // 雪碧大图 URL 列表。
    @property (nonatomic, nullable, copy) NSArray<NSString *> *imageURLs;
    
    /**
     获取 int key value
    
     @param key with key
     */
    - (NSInteger)getValueInt:(NSInteger)key;
    
    /**
     获取 float key value
    
     @param key with key
     */
    - (CGFloat)getValueFloat:(NSInteger)key;
    
    /**
     获取 string key value
    
     @param key with key
     */
    - (nullable NSString *)getValueStr:(NSInteger)key;
    
    /**
     获取 array key value
    
     @param key with key
     */
    - (nullable NSMutableArray<NSString *> *)getValueArray:(NSInteger)key;
    
    @end
    
  • 对于 1.41.2 之前的版本,需通过 key - value 方式获取:

    - (void)_parseThumbInfo:(TTVideoEngineThumbInfo *)thumbInfo {
        // 缩略小图总个数。
        NSInteger imageNum = [thumbInfo getValueInt:VALUE_THUMB_IMG_NUM];
        // 雪碧大图中每行包含的缩略小图数量。
        NSInteger imageXLen = [thumbInfo getValueInt:VALUE_THUMB_IMG_X_LEN];
        // 雪碧大图中每列包含的缩略小图数量。
        NSInteger imageYLen = [thumbInfo getValueInt:VALUE_THUMB_IMG_Y_LEN];
        // 每张缩略小图的宽,单位为 pixel。
        NSInteger imageXSize = [thumbInfo getValueInt:VALUE_THUMB_IMG_X_SIZE];
        // 每张缩略小图的高,单位为 pixel。
        NSInteger imageYSize = [thumbInfo getValueInt:VALUE_THUMB_IMG_Y_SIZE];
        // 相邻缩略小图的时间间隔,单位为秒。
        CGFloat interval = [thumbInfo getValueFloat:VALUE_THUMB_INTERVAL];
        // 雪碧大图格式。
        NSString *format = [thumbInfo getValueArray:VALUE_THUMB_FEXT];
        // 雪碧大图 URL 列表。
        NSArray *imageURLs = [thumbInfo getValueArray:VALUE_THUMB_IMG_URLS];
    }
    

获取并展示缩略图

参考以下示例代码获取并展示指定播放位置的缩略图:

/**
 * 根据播放进度获取当前需要展示的雪碧图
 * @param  progress 播放进度,取值范围为 [0, 1]。
 */
- (UIImage * _Nullable)_updateImageWithProgress:(CGFloat)progress {
    NSInteger imageNum = self.thumbInfo.imageNum;
    NSInteger imageXLen = self.thumbInfo.imageXLen;
    NSInteger imageYLen = self.thumbInfo.imageYLen;
    if (imageNum <= 0 || imageXLen <= 0 || imageYLen <= 0) {
        return nil;
    }
    
    NSInteger imageXSize = self.thumbInfo.imageXSize;
    NSInteger imageYSize = self.thumbInfo.imageYSize;
    NSArray *imageURLs = self.thumbInfo.imageURLs;
    
    /// 雪碧图可能是多张,以下为查找当前雪碧图 Index 的代码示例,业务方可根据需要设计更优的实现
    NSInteger index = MAX(0, ceil((imageNum - 1) * progress));
    NSInteger urlIndex = index / (imageXLen * imageYLen);
    
    /// 以下为加载雪碧图的逻辑
    /// 1. 获取当前雪碧大图的下载地址
    NSString *urlString = nil;
    if (urlIndex < imageURLs.count) {
        urlString = imageURLs[urlIndex];
    }
    if (!urlString.length) {
        return nil;
    }
    
    /// 2. 下载雪碧大图。以下代码仅为展示,这里需要根据业务设计不同的多线程提高效率
    /// 例如在播放开始前就开始记载雪碧图缓存本地,seek 是减少雪碧图加载时间
    ThumbnailHelper *thumbnailHelper = [ThumbnailHelper shared];
    UIImage *thumbBigImage = [thumbnailHelper getImageWithUrl:urlString];
    
    /// 3. 从雪碧大图中截取当前需要展示的缩略小图。以下代码仅为展示,业务方可根据需要设计更优的实现
    if (thumbBigImage) {
        CGFloat x = (index % imageXLen) * imageXSize;
        CGFloat y = (index / imageXLen % imageYLen) * imageYSize;
        CGRect rect = CGRectMake(x, y, imageXSize, imageYSize);
        UIImage *thumbImge = [self getThumbImgFromBigImage:thumbBigImage rect:rect];
        return thumbImge;
    }
    
    return nil;
}

/**
 * 从雪碧大图中裁剪缩略小图
 * 
 * @param  bigImage 雪碧大图
 * @param  rect 裁剪的 rect
 */
- (UIImage *)getThumbImgFromBigImage:(UIImage *)bigImage rect:(CGRect)rect {
    CGImageRef subImageRef = CGImageCreateWithImageInRect(bigImage.CGImage, rect);
    CGRect smallBounds = CGRectMake(0, 0, CGImageGetWidth(subImageRef), CGImageGetHeight(subImageRef));
    
    UIGraphicsBeginImageContext(smallBounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, smallBounds, subImageRef);
    UIImage *img = [UIImage imageWithCGImage:subImageRef];
    CGImageRelease(subImageRef);
    UIGraphicsEndImageContext();
    return img;
}