Tip-获取视频的第一帧图片并利用缓存

235 阅读3分钟
// 获取视频第一帧图片
- (UIImage *)videoImageWithvideoURL:(NSURL *)videoURL atTime:(NSTimeInterval)time {
    //先从缓存中查找是否有图片
    SDImageCache *cache =  [SDImageCache sharedImageCache];
    UIImage *memoryImage =  [cache imageFromMemoryCacheForKey:videoURL.absoluteString];
    if (memoryImage) {
        return memoryImage;
    }else{
        //再从磁盘中查找是否有图片
        UIImage *diskImage =  [cache imageFromDiskCacheForKey:videoURL.absoluteString];
        if (diskImage) {
            return diskImage;
        }
    }
    if (!time) {
        time = 1; //默认去出第一帧
    }
    //如果都不存在,开启异步线程截取对应时间点的画面,转成图片缓存至磁盘
    //开启信号量用于加锁
    dispatch_semaphore_t signal = dispatch_semaphore_create(0);
    
    //局部变量准备赋值
    __block UIImage *image = nil;
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
        NSParameterAssert(asset);
        AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:asset];
        assetImageGenerator.appliesPreferredTrackTransform = YES;
        assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
        CGImageRef thumbnailImageRef = NULL;
        CFTimeInterval thumbnailImageTime = time;
        NSError *thumbnailImageGenerationError = nil;
        thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60)actualTime:NULL error:&thumbnailImageGenerationError];
        if(!thumbnailImageRef)
            NSLog(@"thumbnailImageGenerationError %@",thumbnailImageGenerationError);
        UIImage *thumbnailImage = thumbnailImageRef ? [[UIImage alloc]initWithCGImage: thumbnailImageRef] : nil;
        image = thumbnailImage;
        
        dispatch_async(dispatch_get_main_queue(), ^{
            SDImageCache * cache =  [SDImageCache sharedImageCache];
            //保存至缓存
            [cache storeImage:thumbnailImage forKey:videoURL.absoluteString toDisk:YES completion:nil];
        });
        //完成后解锁
        dispatch_semaphore_signal(signal);
    });
    //等待解锁,解锁后才执行下一步
    dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
    return image;
}
  • 获取到了一个视频的URL,获取视频的第一帧,

  • 如果图片存在缓存,则直接使用缓存,没有缓存则去出图片后保存到缓存

  • 但是我这出现了个问题:就是加锁后 单元格 在显示图片的时候没有缓存是加载数据会很慢大概有2-3秒的等待,可能数据比较少如果数据多的话就更慢了,所以把锁给去掉了

  • 这个是在Cell里直接写的 _dynamicImageView 就是cell中需要赋值的视图

- (void)videoImageWithvideoURL:(NSURL *)videoURL atTime:(NSTimeInterval)time {
    
    //先从缓存中查找是否有图片
    SDImageCache *cache =  [SDImageCache sharedImageCache];
    UIImage *memoryImage =  [cache imageFromMemoryCacheForKey:videoURL.absoluteString];
    if (memoryImage) {
//        [self setBackgroundImage:memoryImage forState:UIControlStateNormal];
        _dynamicImageView.image = memoryImage;
        return;
    }else{
        //再从磁盘中查找是否有图片
        UIImage *diskImage =  [cache imageFromDiskCacheForKey:videoURL.absoluteString];
        if (diskImage) {
//            [self setBackgroundImage:diskImage forState:UIControlStateNormal];
            _dynamicImageView.image = diskImage;

            return;
        }
    }
    if (!time) {
        time = 1;
    }
    //如果都不存在,开启异步线程截取对应时间点的画面,转成图片缓存至磁盘
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
        NSParameterAssert(asset);
        AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:asset];
        assetImageGenerator.appliesPreferredTrackTransform = YES;
        assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
        CGImageRef thumbnailImageRef = NULL;
        CFTimeInterval thumbnailImageTime = time;
        NSError *thumbnailImageGenerationError = nil;
        thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60)actualTime:NULL error:&thumbnailImageGenerationError];
        if(!thumbnailImageRef)
            NSLog(@"thumbnailImageGenerationError %@",thumbnailImageGenerationError);
        UIImage*thumbnailImage = thumbnailImageRef ? [[UIImage alloc]initWithCGImage: thumbnailImageRef] : nil;
        
        dispatch_async(dispatch_get_main_queue(), ^{
            SDImageCache * cache =  [SDImageCache sharedImageCache];
            [cache storeImage:thumbnailImage forKey:videoURL.absoluteString toDisk:YES completion:nil];
//            [self setBackgroundImage:thumbnailImage forState:UIControlStateNormal];
            
            self->_dynamicImageView.image = thumbnailImage;

        });
        
    });
    
}
  • 这个是去掉了锁
// 获取视频第一帧
- (UIImage *)videoImageWithvideoURL:(NSURL *)videoURL atTime:(NSTimeInterval)time {
    //先从缓存中查找是否有图片
    SDImageCache *cache =  [SDImageCache sharedImageCache];
    UIImage *memoryImage =  [cache imageFromMemoryCacheForKey:videoURL.absoluteString];
    if (memoryImage) {
//        [_contentBtn setBackgroundImage:memoryImage forState:UIControlStateNormal];
        return memoryImage;
    }else{
        //再从磁盘中查找是否有图片
        UIImage *diskImage =  [cache imageFromDiskCacheForKey:videoURL.absoluteString];
        if (diskImage) {
//            [_contentBtn setBackgroundImage:diskImage forState:UIControlStateNormal];
            return diskImage;
        }
    }
    if (!time) {
        time = 1;
    }
    //如果都不存在,开启异步线程截取对应时间点的画面,转成图片缓存至磁盘
//    __weak typeof (_contentBtn) weakContentBtn = _contentBtn;
//    dispatch_semaphore_t signal = dispatch_semaphore_create(0);
    
    __block UIImage *image = nil;
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
        NSParameterAssert(asset);
        AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:asset];
        assetImageGenerator.appliesPreferredTrackTransform = YES;
        assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
        CGImageRef thumbnailImageRef = NULL;
        CFTimeInterval thumbnailImageTime = time;
        NSError *thumbnailImageGenerationError = nil;
        thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60)actualTime:NULL error:&thumbnailImageGenerationError];
        if(!thumbnailImageRef)
            NSLog(@"thumbnailImageGenerationError %@",thumbnailImageGenerationError);
        UIImage *thumbnailImage = thumbnailImageRef ? [[UIImage alloc]initWithCGImage: thumbnailImageRef] : nil;
        image = thumbnailImage;
        
        dispatch_async(dispatch_get_main_queue(), ^{
            SDImageCache * cache =  [SDImageCache sharedImageCache];
            [cache storeImage:thumbnailImage forKey:videoURL.absoluteString toDisk:YES completion:nil];
//            [weakContentBtn setBackgroundImage:thumbnailImage forState:UIControlStateNormal];
        });
        
//        dispatch_semaphore_signal(signal);
    });
//    dispatch_semaphore_wait(signal, DISPATCH_TIME_FOREVER);
    return image;
}
  • 所以这个锁的问题,我理解应该是可以不用加的以为没有其他线程同时去访问这个资源。去掉锁后速度会快很多。