上一篇介绍了MediaProjection,这个类可以用来实现安卓屏幕数据的采集,也就是手机一帧帧的截图,并输出成byte流的格式。
有兴趣的同学可以看这篇:
Android视频录制--MediaProjection

但其实只用MediaProjection,并无法生成一个视频,因为我们得到的只是流,还需要把流编码成视频格式。MediaProjection官方的demo里,也仅仅是把输出内容放到了surfaceview里面,在app内部展示。

这次我们就讲一下,如何把MediaProjection输出的流转化成为视频。
其实这个过程,我在另外一篇博客里面也讲过:
android视频直播-直播流程概述

简单说一下,一个视频的生成,最少要有以下两步:
1. 视频的采集,比如摄像头,比如我们讲的MediaProjection,这一步最终的输出,通常是一个流
2. 视频的编码压缩,这一步是对第一步中获取到的流做处理,编码可能采用硬编码,比如h264,也可能采用软编码,自己写编码逻辑,最终生成的是一个解码器(也就是我们通常说的播放器)可以解码(播放)的视频文件(比如mp4)

所以MediaProjection其实帮我们实现了第一步,也就是视频的采集,我们还需要自己来实现视频的编码。
所幸Google给我们提供了另外一个类MediaCodec来实现视频的硬编码,而不需要我们自己写太多的逻辑。
废话不多说,直接上代码,首先,我们需要在开始编码之前,先做一下准备,定义我们要编码的格式等信息:

//MediaFormat这个类是用来定义视频格式相关信息的
//video/avc,这里的avc是高级视频编码Advanced Video Coding
//mWidth和mHeight是视频的尺寸,这个尺寸不能超过视频采集时采集到的尺寸,否则会直接crash
MediaFormat format = MediaFormat.createVideoFormat("video/avc", mWidth, mHeight);//COLOR_FormatSurface这里表明数据将是一个graphicbuffer元数据
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,  MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);  //设置码率,通常码率越高,视频越清晰,但是对应的视频也越大,这个值我默认设置成了2000000,也就是通常所说的2M,这已经不低了,如果你不想录制这么清晰的,你可以设置成500000,也就是500k
format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);//设置帧率,通常这个值越高,视频会显得越流畅,一般默认我设置成30,你最低可以设置成24,不要低于这个值,低于24会明显卡顿
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);//IFRAME_INTERVAL是指的帧间隔,这是个很有意思的值,它指的是,关键帧的间隔时间。通常情况下,你设置成多少问题都不大。
//比如你设置成10,那就是10秒一个关键帧。但是,如果你有需求要做视频的预览,那你最好设置成1
//因为如果你设置成10,那你会发现,10秒内的预览都是一个截图
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);//创建一个MediaCodec的实例
MediaCodec mEncoder = MediaCodec.createEncoderByType("video/avc");//定义这个实例的格式,也就是上面我们定义的format,其他参数不用过于关注
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);//这一步非常关键,它设置的,是MediaCodec的编码源,也就是说,我要告诉mEncoder,你给我解码哪些流。
//很出乎大家的意料,MediaCodec并没有要求我们传一个流文件进去,而是要求我们指定一个surface
//而这个surface,其实就是我们在上一讲MediaProjection中用来展示屏幕采集数据的surface
mSurface = mEncoder.createInputSurface();
mEncoder.start();

关于上面的mSurface,定义和使用的代码:

Surface mSurface;
mMediaProjection.createVirtualDisplay(TAG + "-display",mWidth, mHeight, mDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,mSurface, null, null);

可以看到,通过上面mSurface的串联,我们把mMediaProjection的输出内容放到了mSurface里面,而mSurface正是mEncoder的输入源,这样就完成了对mMediaProjection输出内容的编码,也就是屏幕采集数据的编码。

现在我们搞定编码的输入源(mSurface)问题了,下一步我们需要把编码后的内容输出到一个文件中去:

public class AvcEncoder {private MediaCodec mediaCodec;
private BufferedOutputStream outputStream;public AvcEncoder() { File f = new File(Environment.getExternalStorageDirectory(), "Download/video_encoded.264");touch (f);try {outputStream = new BufferedOutputStream(new FileOutputStream(f));Log.i("AvcEncoder", "outputStream initialized");} catch (Exception e){ e.printStackTrace();}mediaCodec = MediaCodec.createEncoderByType("video/avc");MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 320, 240);mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);mediaCodec.start();
}public void close() {try {mediaCodec.stop();mediaCodec.release();outputStream.flush();outputStream.close();} catch (Exception e){ e.printStackTrace();}
}// called from Camera.setPreviewCallbackWithBuffer(...) in other class
public void offerEncoder(byte[] input) {try {ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);if (inputBufferIndex >= 0) {ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];inputBuffer.clear();inputBuffer.put(input);mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);}MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,0);while (outputBufferIndex >= 0) {ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];byte[] outData = new byte[bufferInfo.size];outputBuffer.get(outData);outputStream.write(outData, 0, outData.length);Log.i("AvcEncoder", outData.length + " bytes written");mediaCodec.releaseOutputBuffer(outputBufferIndex, false);outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);}} catch (Throwable t) {t.printStackTrace();}}

