您现在的位置是:首页 > 文章详情

淘拍-视频云剪辑,我们这样做

日期:2018-07-08点击:403

一、前言

首先说说视频剪辑,视频剪辑其实是一个跨终端、跨多个知识栈的横向领域。任何平台任何语言下,只要有足够的计算能力,应该都可以进行视频剪辑。也相信看完这篇文章后,你对于视频的剪辑不会再感觉陌生。

传统的桌面剪辑软件是提供一个GUI界面,给用户提供所见既所得的编辑效果反馈,并在编辑完成之后产生编辑描述数据,最后交由图形图像模块、音频处理模块以及视频编码模块去生成最终视频文件。

参考大部分开源剪辑软件实现,前半部分GUI大部分通过操作系统图形界面或跨平台如QT、SDL、SWT方式实现,这部分我们称之为“前端”。而后面涉及图形图像、音频、编码相关部分,大部分都会有一套媒体编辑内核来支撑,例如Linux下著名的MLT、GStreamer等等,这里我们称之为“编辑内核”。

云剪辑,其实是剪辑端的一种,这里GUI“前端”需要通过浏览器呈现给用户,而“编辑内核”完全可以复用传统的媒体编辑框架。只是在云编辑场景下,“编辑内核”的计算能力是多用户共用,因此需要解决好资源调度问题即可。在Zookeeper、MQ流行的今天,这些调度问题在Java工程师眼里也都不是问题了。

那么云编辑需要解决以下几个问题:

  • 可以描述的渲染效果
  • 效果与时间的绑定(非线性)
  • 处理逻辑跨平台
  • 解决Javascript弱计算能力

二、技术选型

视频编辑最核心的3个步骤:1、将媒体文件从视频素材解码出来,2、对解码出来的每帧图片和音频进行处理,3、将处理之后的内容在GUI上展示,或传递给编码器。

在以上 GUI + 编辑内核 的思路之下,看似方案已经很明确,只是这里我们需要确定几件事情。例如GUI如何呈现编辑内核的内容。

我们也看到行业内一些做法:

  • 编辑内核放在云端,通过直播的串流方式推给用户界面
  • 编辑内核放在云端,前端GUI只提供少量信息给用户

而以上两种方式都存在一些缺陷,例如第一个的延时问题,第二个的缺失所见即所得问题。而整体看Web端侧,基于WebGL、Video Element、Blob、Web Audio、Web worker、Webassembly一系列令人激动的能力,Web已经有了长足的进步。对于在Web侧实现一套编辑内核看起来似乎已经有理论依据。

因此我们确定了一个方向:编辑内核的复用可以共用设计,而不一定追求共用代码。我们先不分平台,设计出内核架构,再看是否可以多平台轻量实现

1、管道

回顾上文提到的三个步骤:1、将媒体文件从视频素材解码出来,2、对解码出来的每帧图片和音频进行处理,3、将处理之后的内容在GUI上展示,或传递给编码器。同时考虑到这里的媒体解码除了是通过视频文件,也可以是摄像头采集,或通过类似OpenGL这样的图像库渲染出来的,因此可以把这3个环节抽象出3个核心组件:Producer、Filter、Consumer

+-------+ +-------+ +-------+ | | | | |Encoder| |Decoder|-->|Process|-->| | | | | | | GUI | +-------+ +-------+ +-------+ ^ ^ ^ Producer Filter Consumer

当Producer和Consumer中存在多个Filter的时候,管道也就产生了

+--------+ +-------+ +-------+ +--------+ |Producer|-->|Filter1|-->|Filter2|-->|Consumer| +--------+ +-------+ +-------+ +--------+

这里也涉及管道是Producer推,还是Consumer拉。最终我们选择了Consumer拉的模式,至于原因主要考虑资源利用,因为最终有价值的内容是通过Consumer产出,而底下的Producer无法感知上面的逻辑。

2、裁剪、合并

表达裁剪和合并比较容易,对于一段视频会有一个总帧数,而裁剪其实只需记录其开始(in)和结束(out)的时间点即可

+---+-----------------+---+ | x | a | x | +---+-----------------+---+ ^ ^ in out

对于合并,更加简单,记录的多段视频的出现顺序即可,为了表示这种排列数据,新建一个模型PlayList

+-------+---+-------------+ |a | b |c | +-------+---+-------------+

而剪和合都可以抽象的作为一个Producer

3、滤镜

滤镜主要是对内容的处理节点,他所处理的位置在Producer和Consumer中间,他是剪辑中重要的一环。这里核心需要实现的是:如何实现一套统一的处理逻辑,在多个端上可以完全重现

+--------+ +------+ +--------+ |Producer|-->|Filter|-->|Consumer| +--------+ +------+ +--------+

这里我们选择了专业的图像处理框架OpenGL系,OpenGL、OpenGL ES、WebGL之间的关系如下:

15272191923347.jpg

如果要实现统一与平台无关的渲染逻辑,我们需要使用可编程着色器(GLSL),同时考虑多端兼容性,我们选取了OpenGL 2.0 -> OpenGL ES 2.0 -> WebGL 1.0 这条线作为我们的能力集。

4、过渡

过渡的效果设计一个视频画面慢慢转化到另一个视频画面,这里就涉及在中间某个时间内,其实有两个视频源。因此需要正式引入多轨道 Multitrack。和Playlist一样Multitrack也是Producer的一种实现。

 +--------------------+ +-----------------------+ 0: |a1 | |a2 | +---------------+----+------------------+------+----------------+ 1: |b1 | +------------------------------+

轨道可以理解为图片的图层,真实的输出是a1的画面完全叠加在b1之上。当a1没有透明度的情况下,b1在a1结束前是不可见的。

la_01.png

