一 录制视频工具类

import android.content.Context;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;import mwteck.ettda.Utils.AppToast;/*** CreateTime 2017/10/16 15:00* Author LiuShiHua* Description:录制视频* <p>* 1.在Activity的oncreate方法中初始化* 2.在onstart中调用RecordVideoUtil的startPreview方法生成预览界面* 3.在onstop中调用RecordVideoUtil的stopRecord和stotPreview方法终止录制、预览界面* <p>* duration 默认录制时间*/public class RecordVideoUtil {/*** 默认录制时间是30秒*/private int duration = 30;private SurfaceHolder mSurfaceHolder;private Context context;private boolean mIsSufaceCreated = false;private Camera mCamera;private final static int CAMERA_ID = 0;private boolean isRecording = false;private final String TAG = "------------>录像";private MediaRecorder mRecorder;private long start, end;private String savePath;private static int cameraPosition = 1;//0代表前置摄像头,1代表后置摄像头private boolean isView = true;private boolean highQuality = false;//是否录制高质量音频public RecordVideoUtil(Context context, SurfaceView mCameraPreview) {this.context = context;mSurfaceHolder = mCameraPreview.getHolder();mSurfaceHolder.addCallback(mSurfaceCallback);mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);}private SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {mIsSufaceCreated = false;}@Overridepublic void surfaceCreated(SurfaceHolder holder) {mIsSufaceCreated = true;}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {startPreview();}};//启动预览public boolean startPreview() {//保证只有一个Camera对象if (mCamera != null || !mIsSufaceCreated) {Log.d(TAG, "startPreview will return");return true;}try {mCamera = Camera.open(CAMERA_ID);} catch (Exception e) {//未授权相机权限,这里会抛出异常AppToast.makeToast("打开相机失败");e.printStackTrace();return false;}Camera.Parameters parameters = mCamera.getParameters();
//        Camera.Size size = getBestPreviewSize(, CameraUtils.PREVIEW_HEIGHT, parameters);
//        if (size != null) {//            parameters.setPreviewSize(size.width, size.height);
//        }parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);parameters.setPreviewFrameRate(20);//设置相机预览方向mCamera.setDisplayOrientation(90);mCamera.setParameters(parameters);try {mCamera.setPreviewDisplay(mSurfaceHolder);} catch (Exception e) {Log.d(TAG, e.getMessage());}mCamera.startPreview();return true;}//打开闪光灯public boolean openLight() {if (cameraPosition == 0) {return false;}return RecordVideoHelper.openFlashlight(mCamera, context);}//关闭闪光灯public boolean closeLight() {return RecordVideoHelper.closeFlashlight(mCamera);}/*** 外部调用** @param savePath 存储路径* @return 开始是否成功*/public boolean startRecord(String savePath) {this.savePath = savePath;if (isRecording) {return false;}if (!hasSdcard()) {Toast.makeText(context, "请先插入SD卡(存储卡)", Toast.LENGTH_SHORT).show();return false;}if (!isSDCanUseSize50M()) {Toast.makeText(context, "内存已经不足50M了,请先清理手机空间", Toast.LENGTH_SHORT).show();}File file = new File(savePath);if (!file.exists()) {file.getParentFile().mkdirs();try {file.createNewFile();} catch (IOException e) {e.printStackTrace();Toast.makeText(context, "文件创建失败", Toast.LENGTH_SHORT).show();return false;}}if (mRecorder != null) {mRecorder.stop();mRecorder.release();mRecorder = null;}mRecorder = new MediaRecorder();//实例化mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());//预览mCamera.unlock();setMeadiaRecorder(mRecorder, file.getPath());try {mRecorder.prepare();mRecorder.start();isRecording = true;start = System.currentTimeMillis();} catch (Exception e) {e.printStackTrace();if (mCamera != null) {mCamera.lock();}isRecording = false;mRecorder.release();return false;}return true;}/*** 停止录制** @return*/public boolean stopRecord() {end = System.currentTimeMillis();Log.d("---------->", "停止录制");if (!isRecording || mRecorder == null) {return false;}try {mRecorder.stop();} catch (Exception e) {mRecorder = null;mRecorder = new MediaRecorder();}mRecorder.release();mRecorder = null;if (mCamera != null) {mCamera.lock();}isRecording = false;//重启预览if (!startPreview())return false;if (((double) (end - start) / 1000) < 1) {if (savePath != null && new File(savePath).exists()) {new File(savePath).delete();}}return true;}/*** 在activity中的onPause中调用* <p>* 释放Camera对象*/public void stopPreview() {if (mCamera != null) {try {mCamera.setPreviewDisplay(null);} catch (Exception e) {Log.d(TAG, e.getMessage());}mCamera.stopPreview();mCamera.release();mCamera = null;isView = false;}}/*** 设置参数* ** @param mRecorder* @param filePath  1,花屏主要跟VideoSize有关,将Size调到640*480以上花屏问题可解决,或者录制屏幕为正方形。*                  2,清晰度和录制文件大小主要和EncodingBitRate有关,参数越大越清晰,同时录制的文件也越大。*                  3,视频文件的流畅度主要跟VideoFrameRate有关,参数越大视频画面越流畅,但实际中跟你的摄像头质量有很大关系。*/private void setMeadiaRecorder(MediaRecorder mRecorder, String filePath) {mRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {@Overridepublic void onError(MediaRecorder mediaRecorder, int i, int i1) {Log.d("-------->", "MediaRecorder.onError");}});mRecorder.setCamera(mCamera); //给Recorder设置Camera对象,保证录像跟预览的方向保持一致if (cameraPosition == 1) {mRecorder.setOrientationHint(90);  //改变保存后的视频文件播放时是否横屏(不加这句,视频文件播放的时候角度是反的)} else {mRecorder.setOrientationHint(270);  //改变保存后的视频文件播放时是否横屏(不加这句,视频文件播放的时候角度是反的)}mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置从摄像头采集图像mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); // 设置从麦克风采集声音CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 设置视频的输出格式 为MP4
//        mRecorder.setOutputFormat(mProfile.fileFormat);mRecorder.setAudioEncoder(mProfile.audioCodec);// 设置音频的编码格式
//        mRecorder.setVideoEncoder(mProfile.videoCodec);mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 设置视频的编码格式mRecorder.setOutputFile(filePath);
//        mRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);mRecorder.setVideoSize(640, 480);//设置录制的视频帧率,必须放在设置编码和格式的后面,否则报错mRecorder.setVideoFrameRate(mProfile.videoFrameRate);mRecorder.setVideoEncodingBitRate(800 * 1024);//视频码率mRecorder.setAudioEncodingBitRate(mProfile.audioBitRate);
//        mRecorder.setAudioChannels(mProfile.audioChannels);mRecorder.setAudioChannels(1);//设置录制的音频通道数
//        mRecorder.setAudioSamplingRate(mProfile.audioSampleRate);mRecorder.setAudioSamplingRate(44100);
//        mRecorder.setMaxDuration(duration * 1000); //设置最大录像时间为10s}/*** 检查设备是否存在SDCard的工具方法*/public static boolean hasSdcard() {String state = Environment.getExternalStorageState();if (state.equals(Environment.MEDIA_MOUNTED)) {// 有存储的SDCardreturn true;} else {return false;}}/*** 获得sd卡剩余容量是否有50M,即可用大小** @return*/public static boolean isSDCanUseSize50M() {if (!hasSdcard()) {return false;}File path = Environment.getExternalStorageDirectory();StatFs sf = new StatFs(path.getPath());long size = sf.getBlockSize();//SD卡的单位大小long available = sf.getAvailableBlocks();//可使用的数量DecimalFormat df = new DecimalFormat();df.setGroupingSize(3);//每3位分为一组if (size * available / 1024 / 1024 < 50) {return false;}return true;}/*** 切换前置/后置摄像头*/public void changeUseCamera() {if (mCamera == null || mSurfaceHolder == null) return;//切换前后摄像头if (!isCanChange) return;int cameraCount = 0;Camera.CameraInfo cameraInfo = new Camera.CameraInfo();cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数for (int i = 0; i < cameraCount; i++) {Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息if (cameraPosition == 1) {//现在是后置,变更为前置if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置stopPreview();mCamera = Camera.open(i);//打开当前选中的摄像头try {mCamera.setPreviewDisplay(mSurfaceHolder);//通过surfaceview显示取景画面} catch (IOException e) {e.printStackTrace();}if (mCamera != null && !isView) {try {mCamera.startPreview();//开始预览mCamera.setDisplayOrientation(90);Camera.Parameters parameters = mCamera.getParameters();parameters.setPreviewFrameRate(5);//设置旋转代码parameters.setRotation(90);cameraPosition = 0;changeCameraTimer();} catch (Exception e) {e.printStackTrace();}}break;}} else {//现在是前置, 变更为后置if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置      CAMERA_FACING_BACK后置stopPreview();mCamera = Camera.open(i);//打开当前选中的摄像头try {mCamera.setPreviewDisplay(mSurfaceHolder);//通过surfaceview显示取景画面} catch (IOException e) {e.printStackTrace();}if (mCamera != null && !isView) {try {mCamera.startPreview();//开始预览mCamera.setDisplayOrientation(90);Camera.Parameters parameters = mCamera.getParameters();parameters.setPreviewFrameRate(5);//设置旋转代码parameters.setRotation(90);mCamera.setParameters(parameters);cameraPosition = 1;changeCameraTimer();} catch (Exception e) {e.printStackTrace();}}break;}}}}private boolean isCanChange = true;private void changeCameraTimer() {isCanChange = false;new Timer().schedule(new TimerTask() {@Overridepublic void run() {isCanChange = true;}}, 600);}/*** 获取本地视频的第一帧** @param filePath* @return*/public static Bitmap getVideoFirstFrame(String filePath) {MediaMetadataRetriever mmr = new MediaMetadataRetriever();//实例化MediaMetadataRetriever对象File file = new File(filePath);//实例化File对象,文件路径为/storage/sdcard/Movies/music1.mp4if (file.exists()) {mmr.setDataSource(file.getAbsolutePath());//设置数据源为该文件对象指定的绝对路径Bitmap bitmap = mmr.getFrameAtTime();//获得视频第一帧的Bitmap对象return bitmap;}return null;}/*** 获取网络视频的第一帧** @param videoUrl* @return*/public static Bitmap getVideoFirstFrame_Net(String videoUrl) {Bitmap bitmap = null;MediaMetadataRetriever retriever = new MediaMetadataRetriever();try {//根据url获取缩略图retriever.setDataSource(videoUrl, new HashMap());//获得第一帧图片bitmap = retriever.getFrameAtTime();} catch (Exception e) {e.printStackTrace();} finally {retriever.release();}return bitmap;}//    需要将以下方法放在调用此工具类的Activity/fragment中——解决暂停后无法录制的问题
//    @Override
//    protected void onStart() {//        super.onStart();
//        if (videoUtil == null) return;
//        videoUtil.startPreview();
//    }
//
//    @Override
//    protected void onPause() {//        super.onPause();
//        if (videoUtil == null) return;
//        if (isRecordVideo) {//            videoUtil.stopRecord();
//        }
//        videoUtil.stopPreview();
//        isRecordVideo  = false;
//    }
}

