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

回顾

之前解析介绍的是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时用于输入流是实时的,比如说摄像头。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏牛客网

C++后台实习面经 - 腾讯WXG

拿到题目之后没有任何思考,想用中序遍历然后把遍历结果放到一个容量为k的队列中(基本操作)。但是为什么顺手就写下vector???面试官看见我这么快下笔之后看了看...

1874
来自专栏何俊林

性能比肩美拍秒拍的Android视频录制编辑特效解决方案

众所周知,Android平台开发分为Java层和C++层,即Android SDK和Android NDK。常规产品功能只需要涉及到Java层即可,除非特殊需要...

2461
来自专栏云飞学编程

Python爬虫的简单实现!用python爬虫自己做天气预报查询

最近小编在学习爬虫,就想找个东西练练手,小说、图片、音乐什么的都烂大街了,正好最近天气是越来越冷,小编窝家里自己敲了个天气简单查询的代码,请大家指正下!

1191
来自专栏Ceph对象存储方案

对象存储基础概念

对象存储诞生之初 谈到为什么要有对象存储,必须聊聊对象存储诞生之前的两大存储模型:块存储和文件存储。 块存储主要是将存储介质的空间整个映射给主机使用的,主机如果...

6384
来自专栏Python爬虫与算法进阶

【萌新写爬虫】爬知乎关注信息

这个例子是【爬虫工程师课程】中的一个实战,这里简单介绍下。 记得以前说过,爬虫有三步:获取源码、解析源码、储存数据。首先看看知乎的数据在哪里。 一、分析网页请求...

3565
来自专栏linxu shell指南

软件构件、中间件、面向对象

    1、构件定义:组(构)件是软件系统可替换的、物理的组成部分,它封装了实现体(实现某个职能)并提供了一组接口的实现方法。可以认为组件是一个封装的代码模块或...

2684
来自专栏java达人

Java 理论与实践: JDK 5.0 中更灵活、更具可伸缩性的锁定机制

多线程和并发性并不是什么新内容,但是Java 语言设计中的创新之一就是,它是第一个直接把跨平台线程模型和正规的内存模型集成到语言中的主流语言。核心类库包含一个T...

2026
来自专栏Golang语言社区

从Baa开发中总结Go语言性能渐进优化

在Go生态已经有很多WEB框架,但感觉没有一个符合我们的想法,我们想要一个简洁高效的核心框架,提供路由,context,中间件和依赖注入,而且拒绝使用正则和反射...

5658
来自专栏玩转全栈

flutter使用platform-channels制作插件

一、flutter使用platform-channels制作插件是否是一种完美的体验?

4914
来自专栏杨建荣的学习笔记

浅谈pl/sql (r3笔记第14天)

关于pl/sql,可能大家熟悉而又陌生,熟悉是因为大家在工作中老是写sql,如果稍微改动一些,加入begin,end和控制结构,就是pl/sql了。:) 今...

3579

扫码关注云+社区

领取腾讯云代金券