Android 开发 MediaRecorder视频录制入门
<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1><p> MediaRecorder是Android SDK提供用于录制音视频,关于音频的录制在我另一篇博客里已经介绍.传送门: https://www.cnblogs.com/guanxinjing/p/10976026.html ,而这篇博客将介绍MediaRecorder视频录制的入门和一些MediaRecorder视频录制的深坑.为什么只介绍简单的录制视频的入门操作,因为MediaRecorder在实际开发的时候肯定还需要配合Camera来使用.而Camera这个大坑又有Camera1和Camera2,所以我们需要分篇幅来介绍Camera1和Camera2与MediaRecorder的使用方式.</p>
<p> 虽然是入门但是还是需要分2个录制操作来说明</p>
<ul>
<li> <strong> MediaRecorder简单的录制视频(不设置Camera)</strong></li>
<li><strong> MediaRecorder设置Camera的录制视频(这里指的是Camera1)</strong></li>
</ul>
<p> 虽然这2个在简单录制视频的时候操作没啥区别,但是设置Camera录制有一个坑,秉承着写博客就是为了记录深坑避免下次掉坑的精神,所以我要抓出来单独说明.</p>
<h1><span style="color: rgba(0, 128, 128, 1)">MediaRecorder简单的录制视频</span></h1>
<h2><span style="color: rgba(0, 128, 128, 1)">实现流程</span></h2>
<ol>
<li><span style="color: rgba(0, 0, 0, 1)">开启硬件加速(因为个人使用TextureView)</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">获取权限</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">初始化MediaRecorder</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">配置MediaRecorder</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">开始录制视频</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">停止录制视频</span></li>
<li>暂停录制与恢复录制</li>
<li><span style="color: rgba(0, 0, 0, 1)">销毁释放</span></li>
</ol>
<h2><span style="color: rgba(0, 128, 128, 1)">开启硬件加速</span></h2>
<p><span style="color: rgba(0, 0, 0, 1)">因为TextureView来预览图像使用效果会比SurfaceView与SurfaceTexture,在预览的时候更不会那么卡顿.但是使用它需要开启硬件加速,但是现在的手机设备上基本上都支持硬件加速,所以主流是使用<span style="color: rgba(0, 0, 0, 1)">TextureView.下面就是开启硬件加速的方式,在AndroidManifest.xml里给需要硬件加速的activity添加<span style="color: rgba(255, 0, 0, 1)">android:hardwareAccelerated<span style="color: rgba(0, 0, 255, 1)">="true" </span></span></span>属性</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">activity </span><span style="color: rgba(255, 0, 0, 1)">android:name</span><span style="color: rgba(0, 0, 255, 1)">=".MediaRecorderVideoActivity"</span><span style="color: rgba(255, 0, 0, 1)">
android:hardwareAccelerated</span><span style="color: rgba(0, 0, 255, 1)">="true"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">activity</span><span style="color: rgba(0, 0, 255, 1)">></span></pre>
</div>
<h2><span style="color: rgba(0, 128, 128, 1)">获取权限</span></h2>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">音频录制权限 </span><span style="color: rgba(0, 128, 0, 1)">--></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">uses-permission </span><span style="color: rgba(255, 0, 0, 1)">android:name</span><span style="color: rgba(0, 0, 255, 1)">="android.permission.RECORD_AUDIO"</span> <span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">相机权限</span><span style="color: rgba(0, 128, 0, 1)">--></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">uses-permission </span><span style="color: rgba(255, 0, 0, 1)">android:name</span><span style="color: rgba(0, 0, 255, 1)">="android.permission.CAMERA"</span> <span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)">读取和写入存储权限</span><span style="color: rgba(0, 128, 0, 1)">--></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">uses-permission </span><span style="color: rgba(255, 0, 0, 1)">android:name</span><span style="color: rgba(0, 0, 255, 1)">="android.permission.WRITE_EXTERNAL_STORAGE"</span> <span style="color: rgba(0, 0, 255, 1)">/></span>
<span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">uses-permission </span><span style="color: rgba(255, 0, 0, 1)">android:name</span><span style="color: rgba(0, 0, 255, 1)">="android.permission.READ_EXTERNAL_STORAGE"</span> <span style="color: rgba(0, 0, 255, 1)">/></span></pre>
</div>
<p>如果是Android5.0版本这4个权限是需要动态授权的.</p>
<h2><span style="color: rgba(0, 128, 128, 1)">初始化MediaRecorder</span></h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> initMediaRecorder(){
mMediaRecorder </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MediaRecorder();
}</span></pre>
</div>
<p>很简单就是new一个<span style="color: rgba(0, 0, 0, 1)">MediaRecorder</span></p>
<h2><span style="background-color: rgba(255, 255, 255, 1); color: rgba(0, 128, 128, 1)">配置MediaRecorder</span></h2>
<h2> </h2>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> configMediaRecorder(){
File videoFile </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> File(getExternalCacheDir(),"video.mp4"<span style="color: rgba(0, 0, 0, 1)">);
Log.e(TAG, </span>"文件路径="+<span style="color: rgba(0, 0, 0, 1)">videoFile.getAbsolutePath());
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (videoFile.exists()){
videoFile.delete();
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置音频输入源也可以使用 MediaRecorder.AudioSource.MIC</span>
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置视频输入源</span>
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">音频输出格式</span>
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置音频的编码格式</span>
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置图像编码格式
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> mMediaRecorder.setVideoFrameRate(30);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">要录制的视频帧率 帧率越高视频越流畅 如果设置设备不支持的帧率会报错按照注释说设备会支持自动帧率所以一般情况下不需要设置
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> mMediaRecorder.setVideoSize(1280,1920);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置录制视频的分辨率如果设置设备不支持的分辨率会报错</span>
mMediaRecorder.setVideoEncodingBitRate(8*1920*1080); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置比特率,比特率是每一帧所含的字节流数量,比特率越大每帧字节越大,画面就越清晰,算法一般是 5 * 选择分辨率宽 * 选择分辨率高,一般可以调整5-10,比特率过大也会报错</span>
mMediaRecorder.setOrientationHint(90);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置视频的摄像头角度 只会改变录制的视频文件的角度(对预览图像角度没有效果)</span>
<span style="color: rgba(0, 0, 0, 1)">
Surface surface </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Surface(mTextureView.getSurfaceTexture());
mMediaRecorder.setPreviewDisplay(surface);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置拍摄预览</span>
mMediaRecorder.setOutputFile(videoFile.getAbsolutePath());<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">MP4文件保存路径</span>
<span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p>配置<span style="color: rgba(0, 0, 0, 1)">MediaRecorder</span>是坑比较多的地方,现在我们来一一说下这些坑</p>
<ul>
<li>坑1: 首先<span style="color: rgba(0, 0, 0, 1)">MediaRecorder</span>的配置是有顺序要求的,随便配置参数将会报错,一般顺序是 设置音频输入源与视频输入源 > 设置音频编码格式/视频编码格式/音频输出格式 > 设置分辨率/帧率/摄像头角度 > 添加预览 > 添加保存文件路径</li>
<li>坑2: 在上面的代码上我注释了setVideoFrameRate(<span style="color: rgba(0, 0, 128, 1); font-weight: bold">int rate)</span> 与 setVideoSize(<span style="color: rgba(0, 0, 128, 1); font-weight: bold">int width, <span style="color: rgba(0, 0, 128, 1); font-weight: bold">int height)</span></span> 这2个方法,设置录制视频帧率与设置视频分辨率.因为这2个设置的参数都是需要手机设备支持所输入的的值的,随便设置将会抛出 start failed -19 的错误</li>
<li>坑3: setOrientationHint()方法设置角度不会改变预览图像的角度</li>
<li>坑4: <span style="color: rgba(0, 0, 0, 1)">setPreviewDisplay()设置预览,其实只预览录制过程中的图像,停止录制,相机图像预览也停止了.如果想要一直预览就需要操作Camera来实现</span></li>
<li><span style="color: rgba(0, 0, 0, 1)">坑5: 关于各种参数设置的格式(设置视频输入源,音频输入源,音频输出格式,音频编码格式,图像编码),<strong>这里如果你只是实现demo推荐全部使用</strong></span><strong>DEFAULT</strong>,上面的demo图像编码和音频编码使用MP4格式只是一个demo告诉你有很多其他格式.很多情况系统虽然提供了很多格式,但是下各个设备支持的格式是不同的.如果你是大量适配机型最好使用默认格式或者<span style="color: rgba(0, 0, 0, 1)">AAC音频编码格式与H264视频编码格式(目前这2个格式最通用)</span>,如果是只做单一设备开发,可以使用指定格式.</li>
<li>坑6 当你选择默认编码格式录制视频后发现在Ios设备上无法自动播放? 其实是因为默认编码格式选择了IOS设备不支持的格式,Ios只支持<span style="color: rgba(255, 0, 0, 1)"><strong>AAC音频编码格式</strong></span>与<strong><span style="color: rgba(255, 0, 0, 1)">H264视频编码格式</span>,在<span style="color: rgba(255, 0, 0, 1)">正常开发的时候建议使用这2个编码格式(他们是目前最通用的编码格式)</span></strong></li>
</ul>
<p><strong><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)">注意!</span>上面的坑5关于参数配置的问题,</span></strong><span style="color: rgba(0, 0, 0, 1)">当</span><span style="color: rgba(0, 0, 0, 1)">你发现出现MediaRecorder: start failed: -38 或者<strong>其他数值的报错</strong>,一定会去百度,这时候-38报错 百度可能会告诉是MIC没释放或者Camera没释放(Camera没释放的问题我下面那个demo会说明),这的确有可能,但是还有另外一种可能是设置setAudioEncoder或者setVideoEncoder在或者setAudioSource 上出现了问题,比如一些设备是支持setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);但是换调另外一个设备上就不支持了,所以这个时候请切换成setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);默认模式,使用还是重新提醒你如果有需要适配大量机型的APP那么尽量选择默认格式.如果你只是为单一Android设备开发你可以指定格式.</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">小提醒~如果你想一进入Activity就配置MediaRecorder好,那么你就需要设置TextureView的监听setSurfaceTextureListener(SurfaceTextureListener listener),必需它先启动准备好之后在配置MediaRecorder,否则会报错的因为<span style="color: rgba(0, 0, 0, 1)">TextureView</span>在启动activity后需要一段时间初始化启动</span></p>
<p><strong><span style="color: rgba(0, 0, 0, 1)">如果你需要切换摄像头,那么你还需要注意重新配置MediaRecorder时还需要切换角度:</span></strong> </p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">if</span> (mCurrentCameraFacing){ <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">相机前后面向</span>
mMediaRecorder.setOrientationHint(270<span style="color: rgba(0, 0, 0, 1)">);
}</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
mMediaRecorder.setOrientationHint(</span>90<span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<h2><span style="color: rgba(0, 128, 128, 1)">开始录制视频</span></h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> startRecorder(){
configMediaRecorder();<span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)">配置MediaRecorder因为每一次停止录制后调用重置方法后都会取消配置,所以每一次开始录制都需要重新配置一次</span></span>
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
mMediaRecorder.prepare();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">准备</span>
mMediaRecorder.start();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">开启</span>
} <span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e) {
e.printStackTrace();
}
}</span></pre>
</div>
<p><span style="color: rgba(0, 0, 0, 1)">注意!每一次停止录制后调用重置方法后都会取消配置,所以每一次开始录制都需要重新配置一次</span></p>
<h2><span style="color: rgba(0, 128, 128, 1)">停止录制视频</span></h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> stopRecorder(){
mMediaRecorder.stop();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">暂停</span>
mMediaRecorder.reset();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">重置 重置后将进入空闲状态,再次启动录制需要重新配置MediaRecorder</span>
}</pre>
</div>
<h2><span style="color: rgba(0, 128, 128, 1)">暂停录制与恢复录制</span></h2>
<p>暂停录制,注意这里是<span style="color: rgba(0, 0, 0, 1)">pause()方法,不是<span style="color: rgba(0, 0, 0, 1)">stop()</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> pauseRecorder(){
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (Build.VERSION.SDK_INT >=<span style="color: rgba(0, 0, 0, 1)"> Build.VERSION_CODES.N) {
mMediaRecorder.pause();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">暂停</span>
<span style="color: rgba(0, 0, 0, 1)"> }
}</span></pre>
</div>
<p>恢复录制</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> resumeRecorder(){
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (Build.VERSION.SDK_INT >=<span style="color: rgba(0, 0, 0, 1)"> Build.VERSION_CODES.N) {
mMediaRecorder.resume();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">恢复</span>
<span style="color: rgba(0, 0, 0, 1)"> }
}</span></pre>
</div>
<h2><span style="color: rgba(0, 128, 128, 1)">销毁释放</span></h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> destroy(){
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (mMediaRecorder != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
mMediaRecorder.stop();
mMediaRecorder.release();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">释放 释放之前需要先调用stop()</span>
mMediaRecorder = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
}</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)"><strong>MediaRecorder设置Camera的录制视频</strong></span></h1>
<p>添加Camera来录制视频本来是另外一个篇幅应该说的事情,但是有个坑不得不在这里先说. 其他初始化和开启/停止/都与上面的介绍一致,下面我们来说说万恶的<span style="color: rgba(0, 0, 0, 1)">MediaRecorder</span>配置:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> configMediaRecorder(){
File videoFile </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> File(getExternalCacheDir(),"video.mp4"<span style="color: rgba(0, 0, 0, 1)">);
Log.e(TAG, </span>"文件路径="+<span style="color: rgba(0, 0, 0, 1)">videoFile.getAbsolutePath());
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (videoFile.exists()){
videoFile.delete();
}
Camera camera </span>=<span style="color: rgba(0, 0, 0, 1)"> Camera.open();
camera.unlock();
mMediaRecorder.setCamera(camera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置音频输入源</span>
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置视频输入源</span>
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">音频输出格式</span>
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置音频的编码格式</span>
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置图像编码格式</span>
mMediaRecorder.setOrientationHint(90);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置视频的摄像头角度 只会改变录制的视频角度</span>
Surface surface = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Surface(mTextureView.getSurfaceTexture());
mMediaRecorder.setPreviewDisplay(surface);
mMediaRecorder.setOutputFile(videoFile.getAbsolutePath());
}</span></pre>
</div>
<p> 也是一个简单的配置,也就是多了有摄像头的代码,如果你需要选择摄像头可以自己获取摄像头信息来判断前后在获取对应id,打开对应摄像头,作为简单的demo就暂时不演示选择摄像头的代码.</p>
<p> 然后重点来了这里有一个关键,你不会想到<span style="color: rgba(0, 0, 0, 1)">Camera.open();</span>执行后摄像头居然是锁定状态的,就算是明白打开后就是锁定,但是你也不会发现在设置<span style="color: rgba(0, 0, 0, 1)">mMediaRecorder.setCamera(camera);之前是需要将摄像头解除锁定<span style="color: rgba(0, 0, 0, 1)"> camera.unlock();! 是的,就是这行代码困扰我了一下午!!!!!! 所以<strong><span style="color: rgba(255, 0, 0, 1)">重点!重点!重点! 就是</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)">camera.unlock();</span> </span></span></strong><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">最</span></span></span></span>蛋疼的是如果你不做解除锁定的操作报错的提示是 start failed -19, 这个报错提示成功的让我反反复复研究是不是分辨率尺寸设置有问题........</p>
<p> 而这个Camera.unlock()在官方注释里也有说明在启动在设置之前先需要解锁摄像头,如下:</p>
<div class="cnblogs_code">
<pre> * <p>Use <span style="color: rgba(0, 0, 255, 1)">this</span> function to <span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)"> quickly between preview and capture mode without a teardown of
</span>* the camera <span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)">. {@link android.hardware.Camera#unlock()} should be called before
</span>* <span style="color: rgba(0, 0, 255, 1)">this</span>. Must call before {@link #prepare}.</p></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">setProfile</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">这个功能其实是相机预设的一些录制质量,格式和分辨率,官方注释说:</span></p>
<p class="ordinary-output target-output clearfix"><span><strong>使用CamcorderProfile对象中的设置进行录制。这种方法应该在设置视频和音频源之后和setOutputfile()之前调用。如果使用延时摄像机配置文件,音频相关源或录制参数被忽略。</strong> </span></p>
<p class="ordinary-output target-output clearfix"><span>我们看到关键CamcorderProfile对象,那么看看什么CamcorderProfile的解释:</span></p>
<p class="ordinary-output target-output clearfix"><strong>摄像机应用程序的预定义摄像机配置文件设置,这些设置是只读的。其实就是预设的一些摄像头配置设置</strong></p>
<p class="ordinary-output target-output clearfix">预设的属性有这些:</p>
<ul>
<li class="ordinary-output target-output clearfix">QUALITY_LOW</li>
<li class="ordinary-output target-output clearfix">QUALITY_HIGH</li>
<li class="ordinary-output target-output clearfix">QUALITY_QCIF</li>
<li class="ordinary-output target-output clearfix">QUALITY_CIF</li>
<li class="ordinary-output target-output clearfix">QUALITY_480P</li>
<li class="ordinary-output target-output clearfix">QUALITY_720P</li>
<li class="ordinary-output target-output clearfix">QUALITY_1080P</li>
<li class="ordinary-output target-output clearfix">QUALITY_2160P</li>
<li class="ordinary-output target-output clearfix">QUALITY_TIME_LAPSE_LOW</li>
<li class="ordinary-output target-output clearfix">QUALITY_TIME_LAPSE_HIGH</li>
<li class="ordinary-output target-output clearfix">QUALITY_TIME_LAPSE_QCIF</li>
<li class="ordinary-output target-output clearfix">QUALITY_TIME_LAPSE_CIF</li>
<li class="ordinary-output target-output clearfix">QUALITY_TIME_LAPSE_480P</li>
<li class="ordinary-output target-output clearfix">QUALITY_TIME_LAPSE_720P</li>
<li class="ordinary-output target-output clearfix">QUALITY_TIME_LAPSE_1080P</li>
<li class="ordinary-output target-output clearfix">QUALITY_TIME_LAPSE_2160P</li>
<li class="ordinary-output target-output clearfix">QUALITY_HIGH_SPEED_LOW</li>
<li class="ordinary-output target-output clearfix">QUALITY_HIGH_SPEED_HIGH</li>
<li class="ordinary-output target-output clearfix">QUALITY_HIGH_SPEED_480P</li>
<li class="ordinary-output target-output clearfix">QUALITY_HIGH_SPEED_720P</li>
<li class="ordinary-output target-output clearfix">QUALITY_HIGH_SPEED_1080P</li>
<li class="ordinary-output target-output clearfix">QUALITY_HIGH_SPEED_2160P</li>
</ul>
<p class="ordinary-output target-output clearfix"><strong>使用代码:</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) {
CamcorderProfile profile </span>=<span style="color: rgba(0, 0, 0, 1)"> CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
profile.videoBitRate </span>= mPreviewSize.getWidth() *<span style="color: rgba(0, 0, 0, 1)"> mPreviewSize.getHeight();
mMediaRecorder.setProfile(profile);
mMediaRecorder.setPreviewDisplay(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Surface(mTextureView.getSurfaceTexture()));
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) {
CamcorderProfile profile </span>=<span style="color: rgba(0, 0, 0, 1)"> CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
profile.videoBitRate </span>= mPreviewSize.getWidth() *<span style="color: rgba(0, 0, 0, 1)"> mPreviewSize.getHeight();
mMediaRecorder.setProfile(profile);
mMediaRecorder.setPreviewDisplay(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Surface(mTextureView.getSurfaceTexture()));
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QVGA)) {
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA));
mMediaRecorder.setPreviewDisplay(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Surface(mTextureView.getSurfaceTexture()));
} </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_CIF)) {
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_CIF));
mMediaRecorder.setPreviewDisplay(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Surface(mTextureView.getSurfaceTexture()));
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setVideoEncodingBitRate(</span>10000000<span style="color: rgba(0, 0, 0, 1)">);
mMediaRecorder.setVideoFrameRate(</span>30<span style="color: rgba(0, 0, 0, 1)">);
mMediaRecorder.setVideoSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
}</span></pre>
</div>
<p> </p>
<p> </p>
<p><span style="color: rgba(0, 128, 128, 1)">end</span></p>
</div>
<div id="MySignature" role="contentinfo">
<div style="text-align: center">
<p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/10980906.html </p>
<div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/10980906.html
頁:
[1]