Android开发笔记之视频录制

官方使用指南请查看Google音频和视频指南

视频录制基本步骤

  1. 申明权限
    <uses-permission android:name="android.permission.RECORD_AUDIO" /><--如果录制的视频保存在外部SD卡,还需要添加以下权限-><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

注意:RECORD_AUDIO为危险权限,从Android 6.0开始(API级别23)开始,需要动态获取。

  1. 视频录制参数配置
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.text.TextUtils;/*** @author Created by LRH* @description 视频录制参数(参数可自行拓展)* @date 2021/1/19 13:54*/
public class VideoRecorderConfig {//Cameraprivate Camera camera;//摄像头预览宽度private int videoWidth;//摄像头预览高度private int videoHeight;//摄像头预览偏转角度private int cameraRotation;//保存的文件路径private String path;//由于Camera使用的是SurfaceTexture,所以这里使用了SurfaceTexture//也可使用SurfaceHolderprivate SurfaceTexture mSurfaceTexture;private int cameraId = 0;public SurfaceTexture getSurfaceTexture() {return mSurfaceTexture;}public void setSurfaceTexture(SurfaceTexture surfaceTexture) {mSurfaceTexture = surfaceTexture;}public Camera getCamera() {return camera;}public void setCamera(Camera camera) {this.camera = camera;}public int getVideoWidth() {return videoWidth;}public void setVideoWidth(int videoWidth) {this.videoWidth = videoWidth;}public int getVideoHeight() {return videoHeight;}public void setVideoHeight(int videoHeight) {this.videoHeight = videoHeight;}public int getCameraRotation() {return cameraRotation;}public void setCameraRotation(int cameraRotation) {this.cameraRotation = cameraRotation;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}public int getCameraId() {return cameraId;}public void setCameraId(int cameraId) {this.cameraId = cameraId;}public boolean checkParam() {return mSurfaceTexture != null && camera != null && videoWidth > 0 && videoHeight > 0 && !TextUtils.isEmpty(path);}
}
  1. 视频录制接口封装(使用MediaRecorder)
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.view.Surface;import com.emp.yjy.baselib.utils.LogUtils;
import java.io.IOException;/*** @author Created by LRH* @description* @date 2021/1/19 13:53*/
public class VideoRecorder {private static final String TAG = "VideoRecord";private MediaRecorder mRecorder;public VideoRecorder() {}/*** 开始录制** @param config* @return*/public boolean startRecord(VideoRecorderConfig config, MediaRecorder.OnErrorListener listener) {if (config == null || !config.checkParam()) {LogUtils.e(TAG, "参数错误");return false;}if (mRecorder == null) {mRecorder = new MediaRecorder();}mRecorder.reset();if (listener != null) {mRecorder.setOnErrorListener(listener);}config.getCamera().unlock();mRecorder.setCamera(config.getCamera());//设置音频通道
//        mRecorder.setAudioChannels(1);//声音源
//        AudioSource.DEFAULT:默认音频来源
//        AudioSource.MIC:麦克风(常用)
//        AudioSource.VOICE_UPLINK:电话上行
//        AudioSource.VOICE_DOWNLINK:电话下行
//        AudioSource.VOICE_CALL:电话、含上下行
//        AudioSource.CAMCORDER:摄像头旁的麦克风
//        AudioSource.VOICE_RECOGNITION:语音识别
//        AudioSource.VOICE_COMMUNICATION:语音通信mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);//视频源mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);try {//推荐使用以下代码进行参数配置CamcorderProfile bestCamcorderProfile = getBestCamcorderProfile(config.getCameraId());mRecorder.setProfile(bestCamcorderProfile);} catch (Exception e) {//设置输出格式mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//声音编码格式mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//视频编码格式mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);}//设置视频的长宽mRecorder.setVideoSize(config.getVideoWidth(), config.getVideoHeight());
//        设置取样帧率mRecorder.setVideoFrameRate(30);
//        mRecorder.setAudioEncodingBitRate(44100);
//        设置比特率(比特率越高质量越高同样也越大)mRecorder.setVideoEncodingBitRate(800 * 1024);
//        这里是调整旋转角度(前置和后置的角度不一样)mRecorder.setOrientationHint(config.getCameraRotation());
//        设置记录会话的最大持续时间(毫秒)mRecorder.setMaxDuration(15 * 1000);//设置输出的文件路径mRecorder.setOutputFile(config.getPath());//设置预览对象(可以使用SurfaceHoler代替)mRecorder.setPreviewDisplay(new Surface(config.getSurfaceTexture()));//预处理try {mRecorder.prepare();} catch (IOException e) {e.printStackTrace();return false;}//开始录制mRecorder.start();return true;}/*** 停止录制*/public void stopRecord() {if (mRecorder != null) {try {mRecorder.stop();mRecorder.reset();mRecorder.release();mRecorder = null;} catch (Exception e) {e.printStackTrace();LogUtils.e(TAG, e.getMessage());}}}/*** 暂停录制** @return*/public boolean pause() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && mRecorder != null) {mRecorder.pause();return true;}return false;}/*** 继续录制** @return*/public boolean resume() {if (mRecorder != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {mRecorder.resume();return true;}return false;}
}public CamcorderProfile getBestCamcorderProfile(int cameraID){CamcorderProfile profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_LOW);if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_480P)){//对比下面720 这个选择 每帧不是很清晰profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_480P);profile.videoBitRate = profile.videoBitRate/5;return profile;}if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_720P)){//对比上面480 这个选择 动作大时马赛克!!profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_720P);profile.videoBitRate = profile.videoBitRate/35;return profile;}if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_CIF)){profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_CIF);return profile;}if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_QVGA)){profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_QVGA);return profile;}return profile;}
  1. 使用示例
public void recordVideo(CustomCameraView CameraView) {VideoRecorderConfig config = new VideoRecorderConfig();String path = App.sGlobalContext.getExternalFilesDir("video").getAbsolutePath() + File.separator + "test1.mp4";config.setCamera(CameraView.getCamera());config.setCameraRotation(CameraView.getCameraRotation());config.setVideoHeight(CameraView.getCameraSize().height);config.setVideoWidth(CameraView.getCameraSize().width);config.setPath(path);config.setSurfaceTexture(CameraView.getSurfaceTexture());config.setCameraId(0);VideoRecorder record = new VideoRecorder();boolean start = record.startRecord(config, null);int duration = 15_000;while (duration > 0) {if (duration == 10_000) {boolean pause = record.pause();LogUtils.e(TAG, "暂停录制" + pause);}if (duration == 5_000) {boolean resume = record.resume();LogUtils.e(TAG, "重新开始录制" + resume);}SystemClock.sleep(1_000);duration -= 1_000;}record.stopRecord();LogUtils.d(TAG, "停止录制");}

其中CustomCameraView为自己封装的相机库

Android开发笔记之视频录制相关推荐

  1. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  2. Android开发笔记(一百三十)截图和录屏

    屏幕捕捉 Android5.0之后开放了屏幕捕捉的API,因此开发者便可以直接通过代码进行截图与录屏,而无需操作系统底层了.屏幕捕捉的功能由MediaProjectionManager媒体投影管理器实 ...

  3. Android开发笔记(一百二十六)自定义音乐播放器

    MediaRecorder/MediaPlayer 在Android手机上面,音频的处理比视频还要复杂,这真是出人意料.在前面的博文< Android开发笔记(五十七)录像录音与播放>中, ...

  4. Android开发笔记(七十九)资源与权限校验

    硬件资源 因为移动设备的硬件配置各不相同,为了防止使用了不存在的设备资源,所以要对设备的硬件情况进行检查.一般情况下,前置摄像头.部分传感器在低端手机上是没有的,像SD卡也可能因为用户没插卡使得找不到 ...

  5. Android开发笔记(五十七)录像录音与播放

    媒体录制MediaRecorder MediaRecorder是Android自带的录制工具,通过操纵摄像头和麦克风完成媒体录制,既可录制视频,也可单独录制音频.其中对摄像头Camera的介绍参见&l ...

  6. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  7. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  8. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

  9. Android开发笔记(一百六十七)Android8.0的画中画模式

    前面的博文< Android开发笔记(一百五十九)Android7.0的分屏模式>介绍了Android7.0的多窗口特性,但是这个分屏的区域是固定的,要么在屏幕的上半部分,要么在屏幕的下半 ...

  10. Android开发笔记(一百六十六)H5通过WebView录像上传

    前面的博文< Android开发笔记(一百五十二)H5通过WebView上传图片>介绍了如何拍照上传给网页,不料客户又要求再加个摄像上传给网页.既然如此,那么再探讨一下如何实现这个摄像上传 ...

最新文章

  1. 华大 MCU 之六 SEGGER Embedded Studio 及 Ozone 使用 Jlink 调试
  2. GraphQL query的schema校验
  3. 新经济、新选择——人才流动与迁徙2021
  4. 大数据分析方法有哪些
  5. insist fortress g55 机械键盘得救了
  6. matlab 三维画图总结
  7. win10查看电池损耗:生成损耗报告
  8. 匿名飞控STM32版代码整理之Ano_Imu.c
  9. 产品经理-Axure原型设计-共享停车app
  10. 隐藏的Word快捷键操作
  11. 产品DAU下降如何分析
  12. 研究生期间如何做研究:一些建议
  13. Mysql查询历史SQL执行记录
  14. mac和window电脑 解决github打不开问题
  15. Matlab和C#混合编程
  16. 关河因果:钓鱼城引擎技术概述
  17. WRF,WPS,WRF-Chem安装及编译步骤及bug总结(转载)
  18. 象棋棋霸2006 v5.1 五合一免费版 怎么用
  19. 【GATK加速】替换BWA/GATK/Mutect2,Sentieon软件 肿瘤体细胞突变检测分析指南-系列2(ctDNA及其他高深度测序样本)
  20. vue element table列表删除某一页的最后一条数据之后页面不自动跳到上一页

热门文章

  1. 组网 三层交换机配置
  2. 我学过的一些PS基本操作
  3. SQLServer实现快速进行简繁体的翻译功能
  4. ios开发读取剪切板的内容_iOS开发之详解剪贴板
  5. python重复import_Python 中循环 import 造成的问题如何解决?
  6. 【图像处理】自动报靶系统(重弹孔)【含GUI Matlab源码 973期】
  7. 玩游戏计算机缺失msvcp140,游戏缺少msvcp140.dll错误提示怎么办解决方法
  8. 医学影像常用Python包
  9. Mstar 648 平台遥控器/按键包POWER键配置
  10. [我读]十四堂人生创意课