Android--MediaRecorder錄音錄像


前言

  Android除了支持播放多媒體文件之外,還可以從對應的硬件中捕獲多媒體,比如從麥克風錄音、從攝像頭錄像等。本篇博客講解一下Android下如何通過MediaRecorder進行錄音以及錄像的步驟,最后將以簡單的Demo演示。

   本篇博客的主要內容:

  1. MediaRecorder
  2. MediaRecorder錄制音頻
  3. MediaRecorder錄制視頻
  4. MediaRecorder的內部類

 

MediaRecorder

  MediaRecorder主要用於記錄音頻與視頻,它位於"android.media.MediaRecorder"下。它為開發人員提供了詳盡的AIP以完成記錄音頻與視頻的工作,下面簡單介紹一些常用的。

  • void prepar():准備錄制。
  • void start():開始錄制。
  • void stop():停止錄制。
  • void reset():重置MediaRecorder。
  • void release():釋放MediaRecorder占用的資源。
  • void setAudioEncoder(int):設置音頻記錄的編碼格式。
  • void setAudoSource(int):設置音頻記錄的音頻源。
  • void setOutoutFormat(int):設置記錄的媒體文件的輸出轉換格式。
  • void setPreviewDisplay(Surface):設置視頻的預覽界面。
  • void setVideoEncoder(int):設置視頻記錄的編碼格式。
  • void setVideoSource(int):設置視頻記錄的視頻源。
  • void setOutputFile(String):媒體文件輸出路徑。
  • void setMaxDuration(int):設置最大記錄時長,單位為毫秒。

  上面僅僅列出了一些常用的方法,但是通過這個方法可以看出MediaRecorder是需要在多個狀態之間切換的,准備、開始、停止、重置等等。MediaRecorder也為我們提供了一套狀態切換的規則,只有在既定的狀態下,才能完成對應的操作,下圖是官方文檔提供的狀態圖。

  上圖非常直觀的展示了MediaRecorder的狀態間的轉換,這里只說幾點需要注意的地方:

  • 當為MediaRecorder設定媒體錄入源之后即初始化完成,這個時候才可以為其設定其他的參數。
  • 在開始錄制前必須先調用prepare()准備錄制。
  • 只有在Initial初始化狀態,才可以對MediaRecorder調用release()釋放資源,其他狀態必須先stop()或者reset()。
  • 錯誤狀態是游離在所有狀態之外的,當發生錯誤的時候,只有進行reset()才會進入Initial初始狀態。

 

  MediaRecorder錄制視頻必不可少的步驟:

  1. 調用new MediaRecorder()構造函數得到MediaRecorder的實例。
  2. 調用setOutputFormat()設定媒體文件的輸出格式,必須在設定音頻與視頻的編碼格式之前設定。
  3. 如果需要記錄音頻,則調用setAudioSource()設定音頻的錄入源以及調用setAudioEncoder()設定音頻的編碼方式。
  4. 如果需要記錄視頻,則調用setVideoSource()設定視頻的錄入員以及調用setVideoEncoder()設定視頻的編碼方式。
  5. 調用setOutputFile()設定記錄的媒體文件保存的路徑。
  6. 先調用prepare()准備錄制,准備完成之后調用start()開始錄制。
  7. 記錄完成后,調用stop()停止錄制。

  

