獲取常規(guī)格式視頻縮略圖(適用于mp4君编、mov等)
/**
* 獲取視頻的縮略圖方法
* @param videoUrl 視頻鏈接 支持本地路徑和網(wǎng)絡(luò)路徑
* @return 視頻截圖
*/
+ (UIImage *)getVideoImageFromPath:(NSURL *)videoUrl{
UIImage *shotImage;
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoUrl options:nil];
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
gen.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMakeWithSeconds(0.0, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
shotImage = [[UIImage alloc] initWithCGImage:image];
CGImageRelease(image);
return shotImage;
}
獲取m3u8格式視頻縮略圖
m3u8格式是適用于直播流的格式跨嘉,加載時是以切片的模式分段加載,無法從視頻流中直接獲取某一幀圖片
這里是使用AVPlayerItemVideoOutput吃嘿,采用截屏輸出的方案來獲取首幀圖
該方法一定要視頻在可播放的狀態(tài)下才能取到祠乃,如果該縮略圖時做封面圖使用,建議還是和服務(wù)端的同事溝通一下參數(shù)方案吧
一兑燥、聲明對象
/// 播放器
@property (nonatomic, strong) AVPlayer *player;
/// 播放器item
@property (nonatomic, strong) AVPlayerItem *playerItem;
/// 播放器layer
@property (nonatomic, strong) AVPlayerLayer *playerLayer;
/// 視頻截圖輸出
@property (nonatomic, strong) AVPlayerItemVideoOutput *output;
二亮瓷、初始化播放器時,給播放器添加輸出對象
//包裝到Asset降瞳,防止抓包泄露視頻地址
AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL URLWithString:@"視頻鏈接"]];
//創(chuàng)建播放源
self.playerItem = [AVPlayerItem playerItemWithAsset:asset];
//創(chuàng)建播放器
self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
//設(shè)置播放控件
self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
//已經(jīng)創(chuàng)建過了寺庄,代表已經(jīng)添加到playerItem中,這里先移除,防止重復(fù)
if (self.output) {
[self.playerItem removeOutput:self.output];
}
NSDictionary *settings = @{(id)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)};
self.output = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:settings];
[self.playerItem addOutput:self.output];
播放器銷毀時要移除output對象并置為nil
[self.playerItem removeOutput:self.output];
self.output = nil;
三斗塘、監(jiān)聽播放器緩存到可以播放的狀態(tài)
獲取首幀縮略圖時一定要監(jiān)聽該狀態(tài)赢织,否則在此之前去截取會失敗
//監(jiān)聽緩存足夠播放的狀態(tài)
[self.playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
播放器銷毀時移除
[self.player.currentItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
四、去取首幀縮略圖
一定要先暫停馍盟,不然取到的圖片不一定是首幀圖于置,存在著播放中的誤差
//播放器狀態(tài)監(jiān)聽
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {//緩沖到足夠播放的狀態(tài)
[self.player pause];
//這里等待0.5秒時為了等player繪制完成,否則取不到video縮略圖
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//取縮略圖
UIImage *thumImg = [self getThumbnailImageCompletion];
[self.player play];
});
}
}
核心代碼贞岭,如果播放器有截屏的功能也可以用該方法瞄桨,獲取當(dāng)前播放幀的圖片
- (UIImage *)getThumbnailImageCompletion{
UIImage *frameImg = nil;
//確保當(dāng)前時間的視頻已經(jīng)加載完成
CVPixelBufferRef pixelBuffer = [self.output copyPixelBufferForItemTime:self.player.currentTime itemTimeForDisplay:nil];
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
CIContext *temporaryContext = [CIContext contextWithOptions:nil];
CGImageRef videoImage = [temporaryContext createCGImage:ciImage
fromRect:CGRectMake(0, 0,
CVPixelBufferGetWidth(pixelBuffer),
CVPixelBufferGetHeight(pixelBuffer))];
frameImg = [UIImage imageWithCGImage:videoImage];
CGImageRelease(videoImage);
CVBufferRelease(pixelBuffer);
return frameImg;
}