也许这里感觉到多轨道并不能实现过渡效果。因为这里却少了一环,图片混合。

+----------+ |multitrack| | +------+ | +-------------+ +-------+ | |track0|-|--->| |--->|tractor| | +------+ | | | |\ | | | | transitions | | \ | | +------+ | | | | \ | | |track1|-|--->| |--->|---o---|---> | +------+ | +-------------+ | / | | | | / | | +------+ | |/ | | |track2|-|---------------------->| | | +------+ | +-------+ +----------+

这里的transitions和滤镜非常类似,通用可以通过GLSL来实现效果的跨平台性,只是滤镜只需要一个纹理输入,而过渡需要两个纹理。同时,过渡是一个时序相关的动作,因此需要有一个时间变量传入,例如过渡开始为0,而过渡结束为1,过渡过程在0-1之间进行。

 +--------------------+ +-----------------------+ 0: |a1 | |a2 | +---------------+----+------------------+------+----------------+ 1: |b1 | +------------------------------+ ^ ^ ^ ^ 0 1 0 1

5、动画

计算机往往是看起来像什么,而不是是什么。实现动画其实可以参考CSS transition和iOS Core Animation的思路。即记录开始时间和结束时间,物体所在的位置。那么在开始时间和结束时间可以通过算法计算出当前位置。当窗口快速刷新时,看起来物体就进行了移动。

7.4.jpeg

把相同原理应用与大小上,即实现了变大缩少动画,应用于角度上,即实现了旋转。当然这里只有线性变化是通用公示,当非线性动画场景下,如何实现多平台统一呢?答案是给出计算公式,我们使用了开源公式集,包括了easeIn、easeOut、easeInOut等等。

15272572507353.jpg

有了以上计算公式,提供开始时间、结束时间、开始状态值、结束时间值,在时间轴内任意一点可计算出当前值,这样既实现了完全平台无关。

6、平台实现

到此,基本设计方案都以完成。这里就给各个组件寻找实现方式即可。

  • Producer:浏览器可以通过Video Element实现,Linux通过FFmpeg的解码函数实现
  • Consumer:浏览器是提供给用户预览,因此通过Canvas实现,并通过requestAnimationFrame拉取,Linux端负责生成视频,因此使用FFmpeg的编码器实现
  • 滤镜、过渡:基于OpenGL体系,通过GLSL实现,浏览器侧WebGL、Linux侧OpenGL
  • 动画:基于描述语言,浏览器侧通过基于WebGL的pixi.js图像库实现,服务器侧通过QTWebkit内执行pixi.js图像库实现

7、Javascript弱计算能力

计算能力其实也可以作为平台特性放到上一节,但这块最为复杂,单独拿出来。

在一些场景下,例如视频的去抖,大部分的去抖算法,需要首先寻找视频中特征点,之后通过OpticFlow算法寻找运动轨迹,之后再通过前后帧数据寻找纠正矩阵,最后进行修正。

这里第一需要大量的CPU计算,第二去抖算法往往由算法团队通过C的动态库或静态库提供。理论上在共用设计的思路下,只要算法确定,可以用JS把算法再实现一次。但是令人遗憾的是JavaScript计算能力太弱,无法满足实时预览。

这里我们使用了Webassembly,在算法团队提供的C++实现上,在进行一轮包装,主要完成JS内图片数据向C数组拷贝和处理结果矩阵的回传工作,之后抖动纠正交由WebGL的纹理+变换矩阵来处理。

dfe205770c7b537d073544330134043a.png

三、工程化

当所有和视频处理相关的问题都解决的时候,这件事其实已经成了,下面回到我们这些应用工程师的老本行——搭系统、建立模型、链流程。

整体模型主要是Producer、Filter、Transition三个接口,以及他们的若干实现。

15272590331705.jpg

视频生成构建3个应用,其中Editor作为淘拍PC的业务应用,对接前台编辑器。Biz对外提供统一视频制作能力整体方案,包括调度、生成、上传、发布。而Core应用作为底层生产单元。可以完成非淘系视频制作任务。

5E66A996-8787-4FD5-9981-CECE68B89EEF.png

其中Core会JNI调用到媒体框架,依赖ffmpeg、x264、OpenGL、QTWebkit、SOX等,我们将环境打包到Docker里,部署在双显卡的物理机上。并通过Nvidia提供的Docker插件能直接调用到显卡。

15272592242078.jpg

前端SDK的部分因为还未对外开放,这里就不展开。

四、最优解

行之有效方案的方案就是好方案。但回头反思,他是最优方案吗?可能是、也可能不是。对于当前项目周期和业务目标看他是一个有前提的最优解。但全面来说他还有缺点,这里的跨平台是通过一套描述数据+共用GLSL+共用设计的方式实现。

而全量代码的跨平台应用是否可行呢?比较难,但至少也还是有理论依据。例如,SDL(Simple DirectMedia Layer)内置了与OpenGL的连通,并具备音频处理能力。SDL可以直接跨平台的跑在iOS、Android以及云端编辑后台。而Emscripten编译工具内置了SDL的API实现,将OpenGL映射到WebGL,将音频处理映射到Web Audio,可以完整编译SDL项目到Web端。可能最终的终局是可以实现一份代码,4个端上执行。

但目前看来,该项实现的前期投入成本会非常大。目前我们仅做了少量Demo论证可行性,暂时没有计划实施。

五、最后

最后,我们的云编辑平台,首先落在淘拍-电脑版产品中,主要面向商家生产主图视频、包括上面提到的裁剪、合并、滤镜、过渡、字幕、防抖等。其实云编辑的场景不止于此,非常适合制作素材均在云上,只需进行轻量化编辑的场景。

原文链接:https://yq.aliyun.com/articles/608685
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章