讀古今文學網 > Android程序設計:第2版 > 錄製音頻和視頻 >

錄製音頻和視頻

標準的支持錄製的類是MediaRecorder。和Media Player類似,MediaRecorder在其生命週期內也會傳遞各種狀態。這些狀態如下所示(關於這些狀態的更多詳細信息,可以查看開發者網站中給出的狀態圖,http://developer.android.com/reference/android/media/MediaRecorder.html):

Initial

MediaRecorder類執行實例化。

Initialized

MediaRecorder執行了初始化,可以使用了。

DataSource Configured

對媒體資源(指定在哪裡輸出)進行配置。

Prepared

準備好MediaRecorder,用於記錄。

Recording

正在執行記錄。

Released

釋放所有的資源。

要使用MediaRecorder,在清單文件中要設置某些許可:

·要支持視頻記錄,選擇RECORD_VIDEO和CAMERA:


      <uses-permission android:name=\"android.permission.RECORD_VIDEO\"/>
      <uses-permission android:name=\"android.permission.CAMERA\"/>
  

·要記錄音頻,選擇:


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

錄製音頻

有3種錄製音頻的方式。標準方式是使用MediaRecorder;最簡單的方式是使用Intent;AudioRecorder可以直接從硬件緩衝區中錄製。

MediaRecorder音頻錄製

首先,初始化MediaRecorder。然後設置數據源信息(音頻輸入源、輸出格式、編碼類型,在哪裡錄製文件等)。從版本8開始,還可以設置比特率和樣本比率。完成這些後,調用prepare方法。


// initialize the MediaRecorder
MediaRecorder mediarecorder = new MediaRecorder;
// configure the data source
    // the source of the audio input
    mediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    // output format
    mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    // encoding
    mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    // use absolute path to file where output is stored
    mediarecorder.setOutputFile(\"/sdcard/audiorecordexample.3gpp\");
    // prepare to record
    mediarecorder.prepare;
  

然後,當需要啟動錄製時,執行start方法:


mediarecorder.start;
  

要停止錄製,可以調用stop方法。如果後來又想繼續錄製,則可以調用reset方法強制MediaRecorder回到空閒狀態。然後重新配置數據源,再次準備MediaRecorder:


mediarecorder.stop;
...
mediarecorder.reset;
  

一旦不再需要MediaRecorder,要記得釋放它:


mediarecorder.release;
  

下面是一個簡單的應用示例,它為用戶提供record按鈕。單擊該按鈕,record方法會在已經指向的文件路徑下錄製。然後,會顯示stop按鈕,record按鈕會變得不可見。當單擊stop按鈕時,會調用stopRecord方法,又重新顯示record按鈕。


public class AudioRecorder extends Activity {
    private MediaRecorder mediarecorder;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.audiorecorderlayout);
        ImageButton recordbutton = (ImageButton) findViewById(R.id.record);
        recordbutton.setOnClickListener(new OnClickListener {
            public void onClick(View v) {
                record(\"/sdcard/audiorecordexample.3gpp\");
            }
        });
        ImageButton stopbutton = (ImageButton) findViewById(R.id.stop);
        stopbutton.setOnClickListener(new OnClickListener {
            public void onClick(View v) {
                stopRecord;
            }
        });
    }
    private void record(String filePath) {
            try {
                File mediafile = new File(filePath);
                if(mediafile.exists) {
                    mediafile.delete;
                }
                mediafile = null;
                // record button goes away
                ImageButton button = (ImageButton) findViewById(R.id.record);
                button.setVisibility(View.GONE);
                    // stop button shows up
                ImageButton stopbutton = (ImageButton) findViewById(R.id.stop);
                stopbutton.setVisibility(View.VISIBLE);
                    // set up media recorder
                if(mediarecorder == null) mediarecorder = new MediaRecorder;
                mediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                mediarecorder.setOutputFile(filePath);
                    // prepare media recorder
                mediarecorder.prepare;
                    // start media recorder
                mediarecorder.start;
            } catch (Exception e) {
                e.printStackTrace;
            }
        }
    }
    private void stopRecord {
                    // stop media recorder
                mediarecorder.stop;
                    // reset media recorder
                mediarecorder.reset;
                // record button shows up
                ImageButton button = (ImageButton) findViewById(R.id.record);
                button.setVisibility(View.VISIBLE);
                // stop button goes away
                ImageButton stopbutton = (ImageButton) findViewById(R.id.stop);
                stopbutton.setVisibility(View.GONE);
    }
}
 

