Android录屏并利用FFmpeg转换成gif(四)

写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲这种方式还是比较困难的。本来我以为应该也有能直接在手机上录屏并生成gif文件这样的app,下载一个这样的APP来录gif要方便得多。结果发现目前几乎没有此类APP,我就想能不能自己写一个,然后查了查资料,感觉应该能做出来,于是就撸起袖子干起来了。总的来讲要实现这个功能可以分成两个部分(当然,如果有更好的实现方式欢迎大家提出来,谢谢!):

  1. 录屏,生成mp4文件
  2. 利用ffmpeg开源软件将mp4转换成gif

第一点比较容易实现,已有现成的开源代码供参考。难点在第二点,涉及到NDK开发相关的知识,及FFmpeg的集成,这方面知识我之前从未接触过,还是比较有挑战性的。

功能虽然很简单,但要讲解起来感觉还是要费点篇幅的,所以我分成了4篇文章来介绍,分别是:

  1. Android录屏并利用FFmpeg转换成gif(一) 录屏,讲讲怎样录屏生成mp4文件

  2. Android录屏并利用FFmpeg转换成gif(二) 交叉编译FFmpeg源码,说说如何根据我们的需求裁剪FFmepg并编译出可在android下运行的so包

  3. Android录屏并利用FFmpeg转换成gif(三) 在Android中使用ffmpeg命令,说说如何在Android中使用ffmpeg命令,简化C代码的编写难度

  4. Android录屏并利用FFmpeg转换成gif(四) 将mp4文件转换成gif文件,将2、3两步生成的so文件集成到android工程中,实现将mp4文件转换成gif文件,完成最终的工程。

概述

这是最后一篇了,通过前面三篇的工作,可以说这个工程的核心技术部分的功能已经基本完成了,就差最后一个组合的环节了,所以这最后一篇就是介绍一下如何将前面的工作成果串联起来,形成一个完整的工程。

先说说整个工程的业务流程,非常简单,如下图

开始录屏后,在通知栏显示一个通知,点击这个通知可以停止录屏,然后开始转码,转码结束后打开文件浏览器显示gif文件所在位置。

一、通知栏

通知栏的目的是提供一个停止录屏的操作界面,由于录屏开始后,主界面就销毁了,录屏是在子线程中执行的,当要停止录屏的时候就没有界面给用户去停止了,于是就想到利用通知栏来提供一个入口,通知栏既不会占用屏幕也符合用户的操作习惯,所以就选择了这种方式。下面是发送通知的代码:

private void showNotification() {NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);NotificationCompat.Builder builder = new NotificationCompat.Builder(this);Intent intent = new Intent();intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.setClass(this, WaitingActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 99, intent, PendingIntent.FLAG_ONE_SHOT);Notification notification = builder.setContentTitle("正在录屏...").setContentText("点击可结束录屏").setWhen(System.currentTimeMillis()).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)).setContentIntent(pendingIntent).build();notification.flags = Notification.FLAG_AUTO_CANCEL;manager.notify(1, notification);
}

这个通知栏有两个功能,

一是点击了该通知就跳到一个Activity,在该Actitivity里会结束录屏,并执行将mp4转换成gif的命令。

二是点击了之后这条消息就消失了,不会在通知栏中看到了。

二、FFmpeg命令

在第三篇中已经生成了可调用FFmpeg命令的so包了,现在来看看怎么在代码中调用FFmpeg命令,先要加载so包,

static {System.loadLibrary("avutil-55");System.loadLibrary("avcodec-57");System.loadLibrary("avformat-57");System.loadLibrary("avdevice-57");System.loadLibrary("swresample-2");System.loadLibrary("swscale-4");System.loadLibrary("avfilter-6");System.loadLibrary("ffmpeg");
}

这些so包放在jniLibs目录下

将mp4转换成gif可以用一行FFmpeg命令就可以完成,比如:

ffmpeg -i test.mp4 test.gif

不过这样转出来的gif质量很差,会有很多网格,经过一番google,我采用了这个方法 http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html ,转出来的gif质量明显比第一种方式好了很多。这种方式使用了两行命令。

#!/bin/shpalette="/tmp/palette.png"filters="fps=15,scale=320:-1:flags=lanczos"ffmpeg -v warning -i $1 -vf "$filters,palettegen" -y $palette
ffmpeg -v warning -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y $2
  • 注意:上述两种方式转换出来的gif体积都特别大,需要调整一些参数如帧率,gif的高宽等,gif体积才会小一些,但调整后的结果我也不是很满意,转换出来的gif跟原来的mp4文件差不多大小,不知道还有没有别的什么办法来压缩一下。

由于public native int exctFFmpeg(String[] commands)方法是用数组形式传递的FFmpeg命令,因此要将每行命令拆成一个数组,即命令行中的每个关键字或参数都作为数组的一个元素。比如将命令行:

ffmpeg -v warning -i "inputfile.mp4" -vf "fps=5,scale=320:-1:flags=lanczos,palettegen" -y "palette.gpeg"

拆分成:

    String[] c = new String[9];c[0] = "ffmpeg";c[1] = "-v";c[2] = "warning";c[3] = "-i";c[4] = "inputfile.mp4";c[5] = "-vf";c[6] = "fps=5,scale=320:-1:flags=lanczos,palettegen";c[7] = "-y";c[8] = "palette.gpeg";

然后调用:

exctFFmpeg(c);

这样就完成了在android中调用FFmpeg命令了。

三、打开gif所在文件夹

当转换完成后,就打开文件管理器,打开gif文件所在的文件夹,供用户享用转换的成果。