Android视频录制--屏幕录制相关推荐

  1. android 8华为屏幕录制,数码知识:华为nova8pro如何屏幕录制怎么录屏

    如今使用IT数码设备的小伙伴们是越来越多了,那么IT数码设备当中是有很多小技巧的,这些技巧很多小伙伴一般都是不知道如何来实用的,就好比最近就有很多小伙伴们想要知道华为nova8pro如何屏幕录制怎么录 ...

  2. 计算机快捷键屏幕录制,屏幕录制软件哪个好用?设置电脑录屏快捷键

    屏幕录制软件哪个好用?设置电脑录屏快捷键 2020年05月19日 14:40作者:黄页编辑:黄页 分享 屏幕录制软件哪个好用?不管是在生活还是在工作中,电脑录屏的需求都是有的.那在线录制电脑视频的好用 ...

  3. Android录屏——屏幕录制命令screenrecord

    说明 : screenrecord是一个shell命令 支持Android4.4(API level 19)以上 支持视频格式: mp4 直接使用命令录制的效果十分好,也不需要下App 这是直接调用A ...

  4. 【多媒体开发】Android视频全屏录制遇到的一些问题

    最近写了个demo,有个功能是全屏录制视频,录视频的基本功能不算难,demo通过SurfaceView + MediaRecorder的方法, 这里不上代码了,只总结下一些问题: 1.Paramete ...

  5. Android视频编辑器(二)预览、录制视频加上水印和美白磨皮效果

    前言      这是视频编辑器系列的第二篇文章,在上篇文章中,我们讲解了利用OpenGl和SurfaceView进行视频预览,MediaCodec和MeidaMuxer进行视频录制和断点续录.而这篇主 ...

  6. Android视频编辑器(一)通过OpenGL预览、录制视频以及断点续录等

    前言 如今的视频类app可谓是如日中天,火的不行.比如美拍.快手.VUE.火山小视频.抖音小视频等等.而这类视频的最基础和核心的功能就是视频录制和视频编辑功能.包括了手机视频录制.美白.加滤镜.加水印 ...

  7. 如何录制屏幕视频?有哪些录制技巧?

    现在在数字化时代,录制电脑屏幕已经成为很多人的必备技能.无论是制作教学视频,还是分享游戏战绩,录制电脑屏幕都可以很好地满足我们的需求.那么,如何录制电脑屏幕?有哪些录制技巧?下面将逐一介绍. 选择一款 ...

  8. Android限制录制屏幕无声音,哪一个安卓录屏软件可以录制系统的声音

    今天介绍的这款软件许多宝宝在之前就已经问过我很多次了,因为没有什么特别好用,所以一直就没有给大家推荐什么,直到今天才来给大家推荐,是因为小编使用了几天之后发现可以介绍给你们录屏大师,因为它操作起来挺简 ...

  9. 屏幕录制方法?如何在电脑进行屏幕录制

    屏幕录制方法?随着科技的发展,电脑已经成为了我们日常生活办公一项必不可少的组成部分.前些天,有朋友问我:电脑屏幕如何录制?作为一名理工男,这种问题自然是难不倒我的!相信除了我的朋友之外,也有其他小伙伴 ...

  10. Vue中如何进行屏幕录制与直播推流

    Vue中如何进行屏幕录制与直播推流 屏幕录制和直播推流是现代Web应用中常用的功能,例如在线教育.视频会议和游戏直播等.Vue作为一种流行的JavaScript框架,提供了一些工具和库,可以方便地实现 ...

最新文章

  1. 【微信小程序】登录功能实现及讲解(获取用户唯一标识)
  2. 新盒模型移动端的排版
  3. [转载]读塔莎奶奶的美好生活
  4. 2013\National _C_C++_A\5.网络寻路
  5. Linux系统调用号表
  6. Java笔记——Java代码块的执行顺序
  7. VHDL设计交通灯控制器的课程设计
  8. 将DataTable的内容以EXCEl的形式导出到本地
  9. perl里面隐式的继承
  10. 整合 centos安装python的介绍
  11. python cmd窗口名字_python cmd 窗口 中文乱码 解决方法 (附:打印不同颜色)
  12. Android Camera 摄像 demo
  13. org.apache.tomcat.jni.LibraryNotFoundError tcnative-1.dll 异常
  14. WebSocket 协议
  15. android socket编程实例
  16. 天啊~ 少些一个等号的后果
  17. 2017-2018-1 20155339 《信息安全系统设计基础》第8周学习总结
  18. 联想集团杨元庆:联想携手SAP解决用户云计算应用痛点
  19. “飞扬小字典” -- 辅助记忆的小工具
  20. 计算机桌面文件删除不掉是怎么了,文件删不掉怎么办?如何删除一个删不掉的文件?...

热门文章

  1. 如何回答不靠谱的面试问题
  2. Linux ALSA - 支持软件回采参考(playback)信号
  3. Latex表格在线自动生成及word表格转Latex方法
  4. qq气泡php接口,h5实现QQ聊天气泡的实例介绍
  5. 3DMAX中旋转楼梯的做法
  6. JVM类加载机制详解-20160812
  7. 机器人的发展及其概述
  8. 通达信l2数据接口具体有哪些功能可提供?
  9. [手机APP合集]全是干货!你想要的玩机技巧全在这里了,快来领取!
  10. 实验室电磁铁的主要用途