MediaRecorder是Android SDK提供用于录制音视频,关于音频的录制在我另外一篇博客里已经介绍.传送门: http://www.javashuo.com/article/p-qswhcuuw-ez.html,而这篇博客将介绍MediaRecorder视频录制的入门和一些MediaRecorder视频录制的深坑.为何只介绍简单的录制视频的入门操做,由于MediaRecorder在实际开发的时候确定还须要配合Camera来使用.而Camera这个大坑又有Camera1和Camera2,因此咱们须要分篇幅来介绍Camera1和Camera2与MediaRecorder的使用方式.html
虽然是入门可是仍是须要分2个录制操做来讲明android
虽然这2个在简单录制视频的时候操做没啥区别,可是设置Camera录制有一个坑,秉承着写博客就是为了记录深坑避免下次掉坑的精神,因此我要抓出来单独说明.算法
由于TextureView来预览图像使用效果会比SurfaceView与SurfaceTexture,在预览的时候更不会那么卡顿.可是使用它须要开启硬件加速,可是如今的手机设备上基本上都支持硬件加速,因此主流是使用TextureView.下面就是开启硬件加速的方式,在AndroidManifest.xml里给须要硬件加速的activity添加android:hardwareAccelerated="true" 属性ide
<activity android:name=".MediaRecorderVideoActivity" android:hardwareAccelerated="true"></activity>
<!--音频录制权限 --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!--相机权限--> <uses-permission android:name="android.permission.CAMERA" /> <!--读取和写入存储权限--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
若是是Android5.0版本这4个权限是须要动态受权的.ui
private void initMediaRecorder(){ mMediaRecorder = new MediaRecorder(); }
很简单就是new一个MediaRecorderthis
private void configMediaRecorder(){ File videoFile = new File(getExternalCacheDir(),"video.mp4"); Log.e(TAG, "文件路径="+videoFile.getAbsolutePath()); if (videoFile.exists()){ videoFile.delete(); } mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);//设置音频输入源 也可使用 MediaRecorder.AudioSource.MIC mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//设置视频输入源 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//音频输出格式 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);//设置音频的编码格式 mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);//设置图像编码格式 // mMediaRecorder.setVideoFrameRate(30);//要录制的视频帧率 帧率越高视频越流畅 若是设置设备不支持的帧率会报错 按照注释说设备会支持自动帧率因此通常状况下不须要设置 // mMediaRecorder.setVideoSize(1280,1920);//设置录制视频的分辨率 若是设置设备不支持的分辨率会报错 mMediaRecorder.setVideoEncodingBitRate(8*1920*1080); //设置比特率,比特率是每一帧所含的字节流数量,比特率越大每帧字节越大,画面就越清晰,算法通常是 5 * 选择分辨率宽 * 选择分辨率高,通常能够调整5-10,比特率过大也会报错 mMediaRecorder.setOrientationHint(90);//设置视频的摄像头角度 只会改变录制的视频文件的角度(对预览图像角度没有效果) Surface surface = new Surface(mTextureView.getSurfaceTexture()); mMediaRecorder.setPreviewDisplay(surface);//设置拍摄预览 mMediaRecorder.setOutputFile(videoFile.getAbsolutePath());//MP4文件保存路径 }
配置MediaRecorder是坑比较多的地方,如今咱们来一一说下这些坑编码
注意!上面的坑5关于参数配置的问题,当你发现出现MediaRecorder: start failed: -38 或者其余数值的报错,必定会去百度,这时候-38报错 百度可能会告诉是MIC没释放或者Camera没释放(Camera没释放的问题我下面那个demo会说明),这的确有可能,可是还有另一种多是设置setAudioEncoder或者setVideoEncoder在或者setAudioSource 上出现了问题,好比一些设备是支持setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);可是换调另一个设备上就不支持了,因此这个时候请切换成setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);默认模式,使用仍是从新提醒你若是有须要适配大量机型的APP那么尽可能选择默认格式.若是你只是为单一Android设备开发你能够指定格式.spa
小提醒~若是你想一进入Activity就配置MediaRecorder好,那么你就须要设置TextureView的监听setSurfaceTextureListener(SurfaceTextureListener listener),必需它先启动准备好以后在配置MediaRecorder,不然会报错的由于TextureView在启动activity后须要一段时间初始化启动code
private void startRecorder(){ configMediaRecorder();//配置MediaRecorder 由于每一次中止录制后调用重置方法后都会取消配置,因此每一次开始录制都须要从新配置一次 try { mMediaRecorder.prepare();//准备 mMediaRecorder.start();//开启 } catch (IOException e) { e.printStackTrace(); } }
注意!每一次中止录制后调用重置方法后都会取消配置,因此每一次开始录制都须要从新配置一次orm
private void stopRecorder(){ mMediaRecorder.stop();//暂停 mMediaRecorder.reset();//重置 重置后将进入空闲状态,再次启动录制须要从新配置MediaRecorder }
暂停录制,注意这里是pause()方法,不是stop()
private void pauseRecorder(){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mMediaRecorder.pause();//暂停 } }
恢复录制
private void resumeRecorder(){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mMediaRecorder.resume();//恢复 } }
private void destroy(){ if (mMediaRecorder != null){ mMediaRecorder.stop(); mMediaRecorder.release();//释放 释放以前须要先调用stop() mMediaRecorder = null; } }
添加Camera来录制视频原本是另一个篇幅应该说的事情,可是有个坑不得不在这里先说. 其余初始化和开启/中止/都与上面的介绍一致,下面咱们来讲说万恶的MediaRecorder配置:
private void configMediaRecorder(){ File videoFile = new File(getExternalCacheDir(),"video.mp4"); Log.e(TAG, "文件路径="+videoFile.getAbsolutePath()); if (videoFile.exists()){ videoFile.delete(); } Camera camera = Camera.open(); camera.unlock(); mMediaRecorder.setCamera(camera); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置音频输入源 mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//设置视频输入源 mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//音频输出格式 mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);//设置音频的编码格式 mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);//设置图像编码格式 mMediaRecorder.setOrientationHint(90);//设置视频的摄像头角度 只会改变录制的视频角度 Surface surface = new Surface(mTextureView.getSurfaceTexture()); mMediaRecorder.setPreviewDisplay(surface); mMediaRecorder.setOutputFile(videoFile.getAbsolutePath()); }
也是一个简单的配置,也就是多了有摄像头的代码,若是你须要选择摄像头能够本身获取摄像头信息来判断先后在获取对应id,打开对应摄像头,做为简单的demo就暂时不演示选择摄像头的代码.
而后重点来了这里有一个关键,你不会想到Camera.open();执行后摄像头竟然是锁定状态的,就算是明白打开后就是锁定,可是你也不会发如今设置mMediaRecorder.setCamera(camera);以前是须要将摄像头解除锁定 camera.unlock();! 是的,就是这行代码困扰我了一下午!!!!!! 因此重点!重点!重点! 就是camera.unlock(); 最蛋疼的是若是你不作解除锁定的操做报错的提示是 start failed -19, 这个报错提示成功的让我反反复复研究是否是分辨率尺寸设置有问题........
而这个Camera.unlock()在官方注释里也有说明在启动在设置以前先须要解锁摄像头,以下:
* <p>Use this function to switch quickly between preview and capture mode without a teardown of * the camera object. {@link android.hardware.Camera#unlock()} should be called before * this. Must call before {@link #prepare}.</p>
这个功能实际上是相机预设的一些录制质量,格式和分辨率,官方注释说:
使用CamcorderProfile对象中的设置进行录制。这种方法应该在设置视频和音频源以后和setOutputfile()以前调用。若是使用延时摄像机配置文件,音频相关源或录制参数被忽略。
咱们看到关键CamcorderProfile对象,那么看看什么CamcorderProfile的解释:
摄像机应用程序的预约义摄像机配置文件设置,这些设置是只读的。其实就是预设的一些摄像头配置设置
预设的属性有这些:
使用代码:
if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) { CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P); profile.videoBitRate = mPreviewSize.getWidth() * mPreviewSize.getHeight(); mMediaRecorder.setProfile(profile); mMediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture())); } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) { CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P); profile.videoBitRate = mPreviewSize.getWidth() * mPreviewSize.getHeight(); mMediaRecorder.setProfile(profile); mMediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture())); } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QVGA)) { mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA)); mMediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture())); } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_CIF)) { mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_CIF)); mMediaRecorder.setPreviewDisplay(new Surface(mTextureView.getSurfaceTexture())); } else { mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mMediaRecorder.setVideoEncodingBitRate(10000000); mMediaRecorder.setVideoFrameRate(30); mMediaRecorder.setVideoSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); }
end