AVPlayer无缝切换源

2018-08-02  本文已影响195人  黑暗森林的歌者

AVPlayer无缝切换源

很多时候播放视频都有视频清晰度的需求,用户自己选择想要观看的分辨率.

一般切换清晰度就是切换NSURL,需要重新加载视频,如果不做处理就会出现没有图像的黑屏,其实这是不是bug。如下图这样:

没有过度图像

1、其实做出类似无缝切换的效果也不是难事,可以在切换的时候获取当前播放时间点的视频截图,然后用一个UIImageView覆盖到当前的view

- (void)showVideoShotImage {
    // 获取当前player的 sset
    AVAsset *currentPlayerAsset = self.player.currentItem.asset;

    if ([currentPlayerAsset isKindOfClass:AVURLAsset.class]) {
        // 判断是否是 AVURLAsset,并转成 AVURLAsset
        AVURLAsset *asset = (AVURLAsset *)currentPlayerAsset;

        AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];

        generator.appliesPreferredTrackTransform = YES;
        // 获取当前播放到的时间点
        CMTime time = CMTimeMakeWithSeconds(self.playingTime, 600);

        NSError *error = nil;

        CMTime actualTime;
        // 获取当前时间点的视频截图
        CGImageRef image = [generator copyCGImageAtTime:time actualTime:&actualTime error:&error];

        UIImage *shotImage = [[UIImage alloc] initWithCGImage:image];

        CGImageRelease(image);
        
        self.ShotImageView.image = shotImage;
    }
}

2、当视频缓冲的进度大于等于当前播放的时间,就开始播放视频,同时隐藏覆盖的视频截图,这时候的效果就类似无缝切换。

/**
 处理观察到都播放器的状态数据
 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    AVPlayerItem *item = object;
    if ([keyPath isEqualToString:@"status"]) {// 播放状态

    } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {// 缓冲进度
        [self handleLoadedTimeRangesWithPlayerItem:item];
    } else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {// 跳转后没数据

    } else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {// 跳转后有数据

    }
}
/** 处理缓冲进度 */
- (void)handleLoadedTimeRangesWithPlayerItem:(AVPlayerItem *)item {
    NSArray *loadArray = item.loadedTimeRanges;
    
    CMTimeRange range = [[loadArray firstObject] CMTimeRangeValue];
    
    float start = CMTimeGetSeconds(range.start);
    
    float duration = CMTimeGetSeconds(range.duration);
    
    NSTimeInterval totalTime = start + duration;// 缓存总长度
    
    
    if (totalTime >= self.playingTime) {
        // 隐藏视频截图
    }
}
上一篇下一篇

猜你喜欢

热点阅读