MediaRecorder錄制音頻

  上面介紹了使用MediaRecorder錄制視頻必不可少的步驟,因為錄制音頻無需捕獲圖像,所以更簡單一些。下面直接通過一個簡單的示例,演示如何錄制音頻,錄制的音頻文件保存在sd根目錄下,注釋很詳細,這里不在累述了。布局很簡單,只有兩個Button,開始錄音、結束錄音,就不提供布局代碼了。

  實現代碼:

 

  1 package cn.bgxt.mediarecorderdemo;
  2 
  3 import java.io.File;
  4 import android.app.Activity;
  5 import android.media.MediaRecorder;
  6 import android.media.MediaRecorder.OnErrorListener;
  7 import android.os.Bundle;
  8 import android.view.View;
  9 import android.view.View.OnClickListener;
 10 import android.widget.Button;
 11 import android.widget.Toast;
 12 
 13 public class RecordActivity extends Activity {
 14     private Button btn_RecordStart, btn_RecordStop;
 15     private MediaRecorder mediaRecorder;
 16     private boolean isRecording;
 17     @Override
 18     protected void onCreate(Bundle savedInstanceState) {
 19         // TODO Auto-generated method stub
 20         super.onCreate(savedInstanceState);
 21         setContentView(R.layout.activity_record);
 22 
 23         btn_RecordStart = (Button) findViewById(R.id.btn_RecordStart);
 24         btn_RecordStop = (Button) findViewById(R.id.btn_RecordStop);
 25         
 26         btn_RecordStop.setEnabled(false);
 27         
 28         btn_RecordStart.setOnClickListener(click);
 29         btn_RecordStop.setOnClickListener(click);
 30     }
 31 
 32     private View.OnClickListener click = new OnClickListener() {
 33 
 34         @Override
 35         public void onClick(View v) {
 36             switch (v.getId()) {
 37             case R.id.btn_RecordStart:
 38                 start();
 39                 break;
 40             case R.id.btn_RecordStop:
 41                 stop();
 42                 break;
 43             default:
 44                 break;
 45             }
 46         }
 47     };
 48 
 49     /**
 50      * 開始錄音
 51      */
 52     protected void start() {
 53         try {
 54             File file = new File("/sdcard/mediarecorder.amr");
 55             if (file.exists()) {
 56                 // 如果文件存在,刪除它,演示代碼保證設備上只有一個錄音文件
 57                 file.delete();
 58             }
 59             mediaRecorder = new MediaRecorder();
 60             // 設置音頻錄入源
 61             mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 62             // 設置錄制音頻的輸出格式
 63             mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
 64             // 設置音頻的編碼格式
 65             mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
 66             // 設置錄制音頻文件輸出文件路徑
 67             mediaRecorder.setOutputFile(file.getAbsolutePath());
 68 
 69             mediaRecorder.setOnErrorListener(new OnErrorListener() {
 70                 
 71                 @Override
 72                 public void onError(MediaRecorder mr, int what, int extra) {
 73                     // 發生錯誤,停止錄制
 74                     mediaRecorder.stop();
 75                     mediaRecorder.release();
 76                     mediaRecorder = null;
 77                     isRecording=false;
 78                     btn_RecordStart.setEnabled(true);
 79                     btn_RecordStop.setEnabled(false);
 80                     Toast.makeText(RecordActivity.this, "錄音發生錯誤", 0).show();
 81                 }
 82             });
 83             
 84             // 准備、開始
 85             mediaRecorder.prepare();
 86             mediaRecorder.start();
 87             
 88             isRecording=true;
 89             btn_RecordStart.setEnabled(false);
 90             btn_RecordStop.setEnabled(true);
 91             Toast.makeText(RecordActivity.this, "開始錄音", 0).show();
 92         } catch (Exception e) {
 93             e.printStackTrace();
 94         }
 95     }
 96 
 97     /**
 98      * 錄音結束
 99      */
100     protected void stop() {
101         if (isRecording) {
102             // 如果正在錄音,停止並釋放資源
103             mediaRecorder.stop();
104             mediaRecorder.release();
105             mediaRecorder = null;
106             isRecording=false;
107             btn_RecordStart.setEnabled(true);
108             btn_RecordStop.setEnabled(false);
109             Toast.makeText(RecordActivity.this, "錄音結束", 0).show();
110         }
111     }
112 
113     @Override
114     protected void onDestroy() {
115         if (isRecording) {
116             // 如果正在錄音,停止並釋放資源
117             mediaRecorder.stop();
118             mediaRecorder.release();
119             mediaRecorder = null;
120         }
121         super.onDestroy();
122     }
123 
124 }

  錄制音頻需要訪問麥克風設備,訪問設備需要添加權限:

    <uses-permission android:name="android.permission.RECORD_AUDIO"/>

  效果展示:

 

