1,MediaRecorder類概述
Android的MediaRecorder包含了Audio和video的記錄功能,在Android的界面上,Music和Video兩個應用 程序都是調用MediaRecorder實現的。MediaRecorder在底層是基於OpenCore(PacketVideo)的庫實現的,爲了構 建一個MediaRecorder程序,上層還包含了進程間通訊等內容,這種進程間通訊的基礎是Android基本庫中的Binder機制。
1,MediaRecorder方法說明:
方法 說明
setAudioChannels(int numChannels) 設置錄製的音頻通道數
setAudioEncoder(int audio_encoder) 設置audio的編碼格式
setAudioEncodingBitRate(int bitRate) 設置錄製的音頻編碼比特率
setAudioSamplingRate(int samplingRate) 設置錄製的音頻採樣率
setAudioSource(int audio_source) 設置用於錄製的音源
setAuxiliaryOutputFile(String path) 輔助時間的推移視頻文件的路徑傳遞
setAuxiliaryOutputFile(FileDescriptor fd) 在文件描述符傳遞的輔助時間的推移視頻
setCamera(Camera c) 設置一個recording的攝像頭
setCaptureRate(double fps) 設置視頻幀的捕獲率
setMaxDuration(int max_duration_ms) 設置記錄會話的最大持續時間(毫秒)
setMaxFileSize(long max_filesize_bytes) 設置記錄會話的最大大小(以字節爲單位)
setOutputFile(FileDescriptor fd) 傳遞要寫入的文件的文件描述符
setOutputFile(String path) 設置輸出文件的路徑
setOutputFormat(int output_format) 設置在錄製過程中產生的輸出文件的格式
setPreviewDisplay(Surface sv) 表面設置顯示記錄媒體(視頻)的預覽
setVideoEncoder(int video_encoder) 設置視頻編碼器,用於錄製
setVideoEncodingBitRate(int bitRate) 設置錄製的視頻編碼比特率
setVideoFrameRate(int rate) 設置要捕獲的視頻幀速率
setVideoSize(int width, int height) 設置要捕獲的視頻的寬度和高度
setVideoSource(int video_source) 開始捕捉和編碼數據到setOutputFile(指定的文件)
2,MediaRecorder中音視頻編碼格式和資源說明:
- 視頻編碼格式:default,H263,H264,MPEG_4_SP
- 獲得視頻資源:default,CAMERA
- 音頻編碼格式:default,AAC,AMR_NB,AMR_WB
- 獲得音頻資源:defalut,camcorder,mic,voice_call,voice_communication,voice_downlink,voice_recognition, voice_uplink
輸出方式:amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gpp
例如:
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //設置音頻源爲麥克風
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//設置聲音格式爲3gp
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //設置編碼爲AMR
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //設置視頻源爲Camera
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //設置視頻輸出格式爲MP4
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);//設置視頻編碼
recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)); // 默認視頻格式
2,Android 中MediaRecorder和Camera的關係
從功能的角度MediaRecorder一般包含音頻,視頻記錄,視頻預覽的功能,Camera包含了取景區預覽,靜態圖像捕獲的功能。在 Android中,應用程序自上而下分成JAVA應用,JAVA框架,JNI,C框架,具體實現幾個部分。多媒體方面的程序尤其是這樣。 MediaRecorder 和Camera在Android中都有自上而下的架構,它們在頂層JAVA應用層,共用一個應用程序Camera(其中的程序也是獨立的),在JAVA框 架和JNI層是獨立的,主要的聯繫在於Camer的C框架以下的內容被MediaRecorder實現(也就是PVAuthor)所調用,作爲 MediaRecorder實現的視頻輸入設備,它的作用是負責傳輸視頻數據和提供顯示預覽。本身Camera C框架以下的代碼基本提供了取景器預覽(Preview)、視頻數據流獲取、靜止圖像獲取三方面的功能,MediaRecorder實現使用其取景器預覽 和視頻數據流獲取的功能,而Camera的JNI使用其取景器預覽和靜止圖像獲取兩方面的功能。
3,使用過程
1,我們需要在AndroidManifest.xml文件中聲明錄製視頻要用到的權限
2,有SurfaceView提供界面預覽
3,錄製視頻的Java代碼主要實現代碼:
`
public class VideoActivity extends Activity implements SurfaceHolder.Callback {
private File myRecVideoFile;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private TextView tvTime;
private TextView tvSize;
private Button btnStart;
private Button btnStop;
private Button btnCancel;
private MediaRecorder recorder;
private Handler handler;
private Camera camera;
private boolean recording; // 記錄是否正在錄像,fasle爲未錄像, true 爲正在錄像
private int minute = 0;
private int second = 0;
private String time = "";
private String size = "";
private String fileName;
private String name = "";
private Runnable timeRun = new Runnable() {
@Override
public void run() {
long fileLength = myRecVideoFile.length();
if (fileLength < 1024 && fileLength > 0) {
size = String.format("�/10M", fileLength);
} else if (fileLength >= 1024 && fileLength < (1024 * 1024)) {
fileLength = fileLength / 1024;
size = String.format("%dK/10M", fileLength);
} else if (fileLength > (1024 * 1024 * 1024)) {
fileLength = (fileLength / 1024) / 1024;
size = String.format("%dM/10M", fileLength);
}
second++;
if (second == 60) {
minute++;
second = 0;
}
time = String.format("d:d", minute, second);
tvSize.setText(size);
tvTime.setText(time);
handler.postDelayed(timeRun, 1000);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recorded_video);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mSurfaceView = (SurfaceView) findViewById(R.id.videoView);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder.setKeepScreenOn(true);
handler = new Handler();
tvTime = (TextView) findViewById(R.id.tv_video_time);
tvSize = (TextView) findViewById(R.id.tv_video_size);
btnStop = (Button) findViewById(R.id.btn_video_stop);
btnStart = (Button) findViewById(R.id.btn_video_start);
btnCancel = (Button) findViewById(R.id.btn_video_cancel);
btnCancel.setOnClickListener(listener);
btnStart.setOnClickListener(listener);
btnStop.setOnClickListener(listener);
// 設置sdcard的路徑
fileName = Environment.getExternalStorageDirectory().getAbsolutePath();
name = "video_" + System.currentTimeMillis() + ".mp4";
fileName += File.separator + File.separator + "Ruanko_Jobseeker" + File.separator + name;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 開啓相機
if (camera == null) {
int CammeraIndex = FindFrontCamera();
if (CammeraIndex == -1) {
ToastUtil.TextToast(getApplicationContext(), "您的手機不支持前置攝像頭", ToastUtil.LENGTH_SHORT);
CammeraIndex = FindBackCamera();
}
camera = Camera.open(CammeraIndex);
try {
camera.setPreviewDisplay(mSurfaceHolder);
camera.setDisplayOrientation(90);
} catch (IOException e) {
e.printStackTrace();
camera.release();
}
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// 開始預覽
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 關閉預覽並釋放資源
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
}
private View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_video_stop:
if (recorder != null) {
releaseMediaRecorder();
minute = 0;
second = 0;
handler.removeCallbacks(timeRun);
recording = false;
}
btnStart.setEnabled(true);
break;
case R.id.btn_video_start:
if (recorder != null) {
releaseMediaRecorder();
minute = 0;
second = 0;
handler.removeCallbacks(timeRun);
recording = false;
}
recorder();
btnStart.setEnabled(false);
break;
case R.id.btn_video_cancel:
releaseMediaRecorder();
handler.removeCallbacks(timeRun);
minute = 0;
second = 0;
recording = false;
VideoActivity.this.finish();
break;
}
}
};
//判斷前置攝像頭是否存在
private int FindFrontCamera() {
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();
// get cameras number
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
// get camerainfo
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
// 代表攝像頭的方位,目前有定義值兩個分別爲CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK後置
return camIdx;
}
}
return -1;
}
//判斷後置攝像頭是否存在
private int FindBackCamera() {
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();
// get cameras number
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
// get camerainfo
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
// 代表攝像頭的方位,目前有定義值兩個分別爲CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK後置
return camIdx;
}
}
return -1;
}
//釋放recorder資源
private void releaseMediaRecorder() {
if (recorder != null) {
recorder.stop();
recorder.release();
recorder = null;
}
}
//開始錄像
public void recorder() {
if (!recording) {
try {
// 關閉預覽並釋放資源
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
recorder = new MediaRecorder();
// 聲明視頻文件對象
myRecVideoFile = new File(fileName);
if (!myRecVideoFile.exists()) {
myRecVideoFile.getParentFile().mkdirs();
myRecVideoFile.createNewFile();
}
recorder.reset();
// 判斷是否有前置攝像頭,若有則打開,否則打開後置攝像頭
int CammeraIndex = FindFrontCamera();
if (CammeraIndex == -1) {
ToastUtil.TextToast(getApplicationContext(), "您的手機不支持前置攝像頭", ToastUtil.LENGTH_SHORT);
CammeraIndex = FindBackCamera();
}
camera = Camera.open(CammeraIndex);
// 設置攝像頭預覽順時針旋轉90度,才能使預覽圖像顯示爲正確的,而不是逆時針旋轉90度的。
camera.setDisplayOrientation(90);
camera.unlock();
recorder.setCamera(camera);
//設置攝像頭爲相機
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//視頻源
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 錄音源爲麥克風
recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
//設置視頻和聲音的編碼爲系統自帶的格式
recorder.setOutputFile(myRecVideoFile.getAbsolutePath());
recorder.setPreviewDisplay(mSurfaceHolder.getSurface());
// 預覽
recorder.setMaxFileSize(10 * 1024 * 1024);
//設置視頻文件的最大值爲10M,單位B //
recorder.setMaxDuration(3 * 1000);//設置視頻的最大時長,單位毫秒
recorder.setOrientationHint(90);//視頻旋轉90度,沒有用
recorder.prepare(); // 準備錄像
recorder.start(); // 開始錄像
handler.post(timeRun); // 調用Runable
recording = true; // 改變錄製狀態爲正在錄製
} catch (IOException e1) {
releaseMediaRecorder();
handler.removeCallbacks(timeRun);
minute = 0;
second = 0;
recording = false;
btnStart.setEnabled(true);
} catch (IllegalStateException e) {
releaseMediaRecorder();
handler.removeCallbacks(timeRun);
minute = 0;
second = 0;
recording = false;
btnStart.setEnabled(true);
}
} else
ToastUtil.TextToast(getApplicationContext(), "視頻錄製中...", ToastUtil.LENGTH_SHORT);
}
}
`