MediaRecorder之视频录制
生活随笔
收集整理的這篇文章主要介紹了
MediaRecorder之视频录制
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一 前言
? ?在前面已經介紹過使用MediaRecorder錄制音頻,那么錄制視頻呢?很顯然錄制視頻也需要MediaRecorder,同時需要攝像頭Camera(相當于攝像機)。Camera用來取景,然后使用SurfaceView顯示影像,那么MediaRecorder用來做錄制的工作,接下來就是看看視頻的錄制的過程。 ? ?本篇通過一個示例來認識簡單視頻的錄制的過程,示例說明:通過Camera、MediaRecorder實現視頻錄制,停止錄制后,點擊播放按鈕使用MediaPlayer來播放視頻,示例完整代碼最后提供(該實例的完整代碼在recodervideomediarecorder的module中 )。二?視頻錄制
? ?視頻錄制步驟大致如下: (1)打開Camera(攝像頭); (2)設置攝像機參數(CamcorderProfile),設置攝像頭參數; (3)創建MediaRecorder對象實例,可以通過默認的構造方法進行創建; (4)設置音頻來源、視頻來源、錄制設備(Camera)、錄制信息(CamcorderProfile)、輸出文件格式等; (5)創建SurfaceView(可以直接在布局中使用),并給SurfaceHolder添加callback監聽; (6)通過MediaRecorder對象實例調用setPreviewDisplay方法設置視頻預覽界面; (7)調用prepare方法做錄制前的準備工作; (8)調用start、pause、stop方法控制錄制過程; 接下來就來看看具體實現過程。1 打開Camera(攝像頭)
public static Camera open(int cameraId) {//獲取攝像頭數目
int numCameras = Camera.getNumberOfCameras();
if (numCameras == 0) {
Log.w(TAG, "No cameras!");
return null;
}
// cameraId the hardware camera to access, between 0 and numCameras(攝像頭數目) - 1
boolean explicitRequest = cameraId >= 0;
if (!explicitRequest) {
// Select a camera if no explicit camera requested
int index = 0;
while (index < numCameras) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(index, cameraInfo);
//判斷使用是前置還是后置攝像頭 如果是后置攝像頭則停止循環
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
break;
}
index++;
}
cameraId = index;
}
Camera camera;
if (cameraId < numCameras) {
printMessage("Opening camera #" + cameraId);
camera = Camera.open(cameraId);
} else {
if (explicitRequest) {
Log.w(TAG, "Requested camera does not exist: " + cameraId);
camera = null;
} else {// cameraId 值 小于 0 且 不存在后置攝像頭時,會走這里
printMessage( "No camera facing back; returning camera #0");
camera = Camera.open(0);
}
}
return camera;
}
說明:上述代碼的功能主要是通過ID打開攝像頭,一般ID為0的是后置攝像頭;如果有多個攝像頭的ID依次為0,1,2,...。
2 設置攝像機參數(CamcorderProfile)與攝像頭參數
(1)設置攝像機參數 public static CamcorderProfile setCamcorderProfile(boolean isHigh ){//返回后置相機的配置信息的類
CamcorderProfile profile = CamcorderProfile.get(isHigh ? CamcorderProfile.QUALITY_HIGH : CamcorderProfile.QUALITY_LOW);
//設置視頻幀的寬度
profile.videoFrameWidth = (int) (profile.videoFrameWidth * VIDEO_SIZE_RATE);
//設置視頻幀的高度
profile.videoFrameHeight = (int) (profile.videoFrameHeight * VIDEO_SIZE_RATE);
//設置視頻輸出比特率 The target video output bit rate in bits per second
profile.videoBitRate = VIDEO_BIT_RATE;
CamcorderProfile highProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
//The video encoder being used for the video track 設置視頻編碼
profile.videoCodec = highProfile.videoCodec;
//設置音頻編碼
profile.audioCodec = highProfile.audioCodec;
//The file output format of the camcorder profile 設置輸出格式
profile.fileFormat = MediaRecorder.OutputFormat.MPEG_4;
return profile;
} 說明:很顯然上方法主要是配置攝像機參數,返回CamcorderProfile即配置文件(在后面會用到)。那么CamcorderProfile是什么鬼?CamcorderProfile是用來保存攝像機配置信息的一個實體類,準確說是保存音視頻配置信息,Android系統已經幫我們預定好了這些配置信息,當然你也可以自己設置,這些信息有:
1.直接獲取 CamcorderProfile profile=CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); 2.按時間流逝,質量變化情況來 CamcorderProfile profile=CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH); 3.按高幀數下的質量來 CamcorderProfile profile=CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH_SPEED_HIGH); 因此CamcorderProfile為我們實現視頻的錄制提供很大的方便。 (2)設置攝像頭參數 /**
* 設置攝像頭參數,錄制視頻時使用該方法
* @param camera 攝像頭
* @param profile 該參數為攝像機配置文件,里面保存類攝像機的參數
* @param whiteBalance 白平衡 可以為 null
* @param colorEffect 顏色效果 可以為 null
* @return 攝像頭參數類 {@link Camera.Parameters } 對象
*/
public static Camera.Parameters setCameraParameters(Camera camera , CamcorderProfile profile , String whiteBalance , String colorEffect){
if (camera == null){
printMessage("camera can not null !");
return null;
}
if (profile == null){
printMessage("profile can not null !");
return null;
}
//因為android不支持豎屏錄制,所以需要順時針轉90度,讓其游覽器顯示正常
camera.setDisplayOrientation(90);
Camera.Parameters parameters = camera.getParameters();
//設置預覽圖片的大小
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
//設置預覽圖片的幀率
parameters.setPreviewFrameRate(profile.videoFrameRate);
//設置獲焦模式
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
if (TextUtils.isEmpty(whiteBalance)){
whiteBalance = "auto";
}
if (TextUtils.isEmpty(colorEffect)){
colorEffect = "none";
}
// 設置白平衡參數。
if (isSupported(whiteBalance, parameters.getSupportedWhiteBalance())) {
parameters.setWhiteBalance(whiteBalance);
}
// 參數設置顏色效果。
if (isSupported(colorEffect, parameters.getSupportedColorEffects())) {
parameters.setColorEffect(colorEffect);
}
camera.setParameters(parameters);
return parameters;
} 說明:上述代碼主要通過Camera.Parameters與上面返回的CamcorderProfile設置預覽圖片的大小,幀的速率等,在這里我使用豎屏拍攝,所以Camera直接旋轉了90度。
3 創建MediaRecorder對象實例
MediaRecorder mediaRecorder = new MediaRecorder();4 設置音頻來源、視頻來源、錄制設備(Camera)、錄制信息(CamcorderProfile)、輸出文件格式等;
//關閉鎖,使其他線程可以訪問攝像頭 在打開攝像頭時要打開鎖camera.unlock();
mediaRecorder.setCamera(camera);
// 設置錄制視頻源為Camera(相機)
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// 設置音頻資源
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//Uses the settings from a CamcorderProfile object for recording 根據CamcorderProfile對象設置錄制信息
mediaRecorder.setProfile(profile);
//設置視頻大小(分辨率)
mediaRecorder.setVideoSize(1280, 720);
// 設置視頻一次寫多少字節(可調節視頻空間大小)
mediaRecorder.setVideoEncodingBitRate(1024 * 1024);
//每秒4幀
mediaRecorder.setVideoFrameRate(4);
//設置視頻文件的輸出格式 必須在設置聲音編碼格式、圖像編碼格式之前設置
// mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
// mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
// 最大期限
mediaRecorder.setMaxDuration(35 * 1000);
//視頻文件名
String fileName = "VID_" + System.currentTimeMillis() + ".mp4";
file = new File(videoPath, fileName);
// 指定輸出文件 , 設置視頻文件輸出的路徑
mediaRecorder.setOutputFile(file.getAbsolutePath()); 說明:videoPath為視頻本地保存路徑,還有一點需要注意的就是打開Camera后,要調用lock方法鎖住Camera,在開始錄制前避免被其他線程訪問Camera(不然老是出現錯誤,Camera無法使用,我試過了好多次都不行),在開始錄制的時候再調用unlock方法開鎖,使其線程可以訪問。
5 創建SurfaceView(可以直接在布局中使用),并給SurfaceHolder添加callback監聽
(1)創建SurfaceView surfaceView = (SurfaceView) findViewById(R.id.sufaceview); (2)給SurfaceHolder添加callback監聽 surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {@Override
public void surfaceCreated(SurfaceHolder holder) {
if (camera != null){
CameraHelpUtil.startPreview(camera,surfaceView.getHolder());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null){
camera.stopPreview();
}
}
});
6 通過MediaRecorder對象實例調用setPreviewDisplay方法設置視頻預覽界面
//設置 surface 預覽視頻mediaRecorder.setPreviewDisplay(holder.getSurface());
// // 設置保存錄像方向
mediaRecorder.setOrientationHint(90);
7 調用prepare方法做錄制前的準備工作
try {mediaRecorder.prepare();
} catch (IOException e) {
Log.d(TAG,e.getMessage());
}
8 開始錄制
mediaRecorder.start();說明:步驟3,4,6,7,8組合在一起形成一個完整的方法如下: /**
* 初始化 MediaRecorder 對象實例
* @param camera 攝像頭
* @param profile 攝像頭配置文件
* @param videoPath 視頻保存的位置
* @param holder SurfaceHolder 對象實例
*/
public static MediaRecorder record( Camera camera , CamcorderProfile profile , String videoPath, SurfaceHolder holder){
MediaRecorder mediaRecorder = new MediaRecorder();
//關閉鎖,使其他線程可以訪問攝像頭 在打開攝像頭時要打開鎖
camera.unlock();
mediaRecorder.setCamera(camera);
// 設置錄制視頻源為Camera(相機)
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// 設置音頻資源
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//Uses the settings from a CamcorderProfile object for recording 根據CamcorderProfile對象設置錄制信息
mediaRecorder.setProfile(profile);
//設置視頻大小(分辨率)
mediaRecorder.setVideoSize(1280, 720);
// 設置視頻一次寫多少字節(可調節視頻空間大小)
mediaRecorder.setVideoEncodingBitRate(1024 * 1024);
//每秒4幀
mediaRecorder.setVideoFrameRate(4);
//設置視頻文件的輸出格式 必須在設置聲音編碼格式、圖像編碼格式之前設置
// mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
// mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
// 最大期限
mediaRecorder.setMaxDuration(35 * 1000);
//視頻文件名
String fileName = "VID_" + System.currentTimeMillis() + ".mp4";
file = new File(videoPath, fileName);
// 指定輸出文件 , 設置視頻文件輸出的路徑
mediaRecorder.setOutputFile(file.getAbsolutePath());
//設置 surface 預覽視頻
mediaRecorder.setPreviewDisplay(holder.getSurface());
// // 設置保存錄像方向
mediaRecorder.setOrientationHint(90);
mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
@Override
public void onError(MediaRecorder mr, int what, int extra) {
// Toast.makeText(RecorderVideoActivity.this, "未知錯誤", Toast.LENGTH_SHORT).show();
}
});
mediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
@Override
public void onInfo(MediaRecorder mr, int what, int extra) {
}
});
try {
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IOException e) {
Log.d(TAG,e.getMessage());
}
return mediaRecorder;
}
說明:上述代碼都是錄制視頻業務邏輯的實現過程,都寫成了工具類,源碼中有,播放視頻的實現前面有介紹過,這里就不累述了,下面貼出示例的實現代碼:
三 示例
1 視頻錄制界面Activity的實現代碼
public class RecorderVideoActivity extends AppCompatActivity {private String filePath = " ";
private Camera camera;
private CamcorderProfile profile;
private MediaRecorder mediaRecorder;
private SurfaceView surfaceView;
private ImageView img_start;
/** true 正在錄制 */
private boolean isRecoding = false;
private TextView txt_play;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recorder_video);
surfaceView = (SurfaceView) findViewById(R.id.sufaceview);
img_start = (ImageView) findViewById(R.id.img_start);
txt_play = (TextView) findViewById(R.id.txt_play);
setListener();
}
/**
* 設置監聽
*/
private void setListener() {
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (camera != null){
CameraHelpUtil.startPreview(camera,surfaceView.getHolder());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null){
camera.stopPreview();
}
}
});
img_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (camera == null){
return;
}
if (isRecoding){
isRecoding = false;
MediaRecorderHelpUtil.stop(mediaRecorder);
img_start.setImageResource(R.mipmap.icon_voice_transcribe);
}else {
mediaRecorder = MediaRecorderHelpUtil.record(camera,profile,filePath,surfaceView.getHolder());
isRecoding = true;
img_start.setImageResource(R.mipmap.icon_stop_transcribe);
}
}
});
txt_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
play();
}
});
}
private void play() {
if (null == MediaRecorderHelpUtil.getFile()){
return;
}
Intent intent = new Intent(this,MediaPlayerSurfaceActivity.class);
intent.putExtra("video_Path",MediaRecorderHelpUtil.getFile().getAbsolutePath());
startActivity(intent);
}
@Override
protected void onResume() {
super.onResume();
isRecoding = false;
}
@Override
protected void onStart() {
super.onStart();
if (camera == null){
checkPermission();
}
}
/**
* 動態檢測必要的權限
*/
private void checkPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M){
initDrives();
return;
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != 0 ||
ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != 0 ||
ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != 0 ||
ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != 0){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.RECORD_AUDIO,Manifest.permission.CAMERA},0x123);
}else {
initDrives();
}
}
/**
* 初始化攝像頭設備
*/
private void initDrives() {
getFilePath();
camera = CameraHelpUtil.open();
//打開鎖 ,使其他線程無法訪問 攝像頭
camera.lock();
if (camera != null){
profile = CameraHelpUtil.setCamcorderProfile(false);
CameraHelpUtil.setCameraParameters(camera,profile,null,null);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 0x123){
if (grantResults[0] == 0 && grantResults[1] == 0 && grantResults[2] == 0 && grantResults[3] == 0){
initDrives();
}else {
Toast.makeText(this, "需要必要的權限,請授權", Toast.LENGTH_SHORT).show();
}
}
}
/**
* 獲取文件保存路徑
*/
private void getFilePath(){
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() /*+ File.separator + getPackageName()*/;
}else {
filePath = Environment.getDataDirectory().getAbsolutePath() /*+ File.separator + getPackageName()*/;
}
filePath = filePath + File.separator + "Camera";
File file = new File(filePath);
if (!file.exists()){
file.mkdirs();
}
filePath = file.getAbsolutePath();
}
@Override
protected void onDestroy() {
CameraHelpUtil.releaseCamera(camera);
if (isRecoding){
MediaRecorderHelpUtil.stop(mediaRecorder);
// MediaRecorderHelpUtil.release(mediaRecorder);
}
super.onDestroy();
}
}
其Xml文件如下: <?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="com.lzb.video.RecorderVideoActivity">
<SurfaceView
android:id="@+id/sufaceview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/img_start"
android:layout_gravity="bottom|center_horizontal"
android:src="@mipmap/icon_voice_transcribe"
android:layout_marginBottom="50dp"
android:scaleType="fitXY"
android:layout_width="60dp"
android:layout_height="60dp" />
<TextView
android:id="@+id/txt_play"
android:text="播放視頻"
android:textColor="@android:color/white"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
2 播放界面代碼
public class MediaPlayerSurfaceActivity extends Activity implements View.OnClickListener{/** 視頻播放控件*/
private SurfaceView surfaceView;
private Display currDisplay;
/** 給SurfaceView添加CallBack監聽 */
private SurfaceHolder holder;
/** 多媒體*/
private MediaPlayer player;
private int vWidth,vHeight;
/** 視頻路徑*/
private String videoPath = "";
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_surface);
button = (Button) findViewById(R.id.btn_start);
button.setOnClickListener(this);
//獲取播放地址
Intent intent = getIntent();
videoPath = intent.getStringExtra("video_Path");
surfaceView = (SurfaceView) findViewById(R.id.surface_surface_view);
//然后,我們取得當前Display對象
currDisplay = this.getWindowManager().getDefaultDisplay();
//下面開始實例化MediaPlayer對象
player = new MediaPlayer();
setPlayerListener();
setHolder();
}
/**
* 將要播放的視頻圖像輸送到surfaceView
*/
private void setHolder() {
//給SurfaceView添加CallBack監聽
holder = surfaceView.getHolder();
//為了可以播放視頻或者使用Camera預覽,我們需要指定其Buffer類型
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new Callback() {
/**
* Activity進入后臺會觸發該方法
* @param holder
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Toast.makeText(MediaPlayerSurfaceActivity.this, "Surface被銷毀", Toast.LENGTH_SHORT).show();
}
/**
*
* Activity進入前臺會觸發該方法
*
* 當SurfaceView中的Surface被創建的時候被調用*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
Toast.makeText(MediaPlayerSurfaceActivity.this, "Surface被創建", Toast.LENGTH_SHORT).show();
play();
}
/** 當Surface尺寸等參數改變時觸發 */
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
}
});
}
/**
*
* MediaPlayer中的prepare方法和prepareAsync方法的區別
* prepare方法是將資源同步緩存到內存中,一般加載本地較小的資源可以用這個,
* 如果是較大的資源或者網絡資源建議使用prepareAsync方法,異步加載.但如果想讓資源啟動,即start()起來,
* 因為在異步中,如果不設置監聽直接start的話,是拿不到這個資源,如果讓線程睡眠一段時間,則可以取得資源,因為這個時候,
* 異步線程已經取得資源,但不可能使用線程睡眠的方式來獲取資源啊.所以就需要設置監聽事件setOnPreparedListener();
* 來通知MediaPlayer資源已經獲取到了,然后實現onPrepared(MediaPlayer mp)方法.在里面啟動MediaPlayer
* 參考:http://blog.csdn.net/qq_24223073/article/details/69315856
* 設置監聽示例{@link #setPlayerListener}
* 開始播放視頻
*/
void play() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
surfaceView.setForeground(null);
}
if (TextUtils.isEmpty(videoPath)){
return;
}
player.reset();
//將要播放的視頻圖像輸送到surfaceView
player.setDisplay(holder);
try {
player.setDataSource(videoPath);
// player.prepare();
player.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
//首先取得video的寬和高
vWidth = player.getVideoWidth();
vHeight = player.getVideoHeight();
if(vWidth > currDisplay.getWidth() || vHeight > currDisplay.getHeight()){
//如果video的寬或者高超出了當前屏幕的大小,則要進行縮放
float wRatio = (float)vWidth/(float)currDisplay.getWidth();
float hRatio = (float)vHeight/(float)currDisplay.getHeight();
//選擇大的一個進行縮放
float ratio = Math.max(wRatio, hRatio);
vWidth = (int)Math.ceil((float)vWidth/ratio);
vHeight = (int)Math.ceil((float)vHeight/ratio);
//設置surfaceView的布局參數
surfaceView.setLayoutParams(new LinearLayout.LayoutParams(vWidth, vHeight - 100));
//然后開始播放視頻
// player.start();
}
// player.start();
}
/**
*
* 設置播放監聽
*
* @version 1.0
* @createTime 2016-1-20,下午3:04:38
* @updateTime 2016-1-20,下午3:04:38
* @createAuthor lzb
* @updateAuthor
* @updateInfo (此處輸入修改內容,若無修改可不寫.)
*/
@SuppressLint("NewApi") @SuppressWarnings("deprecation")
private void setPlayerListener() {
//設置播放完監聽
player.setOnCompletionListener(new OnCompletionListener() {
/** 當MediaPlayer播放完成后觸發 */
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(MediaPlayerSurfaceActivity.this, "播放完成", Toast.LENGTH_SHORT).show();
}
});
//播放錯誤監聽
player.setOnErrorListener(new OnErrorListener() {
@TargetApi(Build.VERSION_CODES.CUPCAKE) @Override
public boolean onError(MediaPlayer mp, int what, int extra) {
switch (what) {
//播放器壞了
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Toast.makeText(MediaPlayerSurfaceActivity.this, "播放器壞了", Toast.LENGTH_SHORT).show();
break;
//未知錯誤
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Toast.makeText(MediaPlayerSurfaceActivity.this, "未知錯誤", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
return false;
}
});
//詳細監聽
player.setOnInfoListener(new OnInfoListener() {
/** 當一些特定信息出現或者警告時觸發 */
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch(what){
case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING: //視頻交叉紊亂
Toast.makeText(MediaPlayerSurfaceActivity.this, "視頻交叉紊亂", Toast.LENGTH_SHORT).show();
break;
case MediaPlayer.MEDIA_INFO_METADATA_UPDATE: //更新
Toast.makeText(MediaPlayerSurfaceActivity.this, "更新", Toast.LENGTH_SHORT).show();
break;
case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING: //無法解碼
Toast.makeText(MediaPlayerSurfaceActivity.this, "無法解碼", Toast.LENGTH_SHORT).show();
break;
case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE: //不能搜索
Toast.makeText(MediaPlayerSurfaceActivity.this, "不能搜索", Toast.LENGTH_SHORT).show();
break;
}
return false;
}
});
//準備監聽 如果是使用異步加載的方式必須要設置該監聽,在onPrepared方法中調用start()方法
player.setOnPreparedListener(new OnPreparedListener() {
/** 當prepare完成后,該方法觸發,在這里我們播放視頻*/
@Override
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
player.setOnSeekCompleteListener(new OnSeekCompleteListener() {
/** seek操作完成時觸發 */
@Override
public void onSeekComplete(MediaPlayer mp) {
}
});
/** 當video大小改變時觸發 這個方法在設置player的source后至少觸發一次 */
player.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
}
});
}
/**
* 啟動其他Activity或者對話框,暫停播放
*/
@Override
protected void onPause() {
if (player != null){
if (player.isPlaying()){
player.stop();
}
}
super.onPause();
}
@Override
protected void onDestroy() {
if (player != null){
if (player.isPlaying()){
player.stop();
}
player.release();
}
super.onDestroy();
}
@Override
public void onClick(View v) {
if (player.isPlaying()){
player.stop();
player.reset();
play();
}else {
play();
}
}
}
其XML文件如下: <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"
android:id="@+id/main_rLayout"
tools:context="com.lzb.video.MediaPlayerSurfaceActivity" >
<SurfaceView
android:id="@+id/surface_surface_view"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:id="@+id/btn_start"
android:text="重播"
android:textColor="@android:color/white"
android:background="@android:color/transparent"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout> 完整示例代碼
四 效果圖
總結
以上是生活随笔為你收集整理的MediaRecorder之视频录制的全部內容,希望文章能夠幫你解決所遇到的問題。