以前寫過一個視頻錄製功能,最近又看了一下,重新修復了一些問題。由於代碼比較長,我就不給大家去一點一點的講解了,在代碼中我都註釋的很詳細了,在這只是羅列出來一些注意的事項,代碼大家可在文末進行下載。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()兩個方法,具體大家看那一下源碼就知道了。
剩下的各位自己看一下代碼吧!標註的很詳細。