Das Android Multimedia-Framework unterstützt die Erfassung und Codierung einer Vielzahl gängiger
Audio- und Videoformaten. Sie können die MediaRecorder
APIs verwenden, wenn diese unterstützt werden
durch die Gerätehardware.
In diesem Dokument erfährst du, wie du mit MediaRecorder
eine App programmierst, die Audio von einem Gerät aufzeichnet
Mikrofon, speichern Sie die Audiodatei und spielen Sie sie ab (mit MediaPlayer
). Um ein Video aufzunehmen, musst du
Verwende zusammen mit MediaRecorder
die Kamera des Geräts. Dies wird im Leitfaden zur Kamera beschrieben.
Hinweis: Der Android-Emulator kann keine Audio. Teste deinen Code unbedingt auf einem echten Gerät, das eine Aufnahme machen kann.
Berechtigung zum Aufzeichnen von Audio wird angefordert
Damit eine Aufzeichnung möglich ist, muss Ihre App den Nutzer darüber informieren, dass sie auf die die Audioeingabe des Geräts. Du musst dieses Berechtigungs-Tag in die Manifestdatei der App aufnehmen:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
RECORD_AUDIO
gilt als
„gefährlich“ Berechtigung
da sie ein Risiko für die Privatsphäre des Nutzers darstellen kann. Ab Android 6.0 (API-Level 23) eine App
die eine gefährliche Berechtigung verwendet, muss den Nutzer während der Laufzeit um Genehmigung bitten. Nachdem der Nutzer
sollte sich die App merken und nicht noch einmal fragen. Der Beispielcode unten zeigt, wie Sie
dieses Verhalten mithilfe von
ActivityCompat.requestPermissions()
MediaRecorder erstellen und ausführen
Neue Instanz von MediaRecorder
initialisieren
mit den folgenden Aufrufen:
- Audioquelle festlegen mit
setAudioSource()
Sie werden verwenden Sie wahrscheinlichMIC
.Hinweis:Bei den meisten Audioquellen, einschließlich
DEFAULT
, wird das Audiosignal. Wählen Sie zum Aufnehmen von Audio-Rohdaten die folgende Option aus:UNPROCESSED
Einige Geräte unterstützen unverarbeitete Daten nicht Eingabe. Rufen Sie zuerstAudioManager.getProperty(AudioManager.PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED)
an, um zu prüfen, ob das Produkt verfügbar ist. Ist dies nicht der Fall, verwenden Sie stattdessenVOICE_RECOGNITION
. ohne AGC und Rauschunterdrückung. Du kannstUNPROCESSED
verwenden als Audioquelle verwenden, auch wenn die Property nicht unterstützt wird. Es gibt jedoch keine Garantie, ist das Signal in diesem Fall unverarbeitet oder nicht. - Legen Sie das Ausgabedateiformat fest mit
setOutputFormat()
Hinweis: Ab Android 8.0 (API-Level 26) unterstütztMediaRecorder
MPEG2_TS Format, das sich für Streaming eignet:Kotlin
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS)
Java
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
- Legen Sie den Namen der Ausgabedatei fest.
setOutputFile()
Sie müssen einen Dateideskriptor angeben, der eine tatsächliche Datei darstellt. - Audio-Encoder mit einstellen
setAudioEncoder()
- Schließen Sie die Initialisierung ab, indem Sie den Aufruf
prepare()
Starten und stoppen Sie den Rekorder durch folgenden Aufruf:
start()
und
stop()
.
Wenn Sie mit der Instanz MediaRecorder
fertig sind, geben Sie deren Ressourcen kostenlos
so schnell wie möglich, indem Sie uns unter
release()
.
Hinweis:Auf Geräten mit Android 9 (API-Level 28) oder
können im Hintergrund ausgeführte Apps nicht auf das Mikrofon zugreifen. Dementsprechend wird
sollte Ihre App Audio nur dann aufzeichnen, wenn sie im Vordergrund läuft oder
eine Instanz von MediaRecorder
in eine
Service im Vordergrund.
Mit MediaMuxer mehrere Kanäle aufzeichnen
Ab Android 8.0 (API-Level 26) kannst du eine MediaMuxer
verwenden
um mehrere Audio- und Videostreams gleichzeitig aufzuzeichnen. In früheren Android-Versionen ist
jeweils nur einen Audiotrack und/oder einen einzelnen Videotrack aufzeichnen.
addTrack()
verwenden
, um mehrere Tracks zu mischen.
Sie können auch einen oder mehrere Metadaten-Tracks mit benutzerdefinierten Informationen für jeden Frame hinzufügen. nur in MP4-Containern. Deine App definiert das Format und den Inhalt der Metadaten.
Metadaten hinzufügen
Metadaten können für die Offlineverarbeitung nützlich sein. Zum Beispiel erfasste Daten könnte der Gyrosensor für die Videostabilisierung genutzt werden.
Wenn du einen Metadatentrack hinzufügst, muss das MIME-Format des Titels mit dem Präfix beginnen
application/
Das Schreiben von Metadaten entspricht dem Schreiben von Video- oder Audiodaten, mit folgenden Ausnahmen:
dass die Daten nicht aus einem MediaCodec
stammen. Stattdessen gibt die App eine
ByteBuffer
mit einem zugehörigen Zeitstempel für den
writeSampleData()
-Methode.
Der Zeitstempel muss dieselbe Zeitbasis haben wie die Video- und Audiotracks.
Die generierte MP4-Datei verwendet die in Abschnitt 12.3.3.2 definierte TextMetaDataSampleEntry
der Spezifikation ISO BMFF
um das MIME-Format der Metadaten zu signalisieren. Wenn Sie ein MediaExtractor
zum Extrahieren einer Datei mit Metadaten-Tracks verwenden, wird der MIME-Typ der Metadaten
Format wird als Instanz von MediaFormat
angezeigt.
Beispielcode
Den MediaRecorder Das Beispiel zeigt, wie Sie mit MediaRecorder und der Camera API eine Videoaufzeichnung erstellen.
Die Beispielaktivität unten zeigt, wie Sie mit MediaRecorder
eine Audiodatei aufzeichnen. Es
Verwendet außerdem MediaPlayer
für die Audiowiedergabe.
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; } } }
Weitere Informationen
Auf diesen Seiten werden Themen zum Aufzeichnen, Speichern und Abspielen von Audio- und Videoinhalten behandelt.