美文网首页iOS知识收录短视频AVPlayer和GPUImagede学习
GPUImage详细解析(五)滤镜视频录制

GPUImage详细解析(五)滤镜视频录制

作者: 落影loyinglin | 来源:发表于2016-06-14 14:08 被阅读7492次

回顾

GPUImage的基础在详细解析1~4
这次的介绍是录制视频添加滤镜保存到手机

核心思路

通过GPUImageVideoCamera采集视频和音频的信息,音频信息直接发送给GPUImageMovieWriter;视频信息传入响应链作为源头,渲染后的视频信息再写入GPUImageMovieWriter,同时通过GPUImageView显示在屏幕上。


具体细节

1、AV类

AVCaptureSession                *_captureSession;   协调AV输入设备到AVoutput的数据流
AVCaptureDevice                 *_inputCamera;      摄像头设备
AVCaptureDevice                 *_microphone;       麦克风设备
AVCaptureDeviceInput            *videoInput;        摄像头输入
AVCaptureVideoDataOutput        *videoOutput;       摄像头输出
AVCaptureDeviceInput            *audioInput;        麦克风输入
AVCaptureAudioDataOutput        *audioOutput;       麦克风输出
AVAssetWriter                   *assetWriter;       把多媒体数据写入文件的类
AVAssetWriterInput              *assetWriterAudioInput;  音频输入
AVAssetWriterInput              *assetWriterVideoInput;  视频输入
AVAssetWriterInputPixelBufferAdaptor     sh*assetWriterPixelBufferInput; 视频输入适配器

2、流程图

3、流程解析

1、找到物理设备摄像头_inputCamera、麦克风_microphone,创建摄像头输入videoInput和麦克风输入audioInput;
2、设置videoInput和audioInput为_captureSession的输入,同时设置videoOutput和audioOutput为_captureSession的输出,并且设置videoOutput和audioOutput的输出delegate;
3、_captureSession调用startRunning,开始捕获信号;
4、音频数据到达,把数据转发给之前设置的audioEncodingTarget,并通过调用assetWriterAudioInput的appendSampleBuffer方法写入音频数据;
5、视频数据到达,视频数据传入响应链,经过处理后通过assetWriterPixelBufferInput的appendSampleBuffer方法写入视频数据;
6、选择保存后,文件通过ALAssertLibrary写入手机照片库。

4、demo

  • 初始化
  // 摄像头
    _videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];
    _videoCamera.outputImageOrientation = [UIApplication sharedApplication].statusBarOrientation;
    
  // 滤镜
    _filter = [[GPUImageSepiaFilter alloc] init];
    _filterView = [[GPUImageView alloc] initWithFrame:self.view.frame];
    self.view = _filterView;
    
  // 响应链
    [_videoCamera addTarget:_filter];
    [_filter addTarget:_filterView];
    [_videoCamera startCameraCapture];
  • 开始录制
        unlink([pathToMovie UTF8String]); // 如果已经存在文件,AVAssetWriter会有异常,删除旧文件
        _movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.0, 640.0)];
        _movieWriter.encodingLiveVideo = YES;
        [_filter addTarget:_movieWriter];
        _videoCamera.audioEncodingTarget = _movieWriter;
        [_movieWriter startRecording];
  • 结束录制
        [_filter removeTarget:_movieWriter];
        _videoCamera.audioEncodingTarget = nil;
        [_movieWriter finishRecording];

录制后的视频如下:


系统手机库中的视频:


思考

1、在流程图的环节中,哪一步给视频信息添加了滤镜?
2、为何视频的写入类比音频写入类多了一个类?

总结

核心类是GPUImageMovieWriter,协调音频和视频信息的写入。

  • 思考题答案

1、GPUImageVideoCamera把摄像头采集的YUV视频帧,转换为RGB视频帧,同时作为响应链的起始点;GPUImageMovieWriter实现了GPUImageInput协议,可作为响应链的终点,接受滤镜处理过的视频信息。
2、AVAssetWriterInputPixelBufferAdaptor类提供了CVPixelBufferPool用来更快的分配缓存。

相关文章

