Android视频录制
2016-08-26 00:57
239 查看
今天呢介绍一个简单的预览拍摄例子,也是项目中用到的,在Android 4.4以上的手机都是可以支持的,并且支持切换前后置摄像头,开关闪光灯,自动对焦。
下面正式开始:
1.首先我们自定义一个控件,它继承于LinearLayout:
实现上面几个接口要重写以下几个方法,
上面两个方法一个是视频录制时得到的信息函数,一个是录制过程中出现error时的回调函数,具体处理也很简单直接reset掉就可以了
下面来就是预览控件了
这个SurfaceView就是我们需要的,里面获得的suerfaceHolder就是用来预览拍摄视频,
那么怎么把Camera捕捉到的画面放到surfaceView里面去呢,对了就是这个addCallback方法:
里面重写了三方方法,对应着调用他们应该打开Camera,设置Camera参数,和释放Camera,很好理解
突然间我们发现一个函数叫做getAutoFocus,干嘛的?看名字就明白了是用来自动对焦的,这种方法在4.4到6.0上的手机都是有效的
然后这个你用完了记得一定要释放camera也就是freeCameraResource
这样一个简单的视频预览拍摄页面就完成了。
下面这个是打开和关闭闪光灯的方法
没什么难的,看一下就明白了。
下面就是录制过程了,不多说了,直接上代码,里面设置了一些参数看名字就能猜出来个八九不离十了,
如果录制视频不满意则调用这个函数
如果ok拍摄的视频是合格的那么调用下面这个函数
接口
在你的Activity或者fragment中implement这个接口,就可以实现对拍好的视频进行回调方法的处理。
OK,简单的视频拍摄就是这些,后面会把Demo地址更新上来。
下面正式开始:
1.首先我们自定义一个控件,它继承于LinearLayout:
public class RecorderView extends LinearLayout implements MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener { /*这里是代码*/ }
实现上面几个接口要重写以下几个方法,
@Override public void onInfo(MediaRecorder mr, int what, int extra) { try { } catch (Exception e) { } } @Override public void onError(MediaRecorder mr, int what, int extra) { try { if (mr != null) mr.reset(); } catch (Exception e) { } }
上面两个方法一个是视频录制时得到的信息函数,一个是录制过程中出现error时的回调函数,具体处理也很简单直接reset掉就可以了
下面来就是预览控件了
private SurfaceView surfaceView; private SurfaceHolder surfaceHoler; @TargetApi(Build.VERSION_CODES.HONEYCOMB) public RecorderView(Context context, AttributeSet attrs) { super(context, attrs, 0); this.context = context; init(); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) public RecorderView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; } private void init() { LayoutInflater.from(context).inflate(R.layout.ui_recorder, this); surfaceView = (SurfaceView) findViewById(R.id.surfaceview); surfaceHoler = surfaceView.getHolder(); surfaceHoler.addCallback(new VideoCallBack()); surfaceHoler.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.setFocusable(true); surfaceHoler.setKeepScreenOn(true); }
这个SurfaceView就是我们需要的,里面获得的suerfaceHolder就是用来预览拍摄视频,
那么怎么把Camera捕捉到的画面放到surfaceView里面去呢,对了就是这个addCallback方法:
class VideoCallBack implements SurfaceHolder.Callback { @Override public void surfaceCreated(SurfaceHolder holder) { switchCamera(false); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) { startPreView(); } @Override public void surfaceDestroyed(SurfaceHolder holder{ freeCameraResource(); } }
里面重写了三方方法,对应着调用他们应该打开Camera,设置Camera参数,和释放Camera,很好理解
//选择打开前置还是后置摄像头 @TargetApi(Build 4000 .VERSION_CODES.GINGERBREAD) public void switchCamera(boolean isFroCam) { freeCameraResource(); try { if (!isFroCam) { camera = Camera.open(CameraInfo.CAMERA_FACING_BACK); } else { camera = Camera.open(CameraInfo.CAMERA_FACING_FRONT); isFrontCamera = true; } } catch (Exception e) { e.printStackTrace(); } }
//设置camera参数,这里无论是前置还是后置摄像头都要转90度 public void startPreView(){ camera.stopPreview(); if (camera == null) return; try { camera.setDisplayOrientation(90); cameraParameters = camera.getParameters(); cameraParameters.setPreviewSize(1280, 720); camera.setPreviewDisplay(surfaceHoler); getAutoFocus(); camera.setParameters(cameraParameters); camera.setPreviewDisplay(surfaceHoler); camera.startPreview(); camera.unlock(); } catch (IOException e) { e.printStackTrace(); } }
突然间我们发现一个函数叫做getAutoFocus,干嘛的?看名字就明白了是用来自动对焦的,这种方法在4.4到6.0上的手机都是有效的
public void getAutoFocus() { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) { List<String> focusModes = cameraParameters.getSupportedFocusModes(); if (focusModes != null) { if (((Build.MODEL.startsWith("GT-I950")) || (Build.MODEL.endsWith("SCH-I959")) || (Build.MODEL.endsWith("MEIZU MX3")))&& focusModes .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { cameraParameters.setFocusMode (Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } else if (focusModes .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { cameraParameters .setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } } } }
然后这个你用完了记得一定要释放camera也就是freeCameraResource
public void freeCameraResource() { if (null != camera) { camera.setPreviewCallback(null); camera.stopPreview(); camera.lock(); camera.release(); camera = null; } }
这样一个简单的视频预览拍摄页面就完成了。
下面这个是打开和关闭闪光灯的方法
public void openflashlight() { if (camera == null) return; camera.lock(); try { if (!isFlashOn) { isFlashOn = true; cameraParameters.setFlashMode(Parameters.FLASH_MODE_TORCH); } else { cameraParameters.setFlashMode(Parameters.FLASH_MODE_OFF); isFlashOn = false; } camera.setParameters(cameraParameters); } catch (Exception e) { return; } camera.unlock(); }
没什么难的,看一下就明白了。
下面就是录制过程了,不多说了,直接上代码,里面设置了一些参数看名字就能猜出来个八九不离十了,
public void startRecord() { if (isRecording) return; createRecordDir(); initRecord(isFrontCamera); prepareRecord(); }
//建立一个文件夹,并给拍摄的视频起个名字 private void createRecordDir() { File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "You_video/"); if (!sampleDir.exists()) { sampleDir.mkdirs(); } try { startTime = String.valueOf(System.currentTimeMillis()); fileName = "you_video_name" + startTime + ".mp4"; vecordFile = new File(sampleDir.toString(), fileName); } catch (Exception e) { e.printStackTrace(); } }
//设置录制视频的各种参数,在这里前后摄像头录制时设置的旋转角度是不 //一样的 @TargetApi(Build.VERSION_CODES.GINGERBREAD) private void initRecord(boolean isFrontCamera) { mediaRecorder = new MediaRecorder(); mediaRecorder.reset(); if (camera != null) mediaRecorder.setCamera(camera); mediaRecorder.setOnInfoListener(this); mediaRecorder.setOnErrorListener(this); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); try { CamcorderProfile camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); mediaRecorder.setProfile(camcorderProfile); } catch (RuntimeException re) { try { mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); } catch (Exception e) { } } try { mediaRecorder.setVideoSize(1280, 720); } catch (Exception e) { } mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024); if (!isFrontCamera) { mediaRecorder.setOrientationHint(90); } else { mediaRecorder.setOrientationHint(270); } mediaRecorder.setMaxDuration(recordMaxTime * 1000); mediaRecorder.setOutputFile(vecordFile.getAbsolutePath()); mediaRecorder.setPreviewDisplay(surfaceHoler.getSurface()); }
//真正的开始录制是在这里 private void prepareRecord() { try { mediaRecorder.prepare(); mediaRecorder.start(); } catch (IOException e) { e.printStackTrace(); } catch (RuntimeException re) { return; } }
如果录制视频不满意则调用这个函数
public void cancelRecord(boolean cancel) { surfaceView.setVisibility(View.VISIBLE); if (!isRecording) return; isRecording = false; stopRecord(); releaseRecord(); freeCameraResource(); if (vecordFile.exists()) vecordFile.delete(); }
private void stopRecord() { if (mediaRecorder != null) { mediaRecorder.setOnErrorListener(null); mediaRecorder.setPreviewDisplay(null); try { mediaRecorder.stop(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (RuntimeException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
public void releaseRecord() { if (mediaRecorder != null) { mediaRecorder.setOnErrorListener(null); try { mediaRecorder.release(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } mediaRecorder = null; }
如果ok拍摄的视频是合格的那么调用下面这个函数
private void completeRecord(PlayVideoListener playVideoListener) { if (mediaRecorder != null) { mediaRecorder.setOnErrorListener(null); mediaRecorder.setPreviewDisplay(null); try { mediaRecorder.stop(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (RuntimeException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } playVideoListener.callBackToPlayVideo(vecordFile.getAbsolutePath(), startTime, fileName); } }
接口
public interface PlayVideoListener { void callBackToPlayVideo(String videoPath,String startTime,String fileName); }
在你的Activity或者fragment中implement这个接口,就可以实现对拍好的视频进行回调方法的处理。
OK,简单的视频拍摄就是这些,后面会把Demo地址更新上来。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories