【iOS】控件截图、MP4格式视频流和m3u8格式视频流截取某一帧功能的实现

最近开发遇到一个点击按钮实现直播视频流截屏的功能,去网上查了一下资料,总结了一下iOS中截屏相关的知识,然后自己做了个demo。
demo主要实现了3种截屏方法,分别对应三种不同的应用场景。
1、imageView截图,这个截图方法可以用来实现截取项目中的控件,可截取的控件可包括UIImageView、UIView等。截图方法如下:

-(UIImage *)screenshotsWithView:(UIView *)view{
    
    UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

2、MP4格式的视频流截图,即获取MP4格式视频流中的某一帧。截取方法如下:

-(UIImage *)screenshotsMP4WithCurrentTime:(CMTime)currentTime videoUrl:(NSString *)url{
    
    AVURLAsset * asset = [[AVURLAsset alloc] initWithURL:[NSURL URLWithString:url] options:nil];
    AVAssetImageGenerator * gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    gen.appliesPreferredTrackTransform = YES;
    gen.requestedTimeToleranceAfter = kCMTimeZero;
    gen.requestedTimeToleranceBefore = kCMTimeZero;
    CMTime time = CMTimeMakeWithSeconds(CMTimeGetSeconds(currentTime), 600);
    NSError * error = nil;
    CMTime actualTime;
    CGImageRef imageRef = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
    UIImage * image = [[UIImage alloc] initWithCGImage:imageRef];
    return image;
}

这个方法是不是仅限于MP4格式的视频我不是很清楚,但是可以确定的是,MP4截取某一帧的方法不适用于m3u8格式的视频流。
3、m3u8格式视频流截图。方法如下:

-(UIImage *)screenshotsm3u8WithCurrentTime:(CMTime)currentTime playerItemVideoOutput:(AVPlayerItemVideoOutput *)output{
    
    CVPixelBufferRef pixelBuffer = [output copyPixelBufferForItemTime: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))];
    UIImage *frameImg = [UIImage imageWithCGImage:videoImage];
    CGImageRelease(videoImage);
    CVBufferRelease(pixelBuffer);
    return frameImg;
}

需要特别指出来的那两个release方法,不调用的话会造成内存泄漏(可用Instruments调试)。
另外还有一点需要注意,m3u8格式的视频流在截取时需要传入一个AVPlayerItemVideoOutput对象,这个对象一定要在AVPlayerItem初始化的时候设置好,如果以临时变量的形式传入或导致截取失败。
在截屏事件里直接调用以上方法即可获取到截取的image。demo链接地址:https://github.com/zhanqin/screenshots

上一篇:linux入门系列6--软件管理之rpm和yum仓库


下一篇:在Linux环境下mysql的root密码忘记解决方法