以前写过一个视频录制功能,最近又看了一下,重新修复了一些问题。由于代码比较长,我就不给大家去一点一点的讲解了,在代码中我都注释的很详细了,在这只是罗列出来一些注意的事项,代码大家可在文末进行下载。ok,先上一张效果图:
怎么样,从效果上看还是可以的吧!视频录制功能包括:摄像头的切换、闪光灯的开启、视频录制并保存、摄像头自动对焦 功能。需要注意的是一旦视频录制开始就能有办法切换摄像头或者开启闪光灯了。录制视频这个功能用到的类:Camera + surfaceView + MediaRecord,整个视频录制这个功能我封装成了一个类:MovieRecorderView,类布局就是我们按到的surfaceViw 和 下面的进度条。蓝色部分则是在activity中定义的。代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.mediarecorddemo.view.MovieRecorderView
android:id="@+id/vr_record"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="@+id/vr_controller_lay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:background="#46a3e7">
<ImageView
android:id="@+id/vr_change_ca"
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_centerVertical="true"
android:layout_marginRight="34dp"
android:layout_toLeftOf="@+id/vr_turn"
android:src="@drawable/camera_button" />
<ImageView
android:id="@+id/vr_turn"
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_centerInParent="true"
android:background="@drawable/camera"
android:button="@null" />
<RelativeLayout
android:layout_width="43dp"
android:layout_height="43dp"
android:layout_centerVertical="true"
android:layout_marginLeft="34dp"
android:layout_toRightOf="@id/vr_turn">
<ImageView
android:id="@+id/vr_flash"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/flashlig_off" />
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
默认情况下视频录制不能少于5秒,一旦是录制视频开始之后在5秒之内是不能点击关闭按钮的,这个最小录制时长和最大录制时长当然都是可以调节的,可在自定义的时间进度条中调节属性值。代码如下:
<!--use custom view -->
<com.mediarecorddemo.view.VideoRecordProgressBar
android:id="@+id/vr_progress"
android:layout_width="match_parent"
android:layout_height="22dp"
app:progress="0"
app:progress_color="#c62c2c"
app:valid_time="5"
app:max_time="240"/>
其中 progress 属性:初始的进度条位置, progress_color:进度条的颜色,valid_time:最低录制视频时间秒为单位,max_time:最大录制视频时间秒为单位。关于自定义View,就不在多说了,如果有人不懂的话可参照 http://blog.csdn.net/wning1/article/details/52734829 博客,
在这里我就不在多说了。
注意事项:
(1)Camera 初始化
未开始视频录制,界面的预览是通过Camera+surfaceView实现的,摄像头默认是横向设置的所以初始化参数的时候要纵向,另外就是surfaceView的生命周期问题:当activity处于后台之后(点击Home键,或者是跳转到另外一个Activity),surfaceView 都会自动销毁掉,当Activity再次处于前台的时候surfaceView又自动创建出来,这个我们控制不了,只能是说根据surfaceView的生命周期做相应的改变。比如一开始Carame 绑定好了surfaceView这个时候是可以进行摄像头预览的,但是一旦当我们切换到后台在切换回来发现预览界面不见了,这个原因很简单:camera绑定的surfaceView因为生命周期问题已经被销毁掉了,所以从后台切换回来的时候就看不到预览界面了,解决方法:在surfaceView从新创建之后,camera 和 surfaView的生命周期共存.代码如下:
private class CustomCallBack implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
initCamera();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (holder.getSurface() == null) {
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
}
try {
<span style="background-color: rgb(255, 0, 0);"> mCamera.setPreviewDisplay(holder);
mCamera.startPreview();</span>
} catch (Exception e) {
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
freeCameraResource();
}
}
surfaceCreated() 是 surfaceView 创建时执行的方法,在这里面我们初始化camera. surfaceChange()这个方法在界面切换回来之后就会执行这个方法(这个方法是在执行完surfaceCreate()之后执行的,至少执行1次),所以我么在这个里面让Camera 绑定好surfaView 然后 startPreview 即可。surfaceDestroyed()是界面切换到后台执行的方法,这个时候我们要释放调camera资源。
(2)mediaRecoder的初始化
MediaRecorder 的初始化比较严格,按照我写的步骤即可,这个没什么好说,需要注意的是:outputFormat 支持格式有限,好像就只能是MP4 和 3gp 。还有videoSize()这个参数设置起来相当的头疼啊!不同的手机支持不同的视频录制尺寸,android 手机简直是太多了,为什么不统一一下视频录制的尺寸规格呢.....哎!一般不要设置奇葩的尺寸,不然视频是录制不了的,还有可能出现ANR异常。一般情况下大部分手机支持:1920x1088,1280x960,1280x720,960x540,720x540,720x480,640x480,352x288,320x240,176x144。但也有那个脑残的手机例外。我记着原来写项目的时候老板让录制出来的视频是480*480,所以没办法只能录制一个640*480的视频,录制出来之后对视频做裁剪,视频裁剪我使用的是FFMPEG,如果你不懂的话请参照 http://blog.csdn.net/wning1/article/details/52029427 在这里我就不多说了,如果你不是太懂视频压缩这一块,可以给我留言,我最近也在想要不要写一篇视频压缩的博客。setVideoEncodingBitRate 设置视频的采样率,采样率越高视频越清晰,但是录制出来的是视频也会越大,这个要去中间值,我在这取了2*1024*1024这是我经过不断测试得出的,如果你设置的是MP4格式,那么视频编码就是H264。
另外使用MediaRecorder还存在一点问题,还是和surfaceView的生命周期有关,surfaceView一旦销毁掉之后(处于后台的情况),这个时候就不能再继续录制了,唯一的办法就是录制录制保存录制视频。这个如果你看手机自带的录制视频软件也是这样的,具体的做法就是在activity的onPause()方法中去关闭mediaRecorder,保存视频就行了。
(3)权限问题
android 6.0之后,用户在不同意我们项目中所规定的所有权限,也能安装上软件,这就有极大的可能性导致我们项目崩溃,这也是很正常,就比如MediaRecorder是需要录音和摄像头权限的但是你不给它,肯定会初始化失败。在这我有使用checkSelefPerssion() 和 requestPerssions()两个方法,具体大家看那一下源码就知道了。
剩下的各位自己看一下代码吧!标注的很详细。