美文网首页iOS开发部落生活iOS
GPUImage详细解析(六)-用视频做视频水印

GPUImage详细解析(六)-用视频做视频水印

作者: 落影loyinglin | 来源:发表于2016-06-17 10:55 被阅读9557次

    回顾

    之前解析介绍的是GPUImage源码解析、图片模糊、视频滤镜,明白了GPUImage的强大功能,这次介绍的是两个视频的重叠,可以把两个视频文件合并,也可以把视频和录像结合在一起。

    效果展示

    视频的截图如下,视频由两个视频合成,一个来自于文件abc.mp4,一个来自于摄像头。


    核心思路

    摄像头采集的数据通过GPUImageVideoCamera进入响应链,视频文件的数据通过GPUImageMovie进入响应链,在GPUImageDissolveBlenderFilter进行合并,最后把数据传给响应链的终点GPUImageView以显示到UI和GPUImageMovieWriter以写入临时文件,最后临时文件通过ALAssetsLibrary写入系统库。


    具体细节

    1、GPUImageDissolveBlendFilter

    GPUImageDissolveBlendFilter类继承GPUImageTwoInputFilter,添加属性mix作为片元着色器的mix参数。GPUImageDissolveBlendFilter在响应链上需要接受两个输入,当两个输入都就绪时,会通过mix()操作把输入混合,并且输出到响应链上。

    思考1:如果只有一个输入会如何?

    2、GPUImageMovie

    GPUImageMovie类继承了GPUImageOutput类,一般作为响应链的源头,可以通过url、playerItem、asset初始化。

    3、GPUImageMovieWriter

    GPUImageMovieWriter类实现GPUImageInput协议,一般作为响应链的终点。shouldPassthroughAudio表示是否使用源音源。
    movieFile.audioEncodingTarget = movieWriter;表示音频来源是文件。

    if (audioFromFile) {
            // 响应链
            [movieFile addTarget:filter];
            [videoCamera addTarget:filter];
            movieWriter.shouldPassthroughAudio = YES;
            movieFile.audioEncodingTarget = movieWriter;
            [movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
        }
        else {
            // 响应链
            [videoCamera addTarget:filter];
            [movieFile addTarget:filter];
            movieWriter.shouldPassthroughAudio = NO;
            videoCamera.audioEncodingTarget = movieWriter;
            movieWriter.encodingLiveVideo = NO;
        }
    

    思考2:音频来源的不同会对响应链造成什么样的影响?为什么?

    4、响应链
    响应链以GPUImageVideoCamera和GPUImageMovie作为输入,最终以GPUImageMovieWriter为输出。

    • 开始响应链的输入。
        [videoCamera startCameraCapture];
        [movieWriter startRecording];
        [movieFile startProcessing];
    
    • 设置movieWriter的结束回调。
    [movieWriter setCompletionBlock:^{
    }];
    

    思考3:movieWriter的回调是什么时候调用的?由哪里触发?

    思考4:movieWriter的encodingLiveVideo有什么用?把其设置为YES和NO试试,观察是否有影响?

    总结

    做demo的过程中遇到坑,GPUImage上面有Issues,但是并没有人解答ʕ̡̢̡ʘ̅͟͜͡ʘ̲̅ʔ̢̡̢。
    代码地址在这里,参考链接上有趟坑的时候查到的一些资料。

    附录

    几个思考题都是做demo过程比较迷惑不解的地方和遇到的问题,答案分别是:

    思考1:输入只有一个输入的时候,会一直等待第二个输入,不会有输出。问题出现在把videoCamera声明为临时变量,以为添加target会持有videoCamera的引用。实际上就会发生输入只有一个的时候(只有视频文件的信号),同时屏幕是白屏。

    思考2:音频的来源不同会导致CMTime的不同,响应链视频信息的CMTime默认采用第一个输入的CMTime,故而修改音频来源的时候需要修改响应链的输入顺序,否则几秒钟的视频文件会产生两个多小时的文件(CMTime不同步导致)。

    思考3:movieWriter的回调会在视频处理结束的时候调用,由GPUImageMovie的
    reader.status == AVAssetReaderStatusCompleted触发。

    思考4:encodingLiveVideo影响的其实是expectsMediaDataInRealTime属性,YES时用于输入流是实时的,比如说摄像头。

    相关文章

      网友评论

      • shengshenger:大神,请问下,从摄像头获取的数据经过GPUImage美颜等的处理后,输入的数据是yuv420格式还是BGRA格式?
        落影loyinglin:@shengshenger 是的
        shengshenger:@落影loyinglin 额,不好意思,打错了,是输出的数据格式
        落影loyinglin:@shengshenger 看设置
      • be8758f3f131:我打开git连接没有demo 的下载 按钮啊 很奇葩。
      • MrOrz:还有一个问题,我用GPUImageMovie这个类播放视频,发现播放的速度比原视频播放的速度慢,而且我也设置了_gpuMovie.playAtActualSpeed = YES;请问这是什么原因造成的
      • MrOrz:你好,我想请问下,我用GPUImageMovieWriter将滤镜合成好的视频写入到沙盒中,发现滤镜合成好的视频总时长比原视频总时长少了2到3秒,这是为什么?
      • bc049a7130d1:楼主你好,我在用GPUImage处理视频时遇到内存警告,请问楼主遇到过吗?怎么处理?
        落影loyinglin:@遥望彼岸花 看看哪里有内存泄露
      • littleDad:这个demo cpu 超100% 在6s真机debug模式下
      • babystyles: 我这边添加两个视频轨道一个背景视频和一个下雪的视频(背景为黑色) 到 同一个 AVMutableComponation中来进行两个视频的叠加,但是合成出来,背景视频被挡住了,看不到背景视频内容,想问下有没有什么办法能把下雪的视频背景变成透明的,楼主的这个是不是可以实现这种效果
        babystyles:@落影loyinglin 您说的是在制作那个下雪视频的时候 设置alpha值=0,是吧 ?那我想在问下能不能用代码实现修改视频的背景颜色 变成透明。
        落影loyinglin:@这一翅蓝瘦香菇 你把下雪的视频的黑色改成alpha值=0,shader中改
      • 2df6b75e5bec:楼主大神,最近在做视频这块,如果想要在录制了一段时间之后再添加视频水印,这个要怎么处理?
        落影loyinglin:@无可替代_21a1 根据cmtime判断水印添加时间
      • 陈_某_某:林大神,有个问题要请教下。有个类似微信朋友圈拍摄视频的需求,用GPUImageMovieWriter写入,二次录制的之后GPUImageMovieWriter对象要重新初始化吗,不初始化有个闪退的问题,初始化重复录制16次之后会出现奇诡的卡顿,应用退到后台,打开系统相机,系统相机黑屏。。。杀掉进程,系统相机就好了。。。
      • Zszen:思考4:encodingLiveVideo影响的其实是expectsMediaDataInRealTime属性,YES时用于输入流是实时的,比如说摄像头。 设置成No, 可以高速处理视频效果, 用于非实时预览的视频快速处理
      • Zszen:多输入filter如果少设置纹理, 应该会崩
      • Zszen:请问下最方便的视频合成类AVMutableComponation 用来合成视频, 为什么不能创建多个视频轨道, 而创建多个音频轨道没问题, 视频轨道创建多个, 即便上层轨道设置了透明, 下层也还是会被一片黑覆盖, 而有效的办法只能创建一个视频轨道, 然后把视频安插在不同的位置上, 插入新视频的时候, 还要把同样长度的原有时间轴删掉, 否则会增加视频时间长度, 为此这个你怎么看
        Zszen:@这一翅蓝瘦香菇 使用蒙板,具体什么蒙板什么参数自己查
        babystyles:我也是添加两个视频轨道一个背景视频和一个下雪的视频(背景为黑色) 到 同一个 AVMutableComponation中来进行两个视频的叠加,但是合成出来,背景视频被挡住了,看不到背景视频内容,想问下能不能把下雪的视频背景变成透明的,楼主的这个是不是可以实现这种效果
        落影loyinglin:@Zszen 视频的拼接,可以通过指令设置。但是视频的覆盖,涉及到的参数较多,位置,透明度等。
      • 5a7c2642d9ee:你好,请问有遇到startRecording时FPS降低很多的情况吗,如果有请问如何解决呢
      • kevinlishuai:我对视频文件添加滤镜后,GPUImageMovieWriter 写入的文件大小为0, 请问是什么问题?
        心痛的独白:GPUImageMovieWriter 竖屏拍摄的视频为什么旋转了90度,横屏拍摄是好的
        Zszen:GPUImageMovieWriter是不是初始化没设置大小
        落影loyinglin:@kevinlishuai 看看是否add target 和 start
      • akali:我用2个视频做输入源,真机测是没问题的,但是用模拟器就有问题,为什么?
        当2个视频长度不同时,怎么才能得到的视频是跟较长的相同,让短的哪个重复去做,现在是得到的视频是2个中短的哪个时间
        2df6b75e5bec:@落影loyinglin 好的,感谢!
        落影loyinglin:@无可替代_21a1 可以看看最新的opengl篇的视频混合,插入不同的视频轨道可以解决
        2df6b75e5bec:你好,请问你这个问题是怎么解决的呢?
      • 倪灏:博主,你好,我现在是在做短视频处理,我们是先获得摄像头的内容,然后合成到视频上,我们现在遇到的问题是,内存占用过高,动不动就内存爆满崩溃.我们的处理方式如下,不知道你没有什么好的解决方案,或者想法
        这个过程是实时的,使用的是在摄像头的回调中,获得每一帧的图片,然后在 progressFilter 的setFrameProcessingCompletionBlock 将图片合成到视频上.
        落影loyinglin:@倪灏 你视频读取的速度是按时间来的吗?怀疑卡死,你可以debug看看CPU占用。
        倪灏:@落影loyinglin 恩,我现在把内存降低下来了,是我处理内存的时机不对,但是我又遇到一个问题,就是偶然的情况下,我把摄像头的内容合成到视频上,在合成的视频上,发现摄像头的内容卡在了中间的某一个地方不动了.比如:一个10秒的视频,在合成的视频的5秒的地方开始向后,摄像头的内容就不在变化了,卡死了,我感觉是 GPUImage 的线程被卡死了,就没有再执行setFrameProcessingCompletionBlock方法里的内容,你感觉呢?
        落影loyinglin:@倪灏 这个方式是没有问题的。我建议你查查内存过多的问题,GPUImage并不吃太多内存。
      • 一__谷__作气:您好,您这个demo,加水印,原本的视频的方向变换了,向左旋转90度,这个有办法处理么?
        美美的朵朵:AVAsset *asset = [AVAsset assetWithURL:url];

        AVAssetTrack *videoAssetTrack = [asset tracksWithMediaType:AVMediaTypeVideo].lastObject;
        CGAffineTransform videoTransform = videoAssetTrack.preferredTransform;
        通过videoTransform判断方向 然后GPUImageView调用setInputRotation
      • 倪灏:博主,你好,我想问一下,我想将录制的视频做为原有视频的一个画中画,我想实时的修改录制视频在原有视频中的位置,请问有没有什么好的想法?谢谢 O(∩_∩)O
        倪灏:@落影loyinglin 恩,我自己也做了尝试,在setFrameProcessingCompletionBlock 的回调方法中的 Buffer 已经是两个视频合成之后的 Buffer 了.
        倪灏:@落影loyinglin 谢谢你的回答,你说改变 View 的坐标,改变的是那个 View 的坐标呀?平移矩阵我是直接对 SampleBuffer 做处理吗?还是自定义一个 Filter?
        落影loyinglin:@倪灏 方法很多,可以改变view 的坐标,也可以添加平移矩阵等
      • 米兔小书童:博主,看你的demo录制完成后,原视频的声音丢失了,请问是什么原因,有解决办法吗
        落影loyinglin:@米兔小书童 audiotarget要设置
        米兔小书童:@米兔小书童 我尝试GPUImageMovie—>GPUImageView,只播放视频也是没有声音的
      • cb4eb2184b03:博主,如果水印是25张的序列帧图片,怎么做比较好
        落影loyinglin:@cb4eb2184b03 可以先读取视频长度。分成25份,长度到了就换一张图片水印
      • cb4eb2184b03:还想问博主一个问题,如果是两个视频可以吗?一个视频作为另外一个视频的水印
        落影loyinglin:@cb4eb2184b03 我这边真机测试还行。
        cb4eb2184b03:@落影loyinglin 视频水印感觉消耗内存很大啊
        落影loyinglin:@cb4eb2184b03 可以的,这个demo就是
      • cb4eb2184b03:对视频做水印很感兴趣,下载的demo有错误, /usr/local/bin/appledoc: No such file or directory 不知道是怎么回事,楼主可以帮我解答吗?
        WSGNSLog:@stevenChan007 亲,appledoc这个东西怎么搞啊,有参考链接么
        吴霸格07:@cb4eb2184b03 找到解决方法了,下载安装appledoc就可以了,请采纳
        吴霸格07:@cb4eb2184b03 我也是啊,找到解决方法了吗?

      本文标题:GPUImage详细解析(六)-用视频做视频水印

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