二 帮助类

import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.util.Log;import java.util.Collection;/*** CreateTime 2017/12/4 13:59* Author LiuShiHua* Description:打开和关闭闪光灯*///        <uses-permission android:name="android.permission.FLASHLIGHT" />
//        <uses-permission android:name="android.permission.CAMERA"/>
//        <uses-feature android:name="android.hardware.camera" />
//        <uses-feature android:name="android.hardware.autofocus"/>public class RecordVideoHelper {private static boolean isCanUse = false;private static boolean isOpenFrontCamera = false;//打开闪光灯public static boolean openFlashlight(Camera camera, Context context) {if (isCanUseLight(context, camera)) {isCanUse = true;doSetTorch(camera, true);return true;} else {Log.d("------------->", "手机不支持打开闪光灯");return false;}}//关闭闪光灯public static boolean closeFlashlight(Camera camera) {if (isCanUse) {doSetTorch(camera, false);}return isCanUse;}//是否可以使用闪光灯private static boolean isCanUseLight(Context context, Camera camera) {return camera != null && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);}private static void doSetTorch(Camera camera, boolean newSetting) {Camera.Parameters parameters = camera.getParameters();String flashMode;/** 是否支持闪光灯 */if (newSetting) {flashMode = findSettableValue(parameters.getSupportedFlashModes(), Camera.Parameters.FLASH_MODE_TORCH, Camera.Parameters.FLASH_MODE_ON);} else {flashMode = findSettableValue(parameters.getSupportedFlashModes(), Camera.Parameters.FLASH_MODE_OFF);}if (flashMode != null) {parameters.setFlashMode(flashMode);}camera.setParameters(parameters);}private static String findSettableValue(Collection<String> supportedValues, String... desiredValues) {String result = null;if (supportedValues != null) {for (String desiredValue : desiredValues) {if (supportedValues.contains(desiredValue)) {result = desiredValue;break;}}}return result;}
}

