Le framework multimédia Android prend en charge la capture et l'encodage de divers types
aux formats audio et vidéo. Vous pouvez utiliser les API MediaRecorder
si elles sont compatibles
par le matériel de l'appareil.
Ce document explique comment utiliser MediaRecorder
pour écrire une application qui enregistre du contenu audio à partir d'un appareil.
micro, enregistrer le contenu audio et le lire (avec MediaPlayer
). Pour enregistrer une vidéo, vous devez :
utiliser l'appareil photo de l'appareil avec MediaRecorder
. Pour en savoir plus, consultez le guide Appareil photo.
Remarque:Android Emulator ne peut pas enregistrer audio. Veillez à tester votre code sur un appareil réel capable d'enregistrer.
Demander l'autorisation d'enregistrer du contenu audio
Pour pouvoir enregistrer, votre application doit indiquer à l'utilisateur qu'elle accédera à l'entrée audio de l'appareil. Vous devez inclure cette balise d'autorisation dans le fichier manifeste de l'application:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
RECORD_AUDIO
est considéré comme un
"dangereux" autorisation
car il peut présenter un risque
pour la confidentialité de l'utilisateur. Application à partir d'Android 6.0 (niveau d'API 23)
qui utilise une autorisation dangereuse
doit demander l'approbation de l'utilisateur au moment de l'exécution. Une fois que l'utilisateur a
accorder l'autorisation, l'application
doit se souvenir et ne plus demander. L'exemple de code ci-dessous montre comment
implémenter ce comportement en utilisant
ActivityCompat.requestPermissions()
Créer et exécuter un MediaRecorder
Initialiser une nouvelle instance de MediaRecorder
avec les appels suivants:
- Définir la source audio avec
setAudioSource()
Vous allez utilisent probablementMIC
.Remarque:La plupart des sources audio (y compris
DEFAULT
) appliquent le traitement le signal audio. Pour enregistrer un fichier audio brut, sélectionnezUNPROCESSED
Certains appareils ne sont pas compatibles avec les données non traitées saisie. Appelez d'abordAudioManager.getProperty(AudioManager.PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED)
pour vérifier qu'elle est disponible. Si ce n'est pas le cas, essayez d'utiliserVOICE_RECOGNITION
à la place. qui n'utilise pas l'AGC ni la suppression du bruit. Vous pouvez utiliserUNPROCESSED
comme source audio, même lorsque la propriété n'est pas compatible, mais qu'il n'y a aucune garantie le signal ne sera pas traité ou pas dans ce cas. - Définissez le format du fichier de sortie à l'aide de
setOutputFormat()
Notez qu'à partir d'Android 8.0 (niveau d'API 26),MediaRecorder
est compatible avec le format MPEG2_TS , ce qui est utile pour le streaming:Kotlin
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS)
Java
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
- Définissez le nom du fichier de sortie à l'aide de
setOutputFile()
Vous devez spécifier un descripteur de fichier qui représente un fichier réel. - Configurez l'encodeur audio avec
setAudioEncoder()
- Terminez l'initialisation en appelant
prepare()
Démarrez et arrêtez l'enregistreur en appelant
start()
et
stop()
respectivement.
Lorsque vous avez terminé d'utiliser l'instance MediaRecorder
, libérez ses ressources
dès que possible en appelant
release()
Remarque:Sur les appareils équipés d'Android 9 (niveau d'API 28) ou
supérieur, les applications exécutées en arrière-plan ne peuvent pas accéder au micro. Par conséquent,
votre application ne doit enregistrer du contenu audio que lorsqu'elle est exécutée au premier plan ou lorsque vous
inclure une instance de MediaRecorder
dans un
service de premier plan.
Utiliser MediaMuxer pour enregistrer plusieurs canaux
À partir d'Android 8.0 (niveau d'API 26), vous pouvez utiliser un MediaMuxer
.
pour enregistrer plusieurs flux audio et vidéo simultanés. Dans les versions antérieures d'Android, vous ne pouvez
enregistrer une piste audio et/ou une piste vidéo à la fois.
Utiliser le addTrack()
pour mixer plusieurs pistes.
Vous pouvez aussi ajouter une ou plusieurs pistes de métadonnées avec des informations personnalisées pour chaque image, mais uniquement aux conteneurs MP4. Votre application définit le format et le contenu des métadonnées.
Ajouter des métadonnées
Les métadonnées peuvent être utiles pour un traitement hors connexion. Par exemple, les données collectées à partir de le capteur du gyroscope peut être utilisé pour effectuer la stabilisation vidéo.
Lorsque vous ajoutez une piste de métadonnées, le format MIME de la piste doit commencer par le préfixe
application/
L'écriture de métadonnées est identique à l'écriture de données vidéo ou audio, sauf
que les données ne proviennent pas d'un MediaCodec
. Au lieu de cela, l'application transmet
ByteBuffer
par un horodatage associé à
writeSampleData()
.
Le code temporel doit être identique à celui des pistes vidéo et audio.
Le fichier MP4 généré utilise le TextMetaDataSampleEntry
défini dans la section 12.3.3.2
de la spécification ISO BMFF
pour signaler le format MIME des métadonnées. Lorsque vous utilisez un MediaExtractor
pour extraire un fichier contenant des pistes de métadonnées, la méthode MIME
apparaît en tant qu'instance de MediaFormat
.
Exemple de code
MediaRecorder montre comment créer un enregistrement vidéo à l'aide de MediaRecorder et de l'API Camera.
L'exemple d'activité ci-dessous montre comment utiliser MediaRecorder
pour enregistrer un fichier audio. Il
Utilise également MediaPlayer
pour lire l'audio.
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; } } }
En savoir plus
Ces pages traitent de sujets liés à l'enregistrement, au stockage et à la lecture de contenus audio et vidéo.