MediaRecorder錄制視頻

  上面已經介紹了使用MediaRecorder錄制視頻的步驟,這里依照步驟一步一步寫代碼就可以了。下面通過一個簡單的Demo演示如何使用MediaRecorder錄制一段從攝像頭捕獲到的視頻,錄制的視頻文件將保持在SD卡上。布局很簡單,兩個Button,開始、停止,然后還有一個SurfaceView顯示預覽效果,就不給出布局代碼了。

  實現代碼:

  1 package cn.bgxt.mediarecorderdemo;
  2 
  3 import java.io.File;
  4 import java.io.IOException;
  5 
  6 import android.app.Activity;
  7 import android.media.MediaRecorder;
  8 import android.media.MediaRecorder.OnErrorListener;
  9 import android.os.Bundle;
 10 import android.view.SurfaceHolder;
 11 import android.view.SurfaceView;
 12 import android.view.View;
 13 import android.view.View.OnClickListener;
 14 import android.widget.Button;
 15 import android.widget.Toast;
 16 
 17 public class VideoActivity extends Activity {
 18     private Button btn_VideoStart, btn_VideoStop;
 19     private SurfaceView sv_view;
 20     private boolean isRecording;
 21     private MediaRecorder mediaRecorder;
 22 
 23     @Override
 24     protected void onCreate(Bundle savedInstanceState) {
 25         super.onCreate(savedInstanceState);
 26         setContentView(R.layout.activity_video);
 27 
 28         btn_VideoStart = (Button) findViewById(R.id.btn_VideoStart);
 29         btn_VideoStop = (Button) findViewById(R.id.btn_VideoStop);
 30         sv_view = (SurfaceView) findViewById(R.id.sv_view);
 31 
 32         btn_VideoStop.setEnabled(false);
 33 
 34         btn_VideoStart.setOnClickListener(click);
 35         btn_VideoStop.setOnClickListener(click);
 36         
 37         // 聲明Surface不維護自己的緩沖區,針對Android3.0以下設備支持
 38         sv_view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 39     }
 40 
 41     private View.OnClickListener click = new OnClickListener() {
 42 
 43         @Override
 44         public void onClick(View v) {
 45             switch (v.getId()) {
 46             case R.id.btn_VideoStart:
 47                 start();
 48                 break;
 49             case R.id.btn_VideoStop:
 50                 stop();
 51                 break;
 52             default:
 53                 break;
 54             }
 55         }
 56     };
 57 
 58     protected void start() {
 59         try {
 60             File file = new File("/sdcard/video.mp4");
 61             if (file.exists()) {
 62                 // 如果文件存在,刪除它,演示代碼保證設備上只有一個錄音文件
 63                 file.delete();
 64             }
 65             
 66             mediaRecorder = new MediaRecorder();
 67             mediaRecorder.reset();
 68             // 設置音頻錄入源
 69             mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 70             // 設置視頻圖像的錄入源
 71             mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
 72             // 設置錄入媒體的輸出格式
 73             mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
 74             // 設置音頻的編碼格式
 75             mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
 76             // 設置視頻的編碼格式
 77             mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
 78             // 設置視頻的采樣率,每秒4幀
 79             mediaRecorder.setVideoFrameRate(4);
 80             // 設置錄制視頻文件的輸出路徑
 81             mediaRecorder.setOutputFile(file.getAbsolutePath());
 82             // 設置捕獲視頻圖像的預覽界面
 83             mediaRecorder.setPreviewDisplay(sv_view.getHolder().getSurface());
 84             
 85             mediaRecorder.setOnErrorListener(new OnErrorListener() {
 86                 
 87                 @Override
 88                 public void onError(MediaRecorder mr, int what, int extra) {
 89                     // 發生錯誤,停止錄制
 90                     mediaRecorder.stop();
 91                     mediaRecorder.release();
 92                     mediaRecorder = null;
 93                     isRecording=false;
 94                     btn_VideoStart.setEnabled(true);
 95                     btn_VideoStop.setEnabled(false);
 96                     Toast.makeText(VideoActivity.this, "錄制出錯", 0).show();
 97                 }
 98             });
 99             
100             // 准備、開始
101             mediaRecorder.prepare();
102             mediaRecorder.start();
103 
104             btn_VideoStart.setEnabled(false);
105             btn_VideoStop.setEnabled(true);
106             isRecording = true;
107             Toast.makeText(VideoActivity.this, "開始錄像", 0).show();
108         } catch (Exception e) {
109             e.printStackTrace();
110         }
111 
112     }
113 
114     protected void stop() {
115         if (isRecording) {
116             // 如果正在錄制,停止並釋放資源
117             mediaRecorder.stop();
118             mediaRecorder.release();
119             mediaRecorder = null;
120             isRecording=false;
121             btn_VideoStart.setEnabled(true);
122             btn_VideoStop.setEnabled(false);
123             Toast.makeText(VideoActivity.this, "停止錄像,並保存文件", 0).show();
124         }
125     }
126 
127     @Override
128     protected void onDestroy() {
129         if (isRecording) {
130             mediaRecorder.stop();
131             mediaRecorder.release();
132             mediaRecorder = null;
133         }
134         super.onDestroy();
135     }
136 
137 }

  錄制視頻需要用到麥克風和攝像頭硬件,還需要賦予一些相應的權限。

1     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
2     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3     <uses-permission android:name="android.permission.CAMERA"/>
4     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

  效果展示:

 

MediaRecorder的內部類

  通過上面錄制視頻的Demo可以看出,使用MediaRecorder錄制視頻,需要設置一些錄入源、編碼格式、輸出格式等。這些方法都是以int類型的參數設定的,它們其實都是在MediaRecorder的內部類中已經以常量的形式定義好了,直接適用場景進行選擇即可。

  • MediaRecorder.AudioEncoder:音頻的編碼格式。
  • MediaRecorder.AudioSource:錄制的音頻源。
  • MediaRecorder.OutputFormat:媒體文件的輸出編碼格式。
  • MediaRecorder.VideoEncoder:視頻的編碼格式。
  • MediaRecorder.VideoSource:錄制的視頻源。

 

  源碼下載

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM