MediaRecorder の概要

Android マルチメディア フレームワークは、一般的な各種の一般的な画像のキャプチャとエンコードを 生成できます。サポートされている場合は MediaRecorder API を使用できます。 デバイスハードウェアによって 制御されます

このドキュメントでは、MediaRecorder を使用してデバイスから音声をキャプチャするアプリを作成する方法について説明します。 音声の保存、再生ができます(MediaPlayer を使用)。動画を撮影するための要件 MediaRecorder とともにデバイスのカメラを使用する。これについては、カメラのガイドをご覧ください。

注: Android Emulator では、録画は行えません。 生成できます。必ず、録音できる実機を使ってコードをテストしてください。

録音する権限をリクエストする

記録できるようにするには、アプリが デバイスのオーディオ入力。この権限タグは、アプリのマニフェスト ファイルに追加する必要があります。

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

RECORD_AUDIO: 「dangerous」権限 ユーザーのプライバシーを侵害するおそれがあるためです。Android 6.0(API レベル 23)以降では、 危険な権限を使用するアプリは、実行時にユーザーに承認を求める必要があります。ユーザーが アプリが記憶し、再度要求しないようにする必要があります。以下のサンプルコードは、 この動作を実装するには、 ActivityCompat.requestPermissions()

MediaRecorder を作成して実行する

MediaRecorder の新しいインスタンスを初期化する 次の呼び出しに置き換えます。

  • 以下を使用してオーディオ ソースを設定します。 setAudioSource()。これから MIC を使用する可能性があります。

    注: ほとんどのオーディオ ソース(DEFAULT を含む)は、 受信します。未加工の音声を録音するには、 UNPROCESSED。一部のデバイスは未処理の 表示されます。まず AudioManager.getProperty(AudioManager.PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED) に電話をかけて、利用可能であることを確認してください。 そうでない場合は、代わりに VOICE_RECOGNITION を使用してみてください。 AGC もノイズ サプレッションも使用しません。UNPROCESSED を使用できます。 プロパティがサポートされていない場合でもオーディオ ソースとして認識されますが、 この場合、シグナルは未処理であるか、処理されません。

  • 出力ファイルの形式を設定します。 setOutputFormat()。 なお、Android 8.0(API レベル 26)以降、MediaRecorder は MPEG2_TS をサポートしています。 ストリーミングに便利です。

    Kotlin

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS)
    

    Java

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
    
  • 出力ファイル名を setOutputFile()。 実際のファイルを表すファイル記述子を指定する必要があります。
  • 以下を使用して音声エンコーダを設定します。 setAudioEncoder()
  • 次の関数を呼び出して初期化を完了します。 prepare()

次の呼び出しでレコーダーを開始、停止します start()stop() できます。

MediaRecorder インスタンスで作業が完了したら、インスタンスのリソースを解放します。 できるだけ早く release()

注: Android 9(API レベル 28)または それ以降、バックグラウンドで実行されているアプリはマイクにアクセスできません。したがって、 アプリがフォアグラウンドにある場合、または MediaRecorder のインスタンスを フォアグラウンド サービス

MediaMuxer を使って複数チャンネルを記録する

Android 8.0(API レベル 26)以降では、MediaMuxer を使用して、複数の音声ストリームや動画ストリームを同時に録画できます。以前のバージョンの Android では、 音声トラックや動画トラックを 1 つずつ録音する。

addTrack() を使用する メソッドを使用して、複数のトラックをミックスできます。

フレームごとにカスタム情報を含むメタデータ トラックを 1 つ以上追加することもできますが、 アップロードできます。アプリではメタデータの形式とコンテンツを定義します。

メタデータを追加する

メタデータをオフライン処理に活用できます。たとえば ジャイロセンサーを使って動画の手ぶれ補正を行えます