Android 视频录制工具类VideoRecordUtil相关推荐

  1. Camera2视频录制工具类

    Android通过Camera2录制视频,写了个工具类,需要时直接拿来用 import android.Manifest; import android.annotation.SuppressLint ...

  2. android语音播放工具类,Android开发之MediaPlayer多媒体(音频,视频)播放工具类

    本文实例讲述了Android开发之MediaPlayer多媒体(音频,视频)播放工具类.分享给大家供大家参考,具体如下: package com.android.imooc.chat; import ...

  3. 利用FFmpeg玩转Android视频录制与压缩(二)

    请尊重原创,转载请注明出处:http://blog.csdn.net/mabeijianxi/article/details/72983362 预热 时光荏苒,光阴如梭,离上一次吹牛逼已经过去了两三个 ...

  4. 利用FFmpeg玩转Android视频录制与压缩(三)

    请尊重原创,转载请注明出处http://blog.csdn.net/mabeijianxi/article/details/73011313 前言 上一回说到啊,这千秋月没是佳人离别,时逢枯枝落旧城, ...

  5. 用FFmpeg玩转Android视频录制与压缩

    [置顶] 利用FFmpeg玩转Android视频录制与压缩(二) 标签: Android视频采集Android视频编码Android FFmpegAndroid 视频压缩视频编码 2017-06-10 ...

  6. Android视频录制从不入门到入门系列教程(一)————简介

    一.WHY Android SDK提供了MediaRecorder帮助开发者进行视频的录制,不过这个类很鸡肋,实际项目中应该很少用到它,最大的原因我觉得莫过于其输出的视频分辨率太有限了,满足不了项目的 ...

  7. Android视频录制--屏幕录制

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

  8. Android视频录制并转GIF格式

    一.概述 我们在学习Android时候,往往需要查阅很多的资料教程,这时候经常会发现大神写的博客往往都是图文并茂的,充满可能性,效果直观的,所以自己个人记录一些日常工作中遇到的问题以及见解,也希望能够 ...

  9. android 快速开发工具类,android面试知识点

    项目地址:570622566/FastAndrUtils  简介:android 快速开发工具类 更多:作者   提 Bug   官网 标签: Fastandrutils 是一套整理修改整合的 and ...

  10. Android常用的工具类

    2019独角兽企业重金招聘Python工程师标准>>> 最新最准确内容建议直接访问原文:Android常用的工具类 主要介绍总结的Android开发中常用的工具类,大部分同样适用于J ...

