2013-03-13 12 views
11

Zrobiłem aplikację do nagrywania głosu i chcę pokazać czas nagrań w widoku listy. Zapisuję nagrania w ten sposób:uzyskać czas trwania pliku audio

MediaRecorder recorder = new MediaRecorder(); 
recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); 
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); 
folder = new File(Environment.getExternalStorageDirectory() 
      + File.separator + "Audio recordings"); 
String[] files = folder.list(); 
    int number = files.length + 1; 
    String filename = "AudioSample" + number + ".mp3"; 
    File output = new File(Environment.getExternalStorageDirectory() 
      + File.separator + "Audio recordings" + File.separator 
      + filename); 
    FileOutputStream writer = new FileOutputStream(output); 
    FileDescriptor fd = writer.getFD(); 
    recorder.setOutputFile(fd); 
    try { 
     recorder.prepare(); 
     recorder.start(); 
    } catch (IllegalStateException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     Log.e(LOG_TAG, "prepare() failed"); 
     e.printStackTrace(); 
    } 

Jak mogę uzyskać czas trwania w sekundach tego pliku?

góry dzięki

--- EDIT mam to działa, zadzwoniłem MediaPlayer.getduration() wewnątrz MediaPlayer.setOnPreparedListener() metoda więc wrócił 0.

Odpowiedz

0

Po zapisać plik , otwórz go w MediaPlayer i wywołaj na nim getDuration.

+0

Tried to, ale to zawsze zwraca 0 z jakiegoś powodu – Simon

+1

Nieważne, że to działa! Nazwałem MediaPlayer.getDuration() w metodzie MediaPlayer.setOnPreparedListener, a następnie zwrócono 0 – Simon

10

użycie Spróbuj

long totalDuration = mediaPlayer.getDuration(); // to get total duration in milliseconds 

long currentDuration = mediaPlayer.getCurrentPosition(); // to Gets the current playback position in milliseconds 

Division na 1000 do konwersji sekund.

Mam nadzieję, że to pomogło.

+1

MediaPlayer.getduration() zwraca 0 z jakiegoś dziwnego powodu, czy wiesz dlaczego? – Simon

19

Albo spróbuj tego, aby uzyskać czas w milisekundach:

MediaPlayer mp = MediaPlayer.create(yourActivity, Uri.parse(pathofyourrecording)); 
int duration = mp.getDuration(); 

Albo zmierzyć czas, jaki upłynął od recorder.start() do recorder.stop() w nanosekund:

long startTime = System.nanoTime();  
// ... do recording ...  
long estimatedTime = System.nanoTime() - startTime; 
+0

pierwsza zwraca 0, a jeśli chcę użyć drugiego rozwiązania, muszę odtworzyć plik i nie chcę tego. – Simon

+0

Nie musisz odtwarzać pliku dla drugiego. Ustawiasz startTime, kiedy użytkownik rozpoczyna nagrywanie i oblicza szacunkowy czas, gdy użytkownik zatrzyma nagrywanie. Dla pierwszej opcji, upewnij się, że zwolniłeś MediaRecorder przed inicjalizacją MediaPlayer. Jeśli nadal zwraca 0, prawdopodobnie wystąpi błąd. Chciałbym wypróbować różne formaty audio. – Erol

+0

To rozwiązanie działa na niektórych urządzeniach, ale nie na innych. Każdy pomysł, dlaczego? Działa na nexus5, ale nie na hudl. Może to obsługiwane typy mediów? Plik, który próbuję odczytać, to h264 mp4. – speedynomads

1

Czy spojrzał na Ringdroid?. Jest dość lekki, a integracja jest prosta. Działa również z plikami multimedialnymi VBR.

Dla twojego problemu z uzyskaniem czasu, możesz zrobić coś jak poniżej za pomocą Ringdroid.

public class AudioUtils 
{ 
    public static long getDuration(CheapSoundFile cheapSoundFile) 
    { 
     if(cheapSoundFile == null) 
      return -1; 
     int sampleRate = cheapSoundFile.getSampleRate(); 
     int samplesPerFrame = cheapSoundFile.getSamplesPerFrame(); 
     int frames = cheapSoundFile.getNumFrames(); 
     cheapSoundFile = null; 
     return 1000 * (frames * samplesPerFrame)/sampleRate; 
    } 

    public static long getDuration(String mediaPath) 
    { 
     if(mediaPath != null && mediaPath.length() > 0) 
      try 
      { 
       return getDuration(CheapSoundFile.create(mediaPath, null)); 
      }catch (FileNotFoundException e){} 
      catch (IOException e){} 
     return -1; 
    } 
} 

nadzieję, że pomoże

39

MediaMetadataRetriever jest lekki i wydajny sposób to zrobić. MediaPlayer jest zbyt ciężki i może pojawić się problem z wydajnością w środowisku o wysokiej wydajności jak przewijanie, Pager notowań itp

Ponadto Error (100,0) może się zdarzyć na MediaPlayer ponieważ jest to ciężka i czasami ponowne uruchomienie musi być wykonane ponownie i ponownie.

Uri uri = Uri.parse(pathStr); 
MediaMetadataRetriever mmr = new MediaMetadataRetriever(); 
mmr.setDataSource(AppContext.getAppContext(),uri); 
String durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); 
int millSecond = Integer.parseInt(durationStr); 
+0

To było miłe, ponieważ wydaje się, że istnieje błąd w MediaPlayer.getDuration() - przynajmniej dla MP4. Dzięki! –

+0

Jak uzyskać MediaMetadataCompat.METADATA_KEY_DURATION? –

3

Najszybszym sposobem jest przejście przez MediaMetadataRetriever. Jednakże, istnieje haczyk

jeśli używasz URI i kontekst ustawić źródło danych może wystąpić bug https://code.google.com/p/android/issues/detail?id=35794

Rozwiązanie jest używać bezwzględną ścieżkę pliku do pobierania metadanych pliku multimedialnego.

Poniżej znajduje się fragment kodu, aby zrobić tak

private static String getDuration(File file) { 
       MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever(); 
       mediaMetadataRetriever.setDataSource(file.getAbsolutePath()); 
       String durationStr = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); 
       return Utils.formateMilliSeccond(Long.parseLong(durationStr)); 
      } 

Teraz można przekonwertować milisekundę do czytelnej formie za pomocą jednej z poniższych formatów

 /** 
     * Function to convert milliseconds time to 
     * Timer Format 
     * Hours:Minutes:Seconds 
     */ 
     public static String formateMilliSeccond(long milliseconds) { 
      String finalTimerString = ""; 
      String secondsString = ""; 

      // Convert total duration into time 
      int hours = (int) (milliseconds/(1000 * 60 * 60)); 
      int minutes = (int) (milliseconds % (1000 * 60 * 60))/(1000 * 60); 
      int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60)/1000); 

      // Add hours if there 
      if (hours > 0) { 
       finalTimerString = hours + ":"; 
      } 

      // Prepending 0 to seconds if it is one digit 
      if (seconds < 10) { 
       secondsString = "0" + seconds; 
      } else { 
       secondsString = "" + seconds; 
      } 

      finalTimerString = finalTimerString + minutes + ":" + secondsString; 

    //  return String.format("%02d Min, %02d Sec", 
    //    TimeUnit.MILLISECONDS.toMinutes(milliseconds), 
    //    TimeUnit.MILLISECONDS.toSeconds(milliseconds) - 
    //      TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliseconds))); 

      // return timer string 
      return finalTimerString; 
     }