メタデータ トラックを追加する場合、トラックの MIME 形式を接頭辞で始める必要があります。 application/。メタデータの書き込みは、動画データや音声データの書き込みと同じですが、 データが MediaCodec から取得されたものではないことを確認します。代わりに、アプリは タイムスタンプに関連付けられた ByteBuffer writeSampleData() メソッドを使用します。 タイムスタンプは、動画および音声トラックと同じタイムベースである必要があります。

生成される MP4 ファイルは、セクション 12.3.3.2 で定義された TextMetaDataSampleEntry を使用します。 ISO BMFF 仕様 MIME 形式を通知します。MediaExtractor を使用してメタデータ トラックを含むファイルを抽出すると、メタデータの MIME が 形式が MediaFormat のインスタンスとして表示されます。

サンプルコード

MediaRecorder サンプルは、MediaRecorder と Camera API を使用して動画を撮影する方法を示しています。

下記のサンプル アクティビティでは、MediaRecorder を使って音声ファイルを録音する方法を示します。これは、 また、MediaPlayer を使用して音声を再生します。

Kotlin

package com.android.audiorecordtest

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.media.MediaPlayer
import android.media.MediaRecorder
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.Button
import android.widget.LinearLayout
import java.io.IOException

private const val LOG_TAG = "AudioRecordTest"
private const val REQUEST_RECORD_AUDIO_PERMISSION = 200

class AudioRecordTest : AppCompatActivity() {

    private var fileName: String = ""

    private var recordButton: RecordButton? = null
    private var recorder: MediaRecorder? = null

    private var playButton: PlayButton? = null
    private var player: MediaPlayer? = null

    // Requesting permission to RECORD_AUDIO
    private var permissionToRecordAccepted = false
    private var permissions: Array<String> = arrayOf(Manifest.permission.RECORD_AUDIO)

    override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<String>,
            grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        permissionToRecordAccepted = if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
            grantResults[0] == PackageManager.PERMISSION_GRANTED
        } else {
            false
        }
        if (!permissionToRecordAccepted) finish()
    }

    private fun onRecord(start: Boolean) = if (start) {
        startRecording()
    } else {
        stopRecording()
    }

    private fun onPlay(start: Boolean) = if (start) {
        startPlaying()
    } else {
        stopPlaying()
    }

    private fun startPlaying() {
        player = MediaPlayer().apply {
            try {
                setDataSource(fileName)
                prepare()
                start()
            } catch (e: IOException) {
                Log.e(LOG_TAG, "prepare() failed")
            }
        }
    }

    private fun stopPlaying() {
        player?.release()
        player = null
    }

    private fun startRecording() {
        recorder = MediaRecorder().apply {
            setAudioSource(MediaRecorder.AudioSource.MIC)
            setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
            setOutputFile(fileName)
            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)

            try {
                prepare()
            } catch (e: IOException) {
                Log.e(LOG_TAG, "prepare() failed")
            }

            start()
        }
    }

    private fun stopRecording() {
        recorder?.apply {
            stop()
            release()
        }
        recorder = null
    }

    internal inner class RecordButton(ctx: Context) : Button(ctx) {

        var mStartRecording = true

        var clicker: OnClickListener = OnClickListener {
            onRecord(mStartRecording)
            text = when (mStartRecording) {
                true -> "Stop recording"
                false -> "Start recording"
            }
            mStartRecording = !mStartRecording
        }

        init {
            text = "Start recording"
            setOnClickListener(clicker)
        }
    }

    internal inner class PlayButton(ctx: Context) : Button(ctx) {
        var mStartPlaying = true
        var clicker: OnClickListener = OnClickListener {
            onPlay(mStartPlaying)
            text = when (mStartPlaying) {
                true -> "Stop playing"
                false -> "Start playing"
            }
            mStartPlaying = !mStartPlaying
        }

        init {
            text = "Start playing"
            setOnClickListener(clicker)
        }
    }

    override fun onCreate(icicle: Bundle?) {
        super.onCreate(icicle)

        // Record to the external cache directory for visibility
        fileName = "${externalCacheDir.absolutePath}/audiorecordtest.3gp"

        ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION)

        recordButton = RecordButton(this)
        playButton = PlayButton(this)
        val ll = LinearLayout(this).apply {
            addView(recordButton,
                    LinearLayout.LayoutParams(
                            ViewGroup.LayoutParams.WRAP_CONTENT,
                            ViewGroup.LayoutParams.WRAP_CONTENT,
                            0f))
            addView(playButton,
                    LinearLayout.LayoutParams(
                            ViewGroup.LayoutParams.WRAP_CONTENT,
                            ViewGroup.LayoutParams.WRAP_CONTENT,
                            0f))
        }
        setContentView(ll)
    }

    override fun onStop() {
        super.onStop()
        recorder?.release()
        recorder = null
        player?.release()
        player = null
    }
}

