基于FFmpeg的短视频编辑工具Cut

前言

最近在学习FFmpeg和音视频的相关知识,为了加强对FFmpeg的认识和了解,于是撸了一个短视频编辑软件Cut。

效果图先行:

技术点

启动页优化

但启动app的时候会有一个短暂的黑屏或者白屏。为什么呢? 是因为在App启动时,系统会执行3个Task:

1、 加载并启动app
2、在app启动后,立即展示空白的window
3、创建app进程

一旦app进程完成了第一次绘制,系统进程就会用main activity替换已经展示的background window。之后用户才可以使用app。

这个空白的window就是导致白屏或者黑屏的罪魁祸首。怎么解决呢? 1.定义透明的主题,parent中的AppTheme为APP的主题
 

<style name="Theme.AppStartLoadTranslucent" parent="AppTheme">  <item name="android:windowIsTranslucent">true</item>  <item name="android:windowNoTitle">true</item>  </style>  

<!-- 启动界面 -->  <activity  android:name=".ui.LaunchActivity"  android:launchMode="singleTask"  android:theme="@style/Theme.AppStartLoadTranslucent">  <intent-filter>  <action android:name="android.intent.action.MAIN" />  <category android:name="android.intent.category.LAUNCHER" />  </intent-filter>  </activity> 

启动页优化原理

增量更新和全量更新

在App用了增量更新。

增量更新:增量更新是指在进行更新操作时,只更新需要改变的地方,不需要更新或者已经更新过的地方则不会重复更新,增量更新与全量更新相对。

使用的是bsdiff、 在bspatch中还会用到bzip2.
增量更新的流程:下载差分包,手机上的apk和差很包合并形成新的apk,然后再次安装。
 

  DownloadUtil.get().download(appPath, savePath, saveName,new DownloadUtil.OnDownloadListener() {@Overridepublic void onDownloadSuccess(File file) {if(file != null){mProgressDialog.dismiss();LogUtil.e("tag", "---path = " + file.getAbsolutePath());if(update_type == 1){//获取当前应用的apk文件/data/app/appString oldFile = Utils.getSourceApkPath(LaunchActivity.this, getPackageName());//2.合并得到最新版本的APK文件String newApkPath = MApplication.VIDEO_PATH+"meger.apk";//下载差分包的地址String patchFileAbsolutePath = file.getAbsolutePath();LogUtil.e(TAG, "oldfile:"+oldFile);LogUtil.e(TAG, "newfile:"+newApkPath);LogUtil.e(TAG, "patchfile:"+patchFileAbsolutePath);//jni调用baspatch old.APK 和 差分包 合成新的apkBspatchNDK.bspatch(oldFile, newApkPath, patchFileAbsolutePath);//再次安装Utils.installApk(LaunchActivity.this,newApkPath);}else if(update_type == 2){Utils.installApk(LaunchActivity.this,file);}}}@Overridepublic void onDownloading(int progress) {mProgressDialog.setProgress(progress);}@Overridepublic void onDownloadFailed() {mProgressDialog.dismiss();}});

这里会有一个问题?这个差分包,是什么版本和新版本的差分包?我这里是这样处理的:假如市场发布了1.0.01.0.11.0.2,最新版本为1.0.3.
差分包patch是:1.0.21.0.3生成的差分包。
因此:当且仅有版本为1.0.2(前一个版本),才能进行增量更新,1.0.2之前的(前一个版本之前的)都需要全量更新。所以在代码中有这样的一段判断:
 

if (MApplication.getUpgradeinfo().versionCode - Utils.getVerCode(this) == 1) {//前一个版本//增量更新//有新版本hasNewVersion = true;update_type = 1;apkUrl = MApplication.QINIU_ADDRESS + "diff-"+MApplication.getUpgradeinfo().versionCode+".patch";}else if(MApplication.getUpgradeinfo().versionCode - Utils.getVerCode(this) > 1){//全量更新hasNewVersion = true;apkUrl = MApplication.getUpgradeinfo().apkUrl;update_type = 2;} else {update_type = 0;hasNewVersion = false;toHome3Second();}

差分包怎么生成?下载了bsdiff,调用命令即可:(我这里是 Mac OS下执行的)

bsdiff old.apk new.apk diff.patch

然后然后就是差分包和旧的apk在Android如何合成的问题了。因为如何在Android使用bspacth,还得需要如何把bapacth引入Android Studio。 所以新开了一篇文章介绍,可以看这里。

ffmpeg命令行使用

FFmpeg的使用整个项目的重点,大部分的功能都需要它。而在之前的一篇文章中有介绍如何编译FFmpeg并且引入Android Studio 使用, 如何在Android 中使用FFmpeg命令。

ffmpeg命令

在项目中,使用的命令有:改变视频的速度,改变视频的分辨率,视频和视频的连接,视频和图片的合成,视频的剪辑。

【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~

改变视频的速度

点击分镜,会弹出一个popup可以选择分镜播放的速度

/*** 改变视频的速度的ffmpeg命令 atempo【0.5,2】*  ffmpeg -i input.mkv -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" output.mkv* @param videoPath 输入录像* @param outPath 输出路径* @param speed 速度* @return*/private String getSpeedCommandStr(String videoPath, float speed, String outPath) {if (TextUtils.isEmpty(videoPath) || TextUtils.isEmpty(outPath)) {return null;}String filter = String.format(Locale.getDefault(), "[0:v]setpts=%f*PTS[v];[0:a]atempo=%f[a]", 1/speed, speed);StringBuilder sb = new StringBuilder("ffmpeg");sb.append(" -i");sb.append(" "+videoPath);sb.append(" -filter_complex");sb.append(" "+filter);sb.append(" -map");sb.append(" [v]");sb.append(" -map");sb.append(" [a]");sb.append(" -b:v 3000k -g 25");sb.append(" -y");sb.append(" "+outPath);LogUtil.d(TAG,"------- cmd = " + sb.toString());return sb.toString();}

视频和视频的连接

在项目中共有3个分镜头,最后需要把这三个分镜合成一个完整的视频:

 /*** 合成视频命令* ffmpeg -f concat -i filelist.txt -c copy output.mkv* @param path* @return-vcodec libx264*/private String getComplexVideoCmd(String fileList,String path) {StringBuilder builder = new StringBuilder();builder.append("ffmpeg -f concat -safe 0 -i ");builder.append(fileList);
//        builder.append(" -b:v 4000K -b:a 96K ");
//        builder.append("-profile:v baseline -preset ultrafast ");
//        builder.append(" -b:v 1500K -b:a 48K -f mp4 ");builder.append(" ");builder.append(path);LogUtil.d(TAG,"----- 合成视频命令 = " + builder.toString());return builder.toString();}

在视频连接的时候会有一个坑,因为在fileList.txt里面写入的路径是绝对路径,在使用ffmpeg 命令连接视频的时候,会报 Operation not permitted的错误。加上-safe 0就可以解决了。

改变视频的分辨率

每一分镜的视频来源有可能是录制的,也可能是选择本地视频剪辑一部分的,因此分辨率和码率都会各部相同,就对每一分镜统一成相同分辨率和码率,如果不统一,不然会在视频连接的生成的视频会丢帧的厉害。

  /*** 改变视频分辨率的命令* @param videoPath* @return*/private String getChangeVideoSizeCmd(String videoPath,String outPath) {if (TextUtils.isEmpty(videoPath) || TextUtils.isEmpty(outPath)) {return null;}StringBuilder builder = new StringBuilder();builder.append("ffmpeg -y -i ");builder.append(videoPath);builder.append(" -vf scale=1080:1920 -r 25 ");builder.append(outPath);LogUtil.e(TAG, "----- 改变视频size 命令 = " + builder.toString());return builder.toString();}

视频的剪辑

对本地的视频剪辑出其中的一部分 ,现在固定3s。

 StringBuilder builder = new StringBuilder();builder.append("ffmpeg -ss ");builder.append(start);builder.append(" -t ");builder.append(duration);builder.append(" -i ");builder.append(inputFile);
//        builder.append(" -vcodec copy -acodec copy -b:v 4000K -b:a 96K -f mp4 ");builder.append(" -vcodec copy -acodec copy ");builder.append(MApplication.VIDEO_PATH);builder.append(outputName);LogUtil.e(TAG,"------------ 剪辑视频ffmpeg 命令 = " +builder.toString());final String[] command = builder.toString().split(" ");

视频和图片的合成

把三个分镜头合成一个视频后,可以对视频进行涂鸦,帖子,添加文本等操作。

   StringBuilder sb = new StringBuilder();sb.append("ffmpeg");sb.append(" -y -i");sb.append(" "+path);sb.append(" -i");sb.append(" "+imagePath);sb.append(" -filter_complex overlay ");sb.append(mergeVideo);String[] cmds = sb.toString().split(" ");LogUtil.d(TAG, "----- overlay 命令 " + sb.toString());

不足

在这个项目中,完成初期的预想,加深对FFmpeg认识和了解。但是1.0版本存在很多的不足,比如:

  1. 速度的变换范围少
  2. 合成视频画质差
  3. FFmpeg对一些功能,比如:在overlay做叠加,用scale缩放,改变速度功能较慢 。
  4. 不能添加滤镜

后记

这个项目将会一直会维护下去,完善所能知道的一些不足的地方,还请大家多多指导和多提意见,互相学习,感谢。

Thanks
FFmpeg
glide
butterknife
BaseRecyclerViewAdapterHelper
okhttp
bspatchlibrary
ffmpeglibrary
circular-progress-button
material-dialogs
Zhaoss
视频裁剪

作者:maimingliang
原文 基于FFmpeg的短视频编辑工具Cut - 掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/328247.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

试除法求约数算法总结

知识概览 试除法求一个数的约数的时间复杂度是。 例题展示 题目链接 活动 - AcWing 系统讲解常用算法与数据结构&#xff0c;给出相应代码模板&#xff0c;并会布置、讲解相应的基础算法题目。https://www.acwing.com/problem/content/871/ 题解 用试除法求约数&#xff0c;…

Git - 强制替换覆盖 master 分支解决方案

问题描述 在版本迭代中&#xff0c;通常会保持一个主分支 master&#xff0c;及多个 dev 分支&#xff0c;但是因为 dev 分支的开发周期过长&#xff0c;迭代太多而没有及时维护 master &#xff0c;导致后来发版上线的大部分代码都在 dev 分支上&#xff0c;如果将代码在 mas…

报错处理:java.io.IOException: Could not find resource mybatis-config.xml

运行mybatis文件时出现了以下的情况 java.io.IOException: Could not find resource mybatis-config.xmlat org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:114)at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:100)at org.apach…

Flume基础知识(十):Flume 聚合实战

1&#xff09;案例需求&#xff1a; hadoop100上的 Flume-1 监控文件/opt/module/group.log&#xff0c; hadoop101上的 Flume-2 监控某一个端口的数据流&#xff0c; Flume-1 与 Flume-2 将数据发送给 hadoop102 上的 Flume-3&#xff0c;Flume-3 将最终数据打印 到控制台。…

企业数据库安全管理规范

1.目的 为规范数据库系统安全使用活动&#xff0c;降低因使用不当而带来的安全风险&#xff0c;保障数据库系统及相关应用系统的安全&#xff0c;特制定本数据库安全管理规范。 2.适用范围 本规范中所定义的数据管理内容&#xff0c;特指存放在信息系统数据库中的数据。 本…

web——德州扑克

1.此案例只用于学习 2.未接入游戏规则 HTML代码部分 <!DOCTYPE html> <html><head><meta charset"utf-8"><meta name"viewport" content"widthdevice-width"><meta name"Poker Skin" content&quo…

扩散模型: Diffusion Model概念讲解

Diffusion Model 课件视频前向扩散过程 在原始图像中逐步添加高斯分布随机噪声,直到最后得到完全噪声的图像。 反向降噪过程 逐步去除噪声图中的噪声,得到最后原图。 根据噪声图和时间步得到预测的噪声,然后噪声图减去噪声得到原始图 噪声预测的标签来自于前向扩散过程中添加…

Rustdesk打开Win10 下客户端下面服务不会自启,显示服务未运行

环境: Rustdesk1.19 问题描述: Rustdesk打开Win10 下客户端下面服务不会自启,显示服务未运行 解决方案: 1.查看源代码 pub async fn start_all() {crate::hbbs_http::sync::start();let mut nat_tested = false;check_zombie()

【ArcGIS Pro微课1000例】0056:度分秒与十进制度互相转换(度分秒→度、度→度分秒)

ArcGIS软件可以很方便的直接实现度分秒转度、度转度分秒(度分秒→度、度→度分秒)。 文章目录 一、转换预览二、工具介绍三、案例解析一、转换预览 借助ArcGIS快速实现度分秒与度及其他格式的坐标转换,例如:度分秒→度、度→度分秒。 1. 度→度分秒 2. 度分秒→度 转换后…

Ubuntu中连接不上网络的问题解决方法

最近在terminal中调试联通时&#xff0c;一直都是网络未连接没有反应的状态&#xff0c;几经波折后得到了问题的解决方法&#xff0c;这里罗列两种方法。 法1&#xff1a; 在桥接模式下打开虚拟机的编辑—>虚拟网络编辑器后点击更改设置 点击自动桥接&#xff0c;相当于虚…

基于 IP 多播的网络会议程序(2024)

1.题目描述 局域网 IP 多播程序&#xff0c;设计一个图形界面的网络会议程序&#xff08;实现文本多播方式即可&#xff09;。 2.演示Demo 3.参考代码 广播发送代码 //服务端 #include <winsock2.h> #include <iostream> #include <list>#pragma comment(l…

C# Emgu.CV4.8.0读取rtsp流分段保存

【官方框架地址】 https://github.com/emgucv/emgucv 【算法介绍】 EMGU CV&#xff08;Emgu Computer Vision&#xff09;是一个开源的、基于.NET框架的计算机视觉库&#xff0c;它提供了对OpenCV&#xff08;开源计算机视觉库&#xff09;的封装。EMGU CV使得在.NET应用程序…