2013-03-13 55 views
11

Tôi đã tạo một ứng dụng ghi âm giọng nói và tôi muốn hiển thị thời lượng của bản ghi trong một listview. Tôi lưu các bản ghi như thế này:lấy thời lượng của tệp âm thanh

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(); 
    } 

Làm cách nào để có được thời lượng trong tệp này?

Cảm ơn trước

--- EDIT tôi nhận nó làm việc, tôi gọi MediaPlayer.getduration() bên trong MediaPlayer.setOnPreparedListener() phương pháp để nó trở 0.

Trả lời

0

Sau khi bạn ghi các file , mở nó trong MediaPlayer và gọi getDuration trên đó.

+0

Cố gắng đó, nhưng nó luôn luôn trả về 0 đối với một số lý do – Simon

+1

Đừng bận tâm tôi làm việc đó! Tôi gọi là MediaPlayer.getDuration() trong phương thức MediaPlayer.setOnPreparedListener và trả về 0 – Simon

10

sử dụng Thử

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

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

Division trên 1000 chuyển sang giây.

Hy vọng điều này sẽ giúp bạn.

+1

MediaPlayer.getduration() trả về 0 vì một lý do lạ nào đó mà bạn biết tại sao? – Simon

19

Hoặc thử này để có được thời gian trong mili giây:

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

Hoặc đo thời gian trôi qua từ recorder.start() đến recorder.stop() trong nano giây:

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

đầu tiên trả về 0 và nếu tôi muốn sử dụng giải pháp thứ hai, tôi phải phát tệp và tôi không muốn rằng – Simon

+0

Bạn không phải phát tệp cho tệp thứ hai. Bạn đặt thời gian bắt đầu khi người dùng bắt đầu ghi và tính toán thời gian ước tính khi người dùng ngừng ghi. Đối với tùy chọn đầu tiên, hãy đảm bảo bạn phát hành MediaRecorder trước khi khởi tạo MediaPlayer. Nếu nó vẫn trở về 0, có khả năng là một lỗi. Tôi sẽ thử các định dạng âm thanh khác nhau. – Erol

+0

Giải pháp này hoạt động trên một số thiết bị nhưng không hoạt động trên các thiết bị khác. Bất kỳ ý tưởng tại sao? Hoạt động trên nexus5 nhưng không phải là hudl. Có thể nó được hỗ trợ các loại phương tiện truyền thông? Các tập tin tôi đang cố gắng để đọc là một h264 mp4. – speedynomads

1

Bạn đã nhìn Ringdroid?. Đó là trọng lượng khá nhẹ và tích hợp là thẳng về phía trước. Nó hoạt động tốt với các tập tin media VBR.

Đối với vấn đề của bạn với thời gian, bạn có thể muốn làm một cái gì đó như dưới đây bằng cách sử dụng 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; 
    } 
} 

Hy vọng rằng sẽ giúp

39

MediaMetadataRetriever là một cách nhẹ và hiệu quả để làm điều này. MediaPlayer quá nặng và có thể phát sinh vấn đề hiệu suất trong môi trường hiệu suất cao như cuộn, phân trang, liệt kê, v.v.

Hơn nữa, Error (100,0) có thể xảy ra trên MediaPlayer vì nó nặng và đôi khi khởi động lại cần được thực hiện lặp đi lặp lại.

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

Điều này là tốt đẹp để tìm thấy vì có vẻ là một lỗi trong MediaPlayer.getDuration() - ít nhất là cho mp4. Cảm ơn! –

+0

Làm cách nào để tải MediaMetadataCompat.METADATA_KEY_DURATION? –

3

Cách nhanh nhất để thực hiện là qua MediaMetadataRetriever. Tuy nhiên, có một nhược điểm

nếu bạn sử dụng URI và bối cảnh để thiết lập nguồn dữ liệu bạn có thể gặp lỗi https://code.google.com/p/android/issues/detail?id=35794

Giải pháp được sử dụng đường dẫn tuyệt đối của file để lấy siêu dữ liệu của tập tin phương tiện truyền thông.

Dưới đây là đoạn mã để làm như vậy

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)); 
      } 

Bây giờ bạn có thể chuyển đổi một phần nghìn giây sang định dạng có thể đọc được con người sử dụng một trong các định dạng dưới đây

 /** 
     * 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; 
     }