Java

package com.android.audiorecordtest;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;

import java.io.IOException;

public class AudioRecordTest extends AppCompatActivity {

    private static final String LOG_TAG = "AudioRecordTest";
    private static final int REQUEST_RECORD_AUDIO_PERMISSION = 200;
    private static String fileName = null;

    private RecordButton recordButton = null;
    private MediaRecorder recorder = null;

    private PlayButton   playButton = null;
    private MediaPlayer   player = null;

    // Requesting permission to RECORD_AUDIO
    private boolean permissionToRecordAccepted = false;
    private String [] permissions = {Manifest.permission.RECORD_AUDIO};

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case REQUEST_RECORD_AUDIO_PERMISSION:
                permissionToRecordAccepted  = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                break;
        }
        if (!permissionToRecordAccepted ) finish();

    }

    private void onRecord(boolean start) {
        if (start) {
            startRecording();
        } else {
            stopRecording();
        }
    }

    private void onPlay(boolean start) {
        if (start) {
            startPlaying();
        } else {
            stopPlaying();
        }
    }

    private void startPlaying() {
        player = new MediaPlayer();
        try {
            player.setDataSource(fileName);
            player.prepare();
            player.start();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }
    }

    private void stopPlaying() {
        player.release();
        player = null;
    }

    private void startRecording() {
        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setOutputFile(fileName);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            recorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }

        recorder.start();
    }

    private void stopRecording() {
        recorder.stop();
        recorder.release();
        recorder = null;
    }

    class RecordButton extends Button {
        boolean mStartRecording = true;

        OnClickListener clicker = new OnClickListener() {
            public void onClick(View v) {
                onRecord(mStartRecording);
                if (mStartRecording) {
                    setText("Stop recording");
                } else {
                    setText("Start recording");
                }
                mStartRecording = !mStartRecording;
            }
        };

        public RecordButton(Context ctx) {
            super(ctx);
            setText("Start recording");
            setOnClickListener(clicker);
        }
    }

    class PlayButton extends Button {
        boolean mStartPlaying = true;

        OnClickListener clicker = new OnClickListener() {
            public void onClick(View v) {
                onPlay(mStartPlaying);
                if (mStartPlaying) {
                    setText("Stop playing");
                } else {
                    setText("Start playing");
                }
                mStartPlaying = !mStartPlaying;
            }
        };

        public PlayButton(Context ctx) {
            super(ctx);
            setText("Start playing");
            setOnClickListener(clicker);
        }
    }

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        // Record to the external cache directory for visibility
        fileName = getExternalCacheDir().getAbsolutePath();
        fileName += "/audiorecordtest.3gp";

        ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION);

        LinearLayout ll = new LinearLayout(this);
        recordButton = new RecordButton(this);
        ll.addView(recordButton,
                new LinearLayout.LayoutParams(
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        0));
        playButton = new PlayButton(this);
        ll.addView(playButton,
                new LinearLayout.LayoutParams(
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        0));
        setContentView(ll);
    }

    @Override
    public void onStop() {
        super.onStop();
        if (recorder != null) {
            recorder.release();
            recorder = null;
        }

        if (player != null) {
            player.release();
            player = null;
        }
    }
}

詳細

以下は音声と動画の録音、録画、保存、再生に関するトピックを扱うページです。