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; } } }
詳細
以下は音声と動画の録音、録画、保存、再生に関するトピックを扱うページです。