MediaRecorder – Übersicht

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 wahrscheinlich MIC.

    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 zuerst AudioManager.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 stattdessen VOICE_RECOGNITION. ohne AGC und Rauschunterdrückung. Du kannst UNPROCESSED 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ützt MediaRecorder 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.