使用Intent錄製音頻

通過Intent錄製是最簡單的方式。只需要構建Media Store.Audio.Media.RECORD_SOUND_ACTION intent,然後在Activity內調用startActivityForResult方法啟動它,它會啟動在大多數Android設備中都會提供的默認音頻錄製程序,繼續錄製一些音頻:


Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(intent, 1); // intent and requestCode of 1
  

錄製完成後,音頻錄製程序結束,啟動調用startActivityForResult方法的Activity會到前端執行。當發生這種情況時,會觸發Activity的onActivityResult方法,其中包括了我們提供的requestCode代碼(在這個例子中,即1),結果代碼(OK或error),以及包含指向記錄的音頻文件的intent:


protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    // is it our requestCode?
    if (requestCode == 1) {
        // is the resultCode OK?
      if (resultCode == RESULT_OK) {
                // lets get the uri
              Uri audioUri = intent.getData;
                // lets play the uri or do something with it.
              playAudio(audioUri);
         }
    }
}
  

AudioRecorder音頻錄製

和AudioTrack類似,AudioRecorder提供了更直接的錄製體驗:


short buffer = new short[10000];
recorder = new AudioRecord( // source to record from
                    MediaRecorder.AudioSource.MIC,
                            // frequency
                    11025,
                            // channel config
—mono, stereo, etc.
                    AudioFormat.CHANNEL_CONFIGURATION_MONO,
                            // audio encoding
                    AudioFormat.ENCODING_PCM_16BIT,
                            // buffer size
                    buffer.length
                );
  

AudioRecord方法提供了需要錄製的音頻資源類型(話筒、攝像機話筒、或語音呼叫)、以Hz表示的採樣比率(44100、22050或11025)、音頻配置(單聲道或立體聲)、音頻格式/編碼、以字節數表示的緩衝區長度。注意,緩衝區的大小決定了AudioRecord在讀取運行數據之前能夠錄製的時間。數據應該從音頻硬件中讀取,以小於總錄製緩衝區的大小讀取。Android的AudioRecord一旦配置完成,會自動知道如何使用設備上的硬件接口,從而提供愉快的用戶體驗。

為開始錄製,設置AudioRecord的Record狀態,重複從硬件緩衝區中讀取數據:


recorder.startRecording;
while(recordablestate) {
    try {
        // read in up to buffer size
        int readBytes = recorder.read(buffer, 0, buffer.length);
        // do something with the bytes that are read
        } catch (Exception t) {
          recordablestate = false;
        }
}
  

要停止錄製,將AudioRecord的狀態置為Stop。如果不想錄製,則不要忘記釋放和錄製相關的所有資源。如果還想繼續錄製,可以調用startRecording方法再開始錄製:


// stop recording
recorder.stop;
// release recording resources
recorder.release;
  

視頻錄製

可以通過兩種方式錄製視頻:通過使用MediaRecorder或通過使用Intent。不支持類似音頻那樣的原始錄製。

MediaRecorder視頻錄製

通過MediaRecorder錄製視頻的過程和錄製音頻的過程非常相似:初始化MediaRecorder,準備數據源,啟動MediaRecorder。可以給用戶提供預覽窗口,這樣他可以預覽捕捉到的視頻,通過提供之前提到的surface來播放視頻。一般來說,會使用VideoView:


// initialize
MediaRecorder mediarecorder = new MediaRecorder;
// set data source
mediarecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
mediarecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mediarecorder.setOutputFile(\"/sdcard/someexamplevideo.mp4\");
// provide a surface to show the preview in. in this case a VideoView is used
videoview = (VideoView) findViewById(R.id.videosurface);
SurfaceHolder holder = videoview.getHolder;
mediarecorder.setPreviewDisplay(holder.getSurface);
// prepare
mediarecorder.prepare;
// start recording
mediarecorder.start;
  

intent視頻錄製

基於intent的視頻錄製和使用intent錄製音頻類似。要使用的intent是MediaStore.ACTION_VIDEO_CAPTURE,結果數據是視頻文件的URI。