用户权限获取
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="true" />
<!--保证有硬件支持-->
使用TextureView预览Camera的像
在activity的onCreate方法中调用:
//调用摄像头
myTexture = (TextureView) findViewById(R.id.texture);
if (myTexture != null) {
myTexture.setSurfaceTextureListener(this);
}
设置继承自本身的监听器TextureView.SurfaceTextureListener,重载以下方法
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
openCamera(Camera.CameraInfo.CAMERA_FACING_BACK,surface);
this.surface = surface;
}
下面提供一个打开摄像头并且设置全屏预览方法,也就是上面的openCamera()
/**
* 打开摄像头
* @param position 摄像头位置
*/
public void openCamera(int position,SurfaceTexture surface){
current_camera = position;
camera = Camera.open(position);//打开摄像头
parameters= camera.getParameters();//设置参数 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//设置自动对焦
try {
parameters.setPreviewSize(1920,1080);//设置预览尺寸,为了全屏展示,我们选择最大尺寸,同时TextureView也应该是match_parent全屏
camera.setParameters(parameters);//设置相机的参数
camera.setDisplayOrientation(90);//设置显示翻转,为0则是水平录像,90为竖屏
camera.setPreviewTexture(surface);//将onSurfaceTextureAvailable监听中的surface传入进来,设置预览的控件
} catch (IOException t) {
Log.d(TAG, "onSurfaceTextureAvailable: IO异常");
}
camera.startPreview();//开始预览
myTexture.setAlpha(1.0f);
}
MediaRecorder设置录制视频时的参数
/**
* 录制视频
*/
public void record(){
Log.d(TAG, "record: 开始录制");
mediaRecorder = new MediaRecorder();
camera.unlock();
mediaRecorder.setCamera(camera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
// mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); //setProfile不能和后面的setOutputFormat等方法一起使用
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 设置视频的输出格式 为MP4
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); // 设置音频的编码格式
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置视频的编码格式
// mediaRecorder.setVideoSize(176, 144); // 设置视频大小
// mediaRecorder.setVideoSize(320, 240); // 设置视频大小
mediaRecorder.setVideoSize(1920, 1080); // 设置视频大小
mediaRecorder.setVideoEncodingBitRate(5*1024*1024);
mediaRecorder.setVideoFrameRate(60); // 设置帧率
/*
* 设置视频文件的翻转角度
* 改变保存后的视频文件播放时是否横屏(不加这句,视频文件播放的时候角度是反的)
* */
if (current_camera == Camera.CameraInfo.CAMERA_FACING_FRONT){
mediaRecorder.setOrientationHint(270);
}else if (current_camera == Camera.CameraInfo.CAMERA_FACING_BACK){
mediaRecorder.setOrientationHint(90);
}
// mRecorder.setMaxDuration(10000); //设置最大录像时间为10s
// mediaRecorder.setPreviewDisplay();
// mediaRecorder.setPreviewDisplay(myTexture);
//设置视频存储路径
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + File.separator + "yuewu");
if (!file.exists()) {
//多级文件夹的创建
file.mkdirs();
}
Log.d(TAG, "record: path " +file.getPath() + File.separator + "乐舞_" + System.currentTimeMillis() + ".mp4");
mediaRecorder.setOutputFile(file.getPath() + File.separator + "乐舞_" + System.currentTimeMillis() + ".mp4");
//开始录制
try {
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IOException e) {
e.printStackTrace();
}
}
上面的代码有很多坑,首先setOutputFormat()方法必须在setAudioResource和setVideoResource之后,prepare()之前。源码给出的解释如下:
/**
* Sets the format of the output file produced during recording. Call this
* after setAudioSource()/setVideoSource() but before prepare().
*
*It is recommended to always use 3GP format when using the H.263
* video encoder and AMR audio encoder. Using an MPEG-4 container format
* may confuse some desktop players.
*
* @param output_format the output format to use. The output format
* needs to be specified before setting recording-parameters or encoders.
* @throws IllegalStateException if it is called after prepare() or before
* setAudioSource()/setVideoSource().
* @see android.media.MediaRecorder.OutputFormat
*/
如果使用了setOutputFormate()方法,就不应该使用setProfile方法了,本人亲测使用了setProfile方法之后,后面有关mediaRecorder对象的其他参数就不应该被设置,否则就会报illegalStateException,也就是说在这一个方法中就可以完成低质量和高质量的设置。
不过还是希望大家不要使用setProfile这个方法,这个方法不够灵活。我们可以自定义MediaRecorder的一些设置。高清视频的设置主要是以下几个方法:
mediaRecorder.setVideoSize(1920, 1080); // 设置视频大小
mediaRecorder.setVideoEncodingBitRate(5*1024*1024);
mediaRecorder.setVideoFrameRate(60); // 设置帧率
帧率越高,size越大(size是指录像时预览的size和保存的视频尺寸,我们和上面设置的预览size保持一致),bit流越大,视频质量就越高。如果需要低质量的视频就从这几个参数中修改就行了。
停止录制
停止录制的方法也很简单,方法如下:
/**
* 停止录制
*/
public void stop(){
// mediaRecorder.setOnErrorListener(null);
// mediaRecorder.setOnInfoListener(null);
camera.lock();
mediaRecorder.stop();
mediaRecorder.release();
openCamera(Camera.CameraInfo.CAMERA_FACING_BACK,surface);//启动预览,可以判断之前是前置摄像头还是后置摄像头来继续启动预览
Log.d(TAG, "stop: 录制完成");
}