/*** 打开gif文件所在的文件夹,要求安装ES等文件浏览器,系统自带文件管理器无法导航到指定文件夹*/
private void openFolder() {String path = Controller.getInstance().getFileSavedDirectory() + File.separator;Uri selectedUri = Uri.parse(path);Intent intent = new Intent(Intent.ACTION_VIEW);intent.setDataAndType(selectedUri, "resource/folder");if (intent.resolveActivityInfo(getPackageManager(), 0) != null) {// 打开ES等导航到gif文件所在的文件夹startActivity(intent);} else {// 打开系统自带文件管理器手动进入gif文件所在的文件夹intent.setAction(Intent.ACTION_GET_CONTENT);intent.setDataAndType(selectedUri, "*/*");startActivity(intent);}
}
  • 由于没有找到一个能够调用系统自带的文件管理器打开指定的文件夹的方法,只能打开文件管理器后由用户自己手动去打开特定的文件夹。

这样的话,整个工程的实现过程就介绍完了,有什么问题可以一起来讨论。

###最后,上源码:

https://github.com/MingHuang1024/GifRecorder

由于水平有限,如果文中存在错误之处,请大家批评指正,欢迎大家一起来分享、探讨!

博客:http://blog.csdn.net/MingHuang2017

GitHub:https://github.com/MingHuang1024

Email:minghuang1024@foxmail.com

微信:724360018

Android录屏并利用FFmpeg转换成gif(四) 将mp4文件转换成gif文件相关推荐

  1. Android录屏并利用FFmpeg转换成gif(一)录屏

    Android录屏并利用FFmpeg转换成gif(一) 录屏 写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲 ...

  2. Android录屏并利用FFmpeg转换成gif(二)交叉编译FFmpeg源码

    Android录屏并利用FFmpeg转换成gif(二) 写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲这种方 ...

  3. Android录屏并利用FFmpeg转换成gif(三) 在Android中使用ffmpeg命令

    Android录屏并利用FFmpeg转换成gif(三) 写博客时经常会希望用一段动画来演示app的行为,目前大多数的做法是在电脑上开模拟器,然后用gif录制软件录制模拟器屏幕,对于非开发人员来讲这种方 ...

  4. android 录屏 github,GitHub - mabeijianxi/ScreenRecordPushStream: Android 录屏推流demo

    ScreenRecordPushStream 这是一个基于 rtmp 协议的 Android 录屏推流demo (Demo APK 下载) 使用方法 一. 服务器搭建 mkdir nms cd nms ...

  5. android录屏时不截入自定义悬浮框

    前提:使用MediaProjectionManager录屏方案. 问题:会截入自定义悬浮框 解决方案 1.本质上得修改framework层代码surfaceflinger去除悬浮框,在画布中就去除该悬 ...

  6. 录屏固定帧率 Android,Android 录屏时控制帧率

    Android 录屏时通常使用 MediaCodec 做编码器,MediaCodec 会创建一个 Surface 提供给 VirtualDisplay 填内容.通常,Android系统系统刷新速率是6 ...

  7. android 录屏

    录屏,google了一下,记录下来,以免FQ android 4.4 录屏可通过adb:adb shell screenrecord /sdcard/video.mp4 (未测试) android 5 ...

  8. Android录屏分析(Android12源码)

    Android录屏分析 目录 Android录屏分析 prepare方法(准备录制) MediaProjection.MediaRecorder.VirtualDisplay的介绍 开始与结束 缩略图 ...

  9. android 屏幕录制方案,Android录屏的三种解决方案

    本文总结三种用于安卓录屏的解决方案: adb shell命令screenrecord MediaRecorder, MediaProjection MediaProjection , MediaCod ...

最新文章

  1. 从一个需求看问题的无限复杂化和简单化
  2. Spring的Controller是单例还是多例?怎么保证并发的安全
  3. dotnet core入门
  4. NET问答: 如何迭代 Enum ?
  5. 欢乐纪中A组赛【2019.8.18】
  6. 一些用于拥挤场景的异常检测的视频数据集
  7. 神经网络中常用激活函数总结
  8. 放在请求头目的_YSLOW性能测试前端调优23大规则(三)添加Expires头
  9. mysql建立数据库需要注意什么_创建数据库的语句是什么 MySQL数据库使用教程
  10. 运营商大数据有哪些好处
  11. gerrit docker运行失败 chown: /var/gerrit/review_site: Permission denied 【已解决】
  12. 酷酷跑真有java游戏吗_JAVA版光影分享【仅此一次】下
  13. P3853 [TJOI2007]路标设置
  14. PHP 中文手册-国内镜像
  15. 智能汽车领域的开源软件供应链安全检测工具分享
  16. Xilinx Vitis学习-ug1393
  17. 我的前半生之六,创业维艰,我不想骂你,你滚吧
  18. 计算机单位上标,Origin绘图时如何标注带有上标(下标)的单位 -电脑资料
  19. ggplot2绘制地图
  20. Windows系统时间不准问题

热门文章

  1. dst发育筛查有意义吗_儿童智能筛查的意义~
  2. 电脑连接网络失败解决办法
  3. MMDet3D——报错解决:KeyError: ‘SparseConv2d is already registered in conv layer‘
  4. __repr__作用
  5. riscv-sodor 学习笔记
  6. 向亲友吸收资金算不算非法集资数额?两高一部明确
  7. 【计算方法】高斯消去法(线性方程组的求解)
  8. PyCharm设置改变字体大小的快捷键
  9. 调试并修理垂起固定翼(VTOL)
  10. 2020新版CAD都有些啥功能?