Android MediaProjection學習(二)之和MediaRecorder實現錄屏

預備知識

Android MediaProjection學習(一)之實現屏幕截圖
通過預備知識我們應該知道MediaProjection的相關方法和知識。在屏幕截圖裏我們用了ImageReader來獲取截圖,而在這一節中我們通過另外一個工具MediaRecorder來獲取屏幕的視頻。

MediaRecorder

Google官方文檔:官方文檔

Used to record audio and video. The recording control is based on a simple state machine (see below).
在這裏插入圖片描述
A common case of using MediaRecorder to record audio works as follows:

MediaRecorder recorder = new MediaRecorder();
 recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
 recorder.setOutputFile(PATH_NAME);
 recorder.prepare();
 recorder.start();   // Recording is now started
 ...
 recorder.stop();
 recorder.reset();   // You can reuse the object by going back to setAudioSource() step
 recorder.release(); // Now the object cannot be reused

引用結束

其實我們結合流程圖來看就可以明白了,首先我們要初始化Recorder,調用相關方法。然後順着流程圖走,然後就是數據源的配置,方法如圖。配置完這些後我們就調用prepare()方法來讓Recorder處於預備狀態,最後調用start()就開始錄製了。

屏幕錄製

瞭解了上述知識以後我們就可以開始屏幕錄製了,現在只剩一個問題,那就是MediaRecorder的視頻源從哪來?我們先看看幾個常見的視頻源。
Constants

類型 名稱 解釋
int CAMERA Camera video source,Using the Camera API as video source.
int DEFAULT
int SURFACE Surface video source,Using a Surface as video source.

第一個CAMERA視頻源來自系統相機的API,第三個SURFACE則是通過surface來獲取視頻。是不是有頭緒了,沒錯我們的截屏就是通過ImageReader的getSurface方法獲取了surface然後轉換後就可以了。錄屏也是一樣,通過MediaRecorder的getSurface方法來獲取一個surface來錄屏就可以了。

這裏需要注意的一點就是,我們需要把我們的錄屏放在服務裏運行,就可以錄製我們程序以外的屏幕內容了。

代碼

首先我們需要獲取一個MediaProjection方法如下:

private MediaProjection createMediaProjection() {
        Log.i(TAG, "Create MediaProjection");
        return ((MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE)).getMediaProjection(mResultCode, mResultData);
    }

然後初始化MediaRecorder:

private MediaRecorder createMediaRecorder() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        Date curDate = new Date(System.currentTimeMillis());
        String curTime = formatter.format(curDate).replace(" ", "");
        String videoQuality = "HD";
        if(isVideoSd) videoQuality = "SD";

        Log.i(TAG, "Create MediaRecorder");
        MediaRecorder mediaRecorder = new MediaRecorder();
        if(isAudio) mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        mediaRecorder.setOutputFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + "/" + videoQuality + curTime + ".mp4");
        mediaRecorder.setVideoSize(mScreenWidth, mScreenHeight);  //after setVideoSource(), setOutFormat()
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);  //after setOutputFormat()
        if(isAudio) mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);  //after setOutputFormat()
        int bitRate;
        if(isVideoSd) {
            mediaRecorder.setVideoEncodingBitRate(mScreenWidth * mScreenHeight);
            mediaRecorder.setVideoFrameRate(30);
            bitRate = mScreenWidth * mScreenHeight / 1000;
        } else {
            mediaRecorder.setVideoEncodingBitRate(5 * mScreenWidth * mScreenHeight);
            mediaRecorder.setVideoFrameRate(60); //after setVideoSource(), setOutFormat()
            bitRate = 5 * mScreenWidth * mScreenHeight / 1000;
        }
        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Log.i(TAG, "Audio: " + isAudio + ", SD video: " + isVideoSd + ", BitRate: " + bitRate + "kbps");
        return mediaRecorder;
    }

這段代碼包含了錄製高清和普清視頻,幀率設置,視頻源,文件輸出路徑等。
最後我們調用MediaProjection的createVirtualDisplay方法:

 private VirtualDisplay createVirtualDisplay() {
        Log.i(TAG, "Create VirtualDisplay");
        return mMediaProjection.createVirtualDisplay(TAG, mScreenWidth, mScreenHeight, mScreenDensity,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null);
    }

這裏通過mMediaRecorder.getSurface()將屏幕內容給我們初始化的MediaRecorder,最後調用MediaRecorder的start()就可以將錄製的視頻輸出到我們指定的目錄下了。

Summary總結

我們捋一下錄屏的步驟。
Ⅰ 獲取MediaProjectionManager和MediaProjection
Ⅱ 初始化MediaRecorder
Ⅲ 調用MediaProjection的createVirtualDisplay方法傳入MediaRecorder的getSurface方法返回的surface
Ⅳ 調用MediaRecorder的start()方法
然後就可以實現錄屏功能了,開心๑乛◡乛๑。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章