查看原文
其他

仿微信视频拍摄UI, 基于ffmpeg的视频录制编辑

Zhaoss 鸿洋 2019-04-05

本文作者


本文由Zhaoss投稿。

Zhaoss的博客地址:

http://www.jianshu.com/u/f481598cc619


github地址:

https://github.com/Zhaoss/WeiXinRecordedDemo




因为最近项目做了关于视频拍摄和视频处理的需求, 所以特来分享一下, 做了一个基于微信录制,  分析ffmpeg视频编辑的demo, 首先看下使用效果:




功能主要包含5点: 


1.基于ffmpeg的视频拍摄及合成;

2.自定义拍摄按钮, 长按放大并且显示拍摄进度;

3.自定义view, 实现手绘涂鸦;

4.自定义可触摸旋转缩放位移的表情文字view;

5.基于ffmpeg的图片和视频合成处理.


界面风格高仿微信, 只不过微信的编辑处理是作用于图片, 而我们的是基于视频, 所以如果你有需求, 把视频编辑处理换成图片编辑, 更是简单.


1.实现使用ffmpeg录制视频



首先导入lib库和ffmpeg的录制java文件, 我使用的是第三方VCamera封装的ffmpeg, 他没有jar包, 所以需要将con.yixia包下的所有文件都copy过来:


请注意! com.yixia的包名也要完整的copy过来, 要不然找不到so库, 会崩溃!




然后在application里面初始化VCamera:





这个时候, 你就可以在SurfaceView上看见拍摄预览界面了, 

然后mMediaRecorder.startRecord()拍摄视频, 

调用mMediaRecorder.stopRecord()停止录制视频, 


因为拍摄出来的文件是ts视频流, 所以还要调用mMediaRecorder.startEncoding()开始合成MP4视频文件.


MediaRecorderBase类还可以设置视频各个参数, 如:




2.自定义拍摄按钮, 长按放大并且显示拍摄进度




自定义RecordedButton继承View, 在onDraw里分三部分绘制:




在拍摄模式下, 改变radius(半径), 达到放大或者缩小外圈和内圈圆的效果, 不断增加girth值达到显示拍摄进度的效果, 是不是很简单.


3.自定义view, 实现手绘涂鸦




自定义TuyaView继承View, 重写onTouch(), 在手指点下和移动时实时绘制触摸轨迹:




在手指按下时创建new Path()对象, 记录本次手指触摸移动轨迹, 并且实时调用invalidate() 达到不断调用onDraw()的目的, 然后使用canvas.drawPath(path,paint)绘制触摸路径, 是不是非常简单.


4.自定义可触摸旋转缩放位移的表情文字view




这个view稍微有点麻烦, 但我单独写了一篇文章(http://www.jianshu.com/p/15f6efd66f83), 非常详细的讲解了这个view, 而且封装的非常好, 只要addView到布局中就可以使用了, 大家可以点击链接过去看一下.


5.基于ffmpeg的图片和视频合成处理




这也是demo的最后一步, 将涂鸦,和表情文字全部合成到视频当中, 首先是得到需要合成的图片, 我们可以通过view.draw(Canvas canvas),得到布局的bitmap:




然后通过ffmpeg来执行图片和视频的合成, 具体语句是这样的:

ffmpeg -i videoPath -i imagePath -filter_complex overlay=0:0 -vcodec libx264 -profile:v baseline -preset ultrafast -b:v 3000k -g 25 -f mp4 outPath

我把参数讲解一下:


videoPath代表你要编辑视频的路径

imagePath代表你要合成的图片路径

outPath是合成之后的输出视频路径


这些是我们需要替换的参数至于一些别的, 例如:


overlay=0:0表示图片坐标位置, 0:0表示x轴=0,y轴=0

-vcodec后面表示视频输出格式, 3000k码率, 25帧数, 总之ffmpeg的参数还有很多, 如果感兴趣可以去ffmpeg官网看命令大全.




向UtilityAdapter.FFmpegRun()里传入ffmpeg语句就可以执行了, 返回值 int , 如果等于0就是成功, 非0则是失败, FFmpegRun()方法的第一参数如果传入空字符串就是异步执行视频处理, 否则就是同步执行, 这点要注意.


作者还有下篇,放一起咯


新增4个功能:


1.分段视频拍摄, 多段视频合成, 并且可以删除视频段落;

2.改变视频速度(加速或者减速);

3.仿微信裁剪图片控件, 自定义View实现功能;

4.裁剪视频宽高;


1.分段视频拍摄, 多段视频合成, 并且可以删除视频段落:




如图所示, 其实实现起来也很简单, 之前单段拍摄视频的逻辑是将一个拍摄好的ts文件转成mp4, 这次的改动就是用户每点击一次拍摄, 都生成一个ts文件, 然后将多段的ts文件合成一个mp4, 所要做的逻辑只是ffmpeg语句更改:


ffmpeg -i "concat:ts0.ts|ts1.ts|ts2.ts|ts3.ts" -c copy -bsf:a aac_adtstoasc out2.mp4


然后还要改进RecordedButton, 需要绘制段落(就是外面蓝圈中的白色小点点), 来提醒用户:




在点击删除视频段落按钮时, 要将当前段落绘制成红色来提醒用户, 当用户再次点击时才删除当前段落.


2.可以改变视频速度(加速或者减速):






同样简单, 执行ffmpeg语句, 传入源视频目录, 和调整的视频倍速, 但是需要注意的是, 最小视频倍数为0.5(减速一倍播放), 最大为2(加速1倍播放), 当超出范围后, 就会编译失败, 返回值i=1.


3.仿微信裁剪图片控件, 自定义View实现功能:



首先是绘制整个矩形(因为我没有切好的图片, 所以只能自己一步步draw了, 如果有条件可以向UI要切图,更简单):




分为2个部分来绘制, 显示外面一圈的矩形, 然后是4条线和4个加粗角, 绘制过程十分枯燥, 就是根据位置各种算坐标, 很简单, 想了解的自己来看源码.


接下来是最重要的onTouchEvent事件, 手指按下的时候,检测手指位置, 判断是缩放框体还是拖拽框体:




在ACTION_MOVE事件的时候:





这样就实现了手势控制缩放的效果, 最后通过调用getCutArr(), 可以得到裁剪后的margin值:




4.裁剪视频宽高:






这里说下几个参数, x和y是裁剪坐标的起点, cropHeight和cropWidth是想要裁剪的长宽, 这里要注意, x+cropWidth要<=原视频宽, y+cropHeight要<=原视频高, 否者执行会失败, rate是视频的码率, 这里建议的是原码率的1.5倍, 这样视频质量不会改变很大.


github地址:

https://github.com/Zhaoss/WeiXinRecordedDemo


ZZS

优秀人才不缺工作机会,只缺适合自己的好机会。但是他们往往没有精力从海量机会中找到最适合的那个。

100offer 会对平台上的人才和企业进行严格筛选,让「最好的人才」和「最好的公司」相遇。

扫描下方二维码,注册 100offer,谈谈你对下一份工作的期待。一周内,收到 5-10 个满足你要求的好机会!



如果你有想学习的文章直接留言,我会整理征稿。如果你有好的文章想和大家分享欢迎投稿,直接向我投递文章链接即可。


欢迎长按下图->识别图中二维码或者扫一扫关注我的公众号:

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存