2011-01-17 24 views
11

estoy usando un SoundPool para reproducir clips de audio en mi aplicación. Todo está bien, pero necesito saber cuándo ha finalizado la reproducción del clip.¿Cuál es la mejor forma de obtener una duración de archivo de audio en Android?

Por el momento lo sigo en mi aplicación obteniendo la duración de cada clip usando una instancia MediaPlayer. Eso funciona bien, pero parece un desperdicio cargar cada archivo dos veces, solo para obtener la duración. Pude calcular aproximadamente la duración, conociendo la longitud del archivo (disponible en el AssetFileDescriptor), pero aún necesito saber la frecuencia de muestreo y la cantidad de canales.

veo dos soluciones posibles a este problema:

  1. Averiguar cuando un clip ha terminado de jugar (no parece ser posible con soundclip).
  2. Tener una clase que podría cargar solo el encabezado de un archivo de audio y darme la frecuencia de muestreo/número de canales (y, idealmente, el recuento de muestras para obtener la duración exacta).

¿Alguna sugerencia?

Gracias, Max

El código que estoy usando en este momento (funciona bien, pero es bastante pesado para el propósito):

String[] fileNames = ... 
MediaPlayer mp = new MediaPlayer(); 
for (String fileName : fileNames) { 
    AssetFileDescriptor d = context.getAssets().openFd(fileName); 
    mp.reset(); 
    mp.setDataSource(d.getFileDescriptor(), d.getStartOffset(), d.getLength()); 
    mp.prepare(); 
    int duration = mp.getDuration(); 
    // ... 
} 

En una nota lateral, esta cuestión ya ha sido asked pero no obtuve ninguna respuesta.

+0

¿ha considerado un 'onCompletitionListener'? https://developer.android.com/reference/android/media/MediaPlayer.OnCompletionListener.html#onCompletion%28android.media.MediaPlayer%29 – sschrass

+0

@SatelliteSD simplemente no funciona (nunca se llama) en ninguno de los dispositivos Yo tengo. Incluso si recibe una llamada en algunas versiones del sistema operativo/algunos dispositivos, no es confiable y, por lo tanto, inútil. – Gilead

+1

ha verificado dos veces que se llama a 'setOnCompletitionListner' después de' .start() '? – sschrass

Respuesta

9

¿Usted intentó esto:

String mediaPath = Uri.parse("android.resource://<your-package-name>/raw/filename").getPath(); 
MediaMetadataRetriever mmr = new MediaMetadataRetriever(); 
mmr.setDataSource(mediaPath); 
String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); 
mmr.release(); 

pero no estoy muy seguro de que esto es más ligero que exisiting código.

+3

No se olvide de liberar el 'MediaMetadataRetriever' –

+0

Intenté esto, pero siempre me arrojaron una IllegalArgumentException de' mmr.setDataSource() '- ¿hay alguna manera de descubrir cómo debería ser exactamente esa ruta? Porque sospecho que la ruta que uso podría ser incorrecta. Estoy usando archivos de audio in-bundle .m4a y/o .wav. – Jonny

+1

@Meher respuesta perfecta +1 –

3

Trate FFmpegMediaMetadataRetriever:

String[] fileNames = ... 
FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever(); 

for (String fileName : fileNames) { 
    AssetFileDescriptor d = context.getAssets().openFd(fileName); 
    mmr.setDataSource(d.getFileDescriptor(), d.getStartOffset(), d.getLength()); 
    String duration = mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION); 
} 

mmr.release(); 
0

este es un trabajo para mí para obtener activos duración archivo de audio en el total de segundos =====>

MediaMetadataRetriever mmr = new MediaMetadataRetriever(); 
AssetFileDescriptor d = context.getAssets().openFd(fileName); 
mmr.setDataSource(d.getFileDescriptor(), d.getStartOffset(), d.getLength()); 
String duration = 
mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); 
mmr.release(); 

Updated

método para obtener activos archivo de audio du ración en cuestión de segundos

public String gettotaltimeassets() { 

    MediaMetadataRetriever mmr = new MediaMetadataRetriever(); 
    AssetFileDescriptor d = null; 
    try { 
     d = getApplicationContext().getAssets().openFd("ASSETS FILE NAME"); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    mmr.setDataSource(d.getFileDescriptor(), d.getStartOffset(), d.getLength()); 
    String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); 
    long dur = Long.parseLong(duration); 
    String seconds = String.valueOf((dur % 60000)/1000); 
    Log.d("seconds===========>", seconds); 
    mmr.release(); 
    return seconds; 
} 

método para obtener la duración archivo de audio almacenamiento interno en cuestión de segundos

public String gettotaltimestorage(String filePath) { 
    // load data file 
    Log.d("time=================>","time=================>"); 
    MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever(); 
    metaRetriever.setDataSource(YourACTIVITY.this, Uri.parse(filePath)); 
    Log.d("time=================>","time=================>"); 
    String out = ""; 
    // get mp3 info 

    // convert duration to minute:seconds 
    String duration = 
      metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); 
    Log.d("time=================>", duration); 
    long dur = Long.parseLong(duration); 
    String seconds = String.valueOf((dur % 60000)/1000); 
    Log.d("seconds===========>", seconds); 
    // close object 
    metaRetriever.release(); 
    return seconds; 

} 
+0

Proporcione una explicación a su respuesta. Esto no solo ayudará a comprender la causa del problema actual, sino también a evitarlo en el futuro. –

+0

en realidad escribo código para obtener la duración de cualquier archivo de audio en activos como @William Seemann escribe, pero uso MediaMetadata para recuperar la duración ... modifico mi respuesta para que entienda mejor ... puede llamar a este método para múltiples archivos de audio para obtener duración –

+0

No escribí ese comentario porque no pude entender su código, pero es una buena práctica en SO para acompañar su solución con la explicación adecuada. Las respuestas de solo código no son muy apreciadas. –

Cuestiones relacionadas