iOS 视频截图(hls ,mp4)

#HLS截图
From: http://www.jianshu.com/p/bd30ce34a76f

常规获取MP4某一帧画面的方法对m3u8流媒体而言并不适用,如果有需求中需要获取m3u8流媒体截图的小伙伴可以看一下这个方法。

首先,用AVPlayer创建一个视频播放器,并且对AVPlayerItem添加观察者,具体代码不在这里啰嗦了。

流媒体的某一帧在流媒体播放时才能获取,所以我们在KVO中去调用获取画面的方法:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    AVPlayerItem *playerItem=object;
    if ([keyPath isEqualToString:@"status"]) {
        AVPlayerStatus status= [[change objectForKey:@"new"] intValue];
        if(status==AVPlayerStatusReadyToPlay){
            NSLog(@"正在播放...,视频总长度:%.2f",CMTimeGetSeconds(playerItem.duration));
            //image即为获取到的视频帧截图
            UIImage *image = [self getPixelBufferForItem:playerItem];
        }
    }
}

获取视频帧的代码:

//获取m3u8视频帧画面
- (UIImage *)getPixelBufferForItem:(AVPlayerItem *)playerItem{

    AVPlayerItemVideoOutput *output = [[AVPlayerItemVideoOutput alloc] init];
    [playerItem addOutput:output];
    CVPixelBufferRef ref =[output copyPixelBufferForItemTime:CMTimeMake(1000, 60) itemTimeForDisplay:nil];
    UIImage *image = [self CVImageToUIImage:ref];
    return image;
}

copyPixelBufferForItemTime: itemTimeForDisplay:这个方法获取到的视频帧是CVPixelBufferRef类型,我们需要将CVPixelBufferRef类型转化为UIImage类型

//CVPixelBufferRef转UIImage
- (UIImage *)CVImageToUIImage:(CVPixelBufferRef)imageBuffer{
    CVPixelBufferLockBaseAddress(imageBuffer, 0);
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0);

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, baseAddress, bufferSize, NULL);

    CGImageRef cgImage = CGImageCreate(width, height, 8, 32, bytesPerRow, rgbColorSpace, kCGImageAlphaNoneSkipFirst|kCGBitmapByteOrder32Little, provider, NULL, true, kCGRenderingIntentDefault);


    UIImage *image = [UIImage imageWithCGImage:cgImage];

    CGImageRelease(cgImage);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(rgbColorSpace);

    NSData* imageData = UIImageJPEGRepresentation(image, 1.0);
    image = [UIImage imageWithData:imageData];
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
    return image;

}

swift 4 逻辑更完善

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//支持m3u8
open func snapshotImage() -> UIImage? {
guard let playerItem = self.playerItem else { //playerItem is AVPlayerItem
return nil
}
if self.videoOutput == nil {
self.videoOutput = AVPlayerItemVideoOutput(pixelBufferAttributes: nil)
playerItem.remove(self.videoOutput!)
playerItem.add(self.videoOutput!)
}
guard let videoOutput = self.videoOutput else {
return nil
}
let time = videoOutput.itemTime(forHostTime: CACurrentMediaTime())
if videoOutput.hasNewPixelBuffer(forItemTime: time) {
let lastSnapshotPixelBuffer = videoOutput.copyPixelBuffer(forItemTime: time, itemTimeForDisplay: nil)
if lastSnapshotPixelBuffer != nil {
let ciImage = CIImage(cvPixelBuffer: lastSnapshotPixelBuffer!)
let context = CIContext(options: nil)
let rect = CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(CVPixelBufferGetWidth(lastSnapshotPixelBuffer!)), height: CGFloat(CVPixelBufferGetHeight(lastSnapshotPixelBuffer!)))
let cgImage = context.createCGImage(ciImage, from: rect)
if cgImage != nil {
return UIImage(cgImage: cgImage!)
}
}
}
return nil
}

相关资料:
使用AVPlayer播放m3u8视频时,实现视频截图

AVPlayer 对m3u8 视频截屏
AVPlayer 截屏
一个git 上的播放器里面有截屏函数


#MP4 截屏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 根据视频的路径获取单帧图片 (多帧数 也有类似的简单函数)
- (UIImage *)getThumbImage:(NSURL *)url {
//测试视频地址
NSURL *soundFileURL = nil;
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"jiangwan" ofType:@"mp4"];
if (soundFilePath.length) {
soundFileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
}
//截第一帧
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:soundFileURL options:nil];
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
gen.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMakeWithSeconds(0.0, 1);
NSError *error = nil;
CMTime actualTime;
CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
UIImage *thumb = [[UIImage alloc] initWithCGImage:image];
return thumb;
}

相关链接
http://blog.csdn.net/u013756604/article/details/54095907

http://blog.csdn.net/u013282507/article/details/53930947

Author

陈昭

Posted on

2017-11-13

Updated on

2021-12-27

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

Kommentare

You forgot to set the shortname for Disqus. Please set it in _config.yml.