最新文章

  1. 看动画学算法之:线段树-segmentTree
  2. 【附超时原因】1055 The World‘s Richest (25 分)_42行代码AC
  3. Linux内核态之间进程通信,内核态和用户态通信(二)--实现
  4. Smark.Data 1.5更新详解
  5. Ubuntu下安装tilix终端仿真器
  6. android png转灰度,Android提高之使用NDK把彩图转换灰度图的方法
  7. 基于CSE的微服务架构实践-Spring Cloud技术栈选型
  8. android打包方法超过65k错误
  9. linux 输入法成繁体字_寻找Ubuntu中繁体字输入法
  10. FastAdmin 文件图片上传失败File size error
  11. QT xml转ini的实现(从C#转到QT)
  12. MATLAB信号处理——信号与系统的分析基础(2)
  13. 无线服务器网速加快,无线路由器网速慢怎么办?
  14. 如何制作点餐小程序?
  15. iphone SLO-MO, TIME-LAPSE, VIDEO,PANO
  16. Java:XML之JavaSE SAX解析
  17. 7-6 然后是几点(15 分)
  18. 判断数组类型的方法(Array.isArray)以及Math数字对象
  19. 鸿蒙系统平板电脑能安装吗,平板电脑已预装鸿蒙系统,我们来看看效果
  20. 纵论物联网(二):LPWAN技术

热门文章

  1. 软件人才应具备的五种素质
  2. compile函数使用
  3. C/S模式与P2P模式的对比
  4. 游戏编程入门(2):创建游戏引擎和使用该引擎制作小游戏
  5. [内附完整源码和文档] 基于PHP的网上购物系统设计与实现
  6. 塞班系统服务器,在Symbian系统邮件应用程序中使用IMAP服务
  7. visual studio 版本的区别
  8. 关于silverlight的xap包与dll分离的一些事儿
  9. 手机里tencent文件夹能删吗_Android系统tencent文件夹下哪些文件可以删除
  10. centos安装Docker与使用构建业务镜像挂载卷harbor仓库的高可用及网络模式和资源限制介绍...