网友评论

  • Hello_kid:gpuiwage可以直接处理yuv420数据吗
    落影loyinglin:@Ruiz678 你按照420的规则 排列好,放到一个数组就好
    Hello_kid:@落影loyinglin

    static RCDVideoFrameObserver *sharedObserver();
    unsigned int m_width;
    unsigned int m_height;
    unsigned int m_yStride;
    unsigned int m_uStride;
    unsigned int m_vStride;

    unsigned char *m_yBuffer;
    unsigned char *m_uBuffer;
    unsigned char *m_vBuffer;
    这个yuv420格式都这样的。 怎么用gpuimage直接处理,我看评论有人问, 需要转换成rgb格式,再使用gpuimage处理,再转回yuv420格式;
    落影loyinglin:@Ruiz678 可以
  • 0fb0420863cc:请教一下,能否实现设置滤镜的作用区域,比如我想实现半个屏幕是A滤镜 半个屏幕是B滤镜
    0fb0420863cc:@落影loyinglin 忘记补充 是针对视频的滤镜
    0fb0420863cc:@落影loyinglin 我尝试了forceprocessingatsize 但是没有什么效果 能说下如何实现吗
    落影loyinglin:@0fb0420863cc 可以的
  • 千年剑魂:楼主大神,请教个问题:通过滤镜添加实时水印(实时时间)后的实时视频图像数据,怎么获取到处理后的图像数据呢?如果直接是willoutputSampleBuffer回调,出来的数据是没有经过水印处理的。恳请大神提点提点啊:grin:
  • 豆宝的老公:楼主,请问一下,我自己通过代理- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
    采集的音视频数据,然后用GPUImage录视频,并且加了滤镜,我怎么获取到加了滤镜后的CVPixelBufferRef呢?谢谢
  • Zszen:如果想按照显示效果来录制视频, 不能使用
    movieWriter = [[GPUImageMovieWriter alloc]initWithMovieURL:localFile size:_gpuView.sizeInPixels];
    而需要进行16整除运算
    CGSize sizeOutput = CGSizeMake(((int)_gpuView.sizeInPixels.width/16)*16, ((int)_gpuView.sizeInPixels.height/16)*16);
    movieWriter = [[GPUImageMovieWriter alloc]initWithMovieURL:localFile size:sizeOutput];
    否则会有绿边
  • Zszen:为什么单独的把响应链串联(chain)起来会产生频闪, filterGroup和filterPipeline则不会
  • Zszen:unlink([pathToMovie UTF8String]); 和if([[NSFileManager defaultManager]fileExistsAtPath:outputFilePath]){
    [[NSFileManager defaultManager]removeItemAtPath:outputFilePath error:nil];
    } 有什么本质区别么, 一个linux命令, 一个objc函数
  • 5a7c2642d9ee:您好,录制视频时帧率很低,这部分问题可能出在哪呢?
    落影loyinglin:@聪zero 看看cpu 和 gpu的消耗
    聪zero:@汉莎 解决了吗?应该是处理速度跟不上录制速度,丢帧了吧
    汉莎:同问大神
  • Callmewenxi:你好,为什么使用GPUImageMovieWriter录制视频时,这个demo点击录制按钮时,屏幕会闪一下的?我自己之前也写了一个demo,有同样的情况,有解决办法吗?
    Callmewenxi:我擦,我突然找到解决方法了,在初始化GPUImageVideoCamera时添加这个代码就可以了,[m_videoCamera addAudioInputsAndOutputs]; addAudioInputsAndOutputs这个方法里面有解析为什么会导致闪一下
    Callmewenxi:我的那个demo是在官方的demo中SimpleVideoFilter改的,改成可以手动开始录制,然后手动结束录制,也有闪一下的情况...折腾了好些天,没有找到方法解决
  • Sias_Orange:使用前置摄像头录制的时候 录制的视频有噪音 请问博主怎么解决?
  • DSperson:大婶 我将后置摄像头改为前置的时候 左面和右面反过来了 怎么办
    DSperson:@落影loyinglin 您是说给 GPUImageview 做个旋转吗?系统camera 是有transform 的 但是GPUimageVideoCamera 没有
    落影loyinglin:@DSperson 做个镜像
  • 0a7ea1459b80:你还,假设我有两个滤镜要使用,那么应该怎么做呢,我用两个滤镜addtarget-writer,会崩溃,我用滤镜组addtarget-writer,保存的视频就是黑的,请问应该怎么做呢

    0a7ea1459b80:@哈嘿吼 已解决,多谢楼主分享,收货很多
  • 小克码奴001:你好,我在录制的时候是显示正常的,可是在相册中播放的时候视频就被横向拉伸了,怎么解决啊。求大牛帮忙。
    2ac58c3b90fa:@汉莎    你好 请问你的问题解决了吗?我这边遇到类似的问题 以前录制的时候分辨率使用AVCaptureSessionPreset640x480没有问题 但是清晰度不够 换用AVCaptureSessionPreset1280x720后清晰度够了 但是视频失真(横向被拉伸了),请问这种问题应该怎么解决
    视频录制分辨率和输出的视频的宽高之间应该如何控制
    汉莎:@哈嘿吼 可是有的视频有时好的,只有部分视频是有问题的
    0a7ea1459b80:@小克码奴001 wirter初始化的尺寸制定的有问题吧
  • 一__谷__作气:你好,请教一个问题,我用滤镜处理视频,最后得到的视频旋转了,这个该怎么处理?是哪里没有设置?还是什么问题?多谢
    2df6b75e5bec:你好,这个问题解决了吗?我也遇到同样的坑:cold_sweat:
    一__谷__作气:@_iOSer 我就是这么处理的啊
    陈_某_某:Transform不对吧
  • 木子影:你好,我想学习图片处理,进而学习视频的处理,必须要学OpenGL ES 么?我看了你GPUImage的文章,有好多看不懂,需要从OpenGL ES 开始学习么?
    落影loyinglin:@木子影 可以。
    木子影:@落影lying-in 我连OpenGL都没学,我想学习GPUImage 这个框架,先做出效果,忽略掉底层的东西,框架都封装好底层了,想深入了解的话再去学底层,这样可以么,我是iOS新手。
    落影loyinglin:@木子影 图片和视频与OpenGL有关系。但是只学了OpenGL远远不够
  • 开心就好123:谢谢 !
  • 开心就好123:您好! 有个问题比较急,希望能够得到帮助 我在录制视频的时候,保存到相册 如果存放的是.m4v格式没有任何问题 如果存放的是MP4前几帧会显示黑屏 使用AVAssetExportSession 做压缩,压缩完的视频也会有黑屏,有的时候视频后面的内容还会卡主 只有音频 没有视频
    开心就好123:谢谢! 打扰了
    开心就好123:您好不是太明白, self.movieWriter.hasAudioTrack = NO; 的时候没有黑帧 ,我感觉是音频视频不同步,先有了音频之后才有了视频 如何将音频和视频帧的时间统一?
    落影loyinglin:@开心就好123 看看音频和视频帧的时间
  • 北冥风尘:你好,,我录制视频的时候,没有声音,是怎么回事呢
    陈_某_某:@北冥风尘 声音的问题解决了吗
    北冥风尘:@落影loyinglin 这个添加了
    落影loyinglin:@北冥风尘 你看添加了麦克风的录入吗
  • 172429493a55:楼主,请问怎么暂停拍摄和继续拍摄
    落影loyinglin:@13726222894 你看看GPUImageVideoCamera的头文件,写了。
    172429493a55:@落影loyinglin 哪一个??我看了LearnOpenGLESWithGPUImage,这个没有
    落影loyinglin:@13726222894 看看后面的demo
  • 楚简约:问下为什么摄像头显示的正常颜色,录制出来的视频带淡黄的一层,能不能去除显示正常颜色
    落影loyinglin:@楚_简书书_简约 你看看是不是添加了滤镜
  • xiaopaopao:大神,你好,我用GPUImage录制视频,一直出现黑屏问题,这个怎么解决呢,addAudioInputsAndOutputs这个方法也添加了
    4021606a5cc9:请问你解决了GPUImage录制是黑屏的情况了吗?如果已解决请告诉我方法。
    狂奔的兔子:@xiaopaopao 是不是权限没有打开,权限没有打开就是黑屏的
  • jobs_chen:高手,膜拜啊!
    落影loyinglin:@eaefdcc5e51b 谢谢夸奖
  • 熊啊熊啊熊:你好,能问个问题吗?
    我录制视频的时候,开始,结束的时候会卡顿一下,还有,导入相册第一帧是黑屏的 有没有什么可以解决的办法
    落影loyinglin:@听弦不知音 等待视频帧有了再写入音频帧?
    听弦不知音:导入相册第一帧是黑屏的,应该是录制时先写入了音频,在源码里修改视频写入有效后开始录制
    落影loyinglin:@熊啊熊啊熊 代码整理成demo,给个链接我看看
  • 落影loyinglin:不加滤镜的视频录制可以看扩展阅读
    熊大加油:在哪?

本文标题:GPUImage详细解析(五)滤镜视频录制

本文链接:https://www.haomeiwen.com/subject/deoydttx.html