美文网首页视频知识
用GPUImage处理视频水印

用GPUImage处理视频水印

作者: wo不懂 | 来源:发表于2017-05-03 20:12 被阅读916次

    简介:视频水印处理效果相关的总结,其中参考了@落影loyinglin 的水印处理的文章,自己也相对的做了一些修改和总结希望将相关的经验分享给大家

    一:主要思路

    1、UIView上面有UILabel(文字水印)和UIImageView(图片水印),再通过GPUImageUIElement把UIView对象转换成纹理对象,进入响应链;

    2、视频文件的图像数据通过GPUImageMovie进入响应链;

    3、GPUImageDissolveBlenderFilter合并水印图像和视频,把数据传给响应链的终点GPUImageView以显示到UI和GPUImageMovieWriter以写入临时文件;

    4、视频文件的音频数据通过GPUImageMovie传给GPUImageMovieWriter以写入临时文件;

    5、最后临时文件通过ALAssetsLibrary写入系统库。

    具体细节

    1、GPUImageUIElement

    GPUImageUIElement继承GPUImageOutput类,作为响应链的源头。通过CoreGraphics把UIView渲染到图像,并通过glTexImage2D绑定到outputFramebuffer指定的纹理,最后通知targets纹理就绪。

    2、GPUImageOutput和GPUImageFilter

    本次demo主要用到了frameProcessingCompletionBlock属性,当GPUImageFilter渲染完纹理后,会调用frameProcessingCompletionBlock回调。

    3、响应链解析

    1、当GPUImageMovie的纹理就绪时,会通知GPUImageFilter处理图像;

    2、GPUImageFilter会调用frameProcessingCompletionBlock回调;

    3、GPUImageUIElement在回调中渲染图像,纹理就绪后通知

    GPUImageDissolveBlendFilter;

    4、frameProcessingCompletionBlock回调结束后,通知

    GPUImageDissolveBlendFilter纹理就绪;

    5、GPUImageDissolveBlendFilter收到两个纹理后开始渲染,纹理就绪后通知GPUImageMovieWriter;

    如图:相关流程请看下图,总结的下图的是:@落影loyinglin,我个人觉得很好很清楚

    下面我自己写的相关的一些知识的实现

    GPUImageView *gpuImageView = (GPUImageView*)self.view;

    GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];

    videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;

    _videoCamera = videoCamera;

    //添加时间戳水印和图片水印

    UIView *contentView = [[UIView alloc] initWithFrame:self.view.bounds];

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

    [formatter setDateFormat:@"yyyy年MM月dd日hh:mm:ss"];

    NSDate *currentDate = [NSDate date];

    NSString *timeString = [formatter stringFromDate:currentDate];

    UILabel *timestampLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 300, 30)];

    timestampLabel.text = timeString;

    timestampLabel.textColor = [UIColor redColor];

    [contentView addSubview:timestampLabel];

    UIImageView *imageV = [[UIImageView alloc] initWithFrame:CGRectMake(10, 100, 300, 80)];

    [contentView addSubview:imageV];

    //创建水印图形

    GPUImageUIElement *uiElement = [[GPUImageUIElement alloc] initWithView:contentView];

    //创建滤镜

    GPUImageDissolveBlendFilter *filter = [[GPUImageDissolveBlendFilter alloc] init];

    filter.mix = 0.5;

    GPUImageFilter *videoFilter = [[GPUImageFilter alloc] init];

    [videoCamera addTarget:videoFilter];

    [videoFilter addTarget:filter];

    [uiElement addTarget:filter];

    // 添加滤镜

    [filter addTarget:gpuImageView];

    [videoCamera startCameraCapture];

    //下面的回调必须写不然不会更新

    __unsafe_unretained GPUImageUIElement *weakOverlay = uielement;

    [videoFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {

    [weakOverlay update];

    }];(这句代码总是不断的调用很影响性能,通过查找资料修改如下

    __unsafe_unretained GPUImageUIElement *weakOverlay = uielement;

    [filter disableSecondFrameCheck];//这样只是在需要更新水印的时候检查更新就不会调用很多次

    runAsynchronouslyOnVideoProcessingQueue(^{

    [weakOverlay update];

    });

    当然这样写因为GPUImage框架也有些不完善的地方调用update会崩溃,解决办法见:https://github.com/BradLarson/GPUImage/issues/2211

    同时如果你觉得水印不够清晰你可以修改着色的语言,重写着色算法

    重写blend的着色语言如下:

    NSString *const kGPUImageDissolveBlendFragmentShaderString = SHADER_STRING

    (

    uniform sampler2D inputImageTexture;

    uniform sampler2D inputImageTexture2;

    uniform mediump int type;

    // varying highp vec2 anyTexCoord;

    varying highp vec2 textureCoordinate;

    void main ()

    {

    mediump float alpha =texture2D(inputImageTexture2, textureCoordinate).a;

    mediump vec4 base = texture2D(inputImageTexture2,textureCoordinate);

    mediump vec4 overlay = texture2D(inputImageTexture, textureCoordinate);

    mediump float r = base.r*alpha + overlay.r*(1.0 - alpha);

    mediump float g = base.g*alpha + overlay.g*(1.0 - alpha);

    mediump float b = base.b*alpha + overlay.b*(1.0 - alpha);

    mediump float a =0.1;

    gl_FragColor = vec4(r, g, b,a);

    }

    );

    大家可以比较选择,选择合适自己的方法,这块我也在不断的学习,希望大家一起努力,共同进步,有什么好的方法和思路可以告诉我,我虚心学习

    相关文章

      网友评论

      • 白水灬煮一切:runAsynchronouslyOnVideoProcessingQueue(^{

        [weakOverlay update];

        });这里会崩溃,楼主给的链接没有看懂!请问这里这么处理????
        wo不懂:__unsafe_unretained GPUImageUIElement *weakOverlay = uielement;

        [videoFilter setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {

        [weakOverlay update];

        }]; 那使用这个更新看会不会崩溃,具体崩溃原因,你需要查下
      • 古子林:楼主你前面的文章讲了一堆的 GPUImageMovie 和 GPUImageMovieWriter 的,结果代码中根本就没用到:sweat: 不知这两者结合起来要怎么实现呢?用 GPUImageVideoCamera 我也实现了,我们现在的需求是从本地读取一段视频,然后把视频加上水印,再保存到本地;我用 GPUImageMovie 和 GPUImageMovieWriter 结合总是有问题。
        古子林:@心痛的独白 用 GPUImageAlphaBlendFilter 这个类。 https://www.jianshu.com/p/91bafff116be
        心痛的独白:楼主,添加的水印模糊还有没有什么解决办法 ,上面的方法不行啊
        wo不懂:首先谢谢你提出疑问,基本原理那个图很清楚了,把本地视频路径放到GPUImageMovie里把视频图像和音频分开处理 把每一帧图像做一些处理 后需要GPUImageMovieWriter重新组合写入,这样说可能不专业但是你应该能明白, GPUImageVideoCamera 采集加水印处理完了,用苹果API保存本地也可以,但是内存很吃紧,因为我们需要加些滤镜效果,我直接结合项目总结这篇,根据具体的需求挑选关键的知识学习就好
      • 剑子仙迹:求一个demo 谢谢
        wo不懂:@朴树恒阳 那个代码就可以了,我直接在项目里面做的

      本文标题:用GPUImage处理视频水印

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