2012-09-11 60 views
2

有人可以與我分享一個可靠的方式來記錄使用MediaRecorder的所有設備的音頻?我只是試圖記錄一個低比特率的AMR格式音頻文件,根據谷歌是所有設備的標準。這是一堆廢話。Android:可靠的音頻錄製,所有設備

根據我的經驗,有許多非品牌設備,平板電腦等在使用默認AudioEncoder.AMR_NB時會發生可怕的失敗。我的解決方法是使用反射來輪詢超類中的編碼器,然後使用errorlistener循環每個編碼器以查看哪個不會失敗。這不僅不夠優雅,而且不能捕捉所有設備。我也嘗試將AudioEncoder和OutputFormat選項(常量0)設置爲默認值,並且在某些設備上也會出現可怕的錯誤。

這裏是我使用什麼,如果默認AMR編碼器不工作:

Class encoderClass = MediaRecorder.AudioEncoder.class; 
Field[] encoders = encoderClass.getFields(); 

然後我遍歷每個編碼器,設置一個錯誤監聽。如果它成功結束,我將它設置爲默認編碼器。

for (int i = j; i < encoders.length; i++) { 

try { 
    int enc = encoders[i].getInt(null); 
    recorder.reset(); 
    recorder.setAudioSource(AudioSource.MIC); 
    recorder.setOutputFormat(OutputFormat.THREE_GPP); 
    recorder.setAudioEncoder(enc); //testing the encoder const here 
    recorder.setOutputFile(amrPath); 
    recorder.setMaxDuration(3000); 
    recorder.setOnInfoListener(new OnInfoListener() { 

我繼續循環,如果監聽器捕獲了一個錯誤:

if (arg1 == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) { 

這種技術適用於大多數設備。其餘的呢? 我仍然有裝置,通過裂縫下降,坦率地說,我想 幾乎所有設備的東西可靠?

+0

你爲什麼不試試[this](http://www.benmccann.com/dev-blog/android-audio-recording-tutorial/)? – Praveenkumar

+0

@SpK:感謝您的鏈接,但他的代碼遵循設置AMR_NB的正常路徑,就像我說的在許多設備上失敗一樣。 – ThumbsDP

回答

2

那麼,因爲沒有人想發佈一個解決方案,這裏是我現在使用的,這是有效的,但有點混亂。我從一個setupAudio()方法開始,它嘗試三種常見的音頻編碼器和容器設置。這將適用於大多數設備。如果它不起作用,它默認使用一個附加方法setupAltAudio(),該方法在設備列出的編碼器值中循環並嘗試每一個。我確定有人會發出聲音說「爲什麼不使用OnErrorListener()」?這對許多設備不起作用,因爲它們會拋出奇怪的非致命錯誤,如果我對此作出響應,我可能會停止有效的錄製設置。

設置MediaRecorder時通常是不可恢復的錯誤,所以我messily抓住setAudioEncoder()和prepare()和start()方法。如果它在這裏引發異常,我沒有有效的音頻記錄設置。我還沒有清理過這個代碼,它有一些可以改進的元素。一旦音頻編碼器成功,我將編碼器和容器值保存到設置並重新運行setupAudio()方法。這次會發生什麼,抓住這些設置並直接進入startRecording()。所以總的來說,我首先嚐試了最常見的MediaRecorder設置,然後我使用反射來循環遍歷每個編碼器,作爲試錯法。 編輯: setupAltAudio缺少一個細節。主循環需要初始化(i)到設置中的audioLoop值。這會跟蹤最後一次測試的編碼器。

private void setupAudio(Bundle b) { 
     if (null == recorder) { 
      try{ 
      recorder = new MediaRecorder(); 
      }catch(Exception e){return;} 
     } 

     if (settings.getInt("audioEncoder", -1) > -1) { 
      if(null==b){ 
       seconds = 60; 
      }else{ 
      seconds = b.getInt("seconds"); 
      } 
      startRecording(); 
      return; 
     }  


     int audioLoop = 0; 
     int enc=0; 
     int out=0; 

     if(settings.getInt("audioLoop", 0)>0){ 
      audioLoop = settings.getInt("audioLoop",0); 
     } 

     /** 
     * @Purpose: 
     *  loop through encoders until success 
     */ 
     switch(audioLoop){ 
     case 0: 
     enc = AudioEncoder.AMR_NB; 
     out = OutputFormat.THREE_GPP; 
     break; 
     case 1: 
     enc = AudioEncoder.AMR_NB; 
     out = OutputFormat.DEFAULT; 
     break; 
     case 2: 
     enc = AudioEncoder.DEFAULT; 
     out = OutputFormat.DEFAULT; 
     break; 
     case 3: 
      setupAltAudio(seconds); 
      return; 
     } 

     String amrPath = Environment.getExternalStorageDirectory() 
        .getAbsolutePath() + "/data/temp"; 
     if(!new File(amrPath).exists()){ 
      new File(amrPath).mkdirs(); 
     } 
     amrPath += "/test.3gp"; 
     try{  
     recorder.reset(); 
     recorder.setAudioSource(AudioSource.MIC); 
     recorder.setOutputFormat(out); 
     recorder.setAudioEncoder(enc); 
     recorder.setOutputFile(amrPath); 
     recorder.setMaxDuration(5000); 
     recorder.prepare(); 
     recorder.start(); 
     SharedPreferences.Editor editor = settings.edit(); 
     editor.putInt("audioEncoder", enc); 
     editor.putInt("audioContainer", out); 
     editor.commit(); 
     setupAudio(b); 
     return; 
     }catch(Exception e){ 
      e.printStackTrace(); 
      int count = settings.getInt("audioLoop", 0); 
      count++; 
      SharedPreferences.Editor editor = settings.edit(); 
      editor.putInt("audioLoop", count); 
      editor.commit(); 
      setupAudio(b); 
      return; 
     } 


    } 

    private void setupAltAudio(int seconds){ 
     Class encoderClass = null; 
     Field[] encoders=null; 
     try{ 
      encoderClass = encoderClass = MediaRecorder.AudioEncoder.class; 
      encoders = encoderClass.getFields();    
     }catch(Exception e){} 

     File tempDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data/tmp"); 
     if(!tempDir.exists()){ 
      tempDir.mkdirs(); 
     } 

     int enc = 0; 
     int container = 0; 

     for(int i = 0; i < encoders.length; i++){ 

      try{ 
       enc = encoders[i].getInt(null); 
      }catch(Exception e){ 
       continue; 
      } 
      recorder.reset(); 
      recorder.setAudioSource(AudioSource.MIC); 
      try{ 
      recorder.setOutputFormat(OutputFormat.THREE_GPP); 
      container = OutputFormat.THREE_GPP; 
      }catch(Exception e){ 
       recorder.setOutputFormat(OutputFormat.DEFAULT); 
       container = OutputFormat.DEFAULT; 
      } 
      recorder.setAudioEncoder(enc); 
      recorder.setOutputFile(amrPath); 
      recorder.setMaxDuration(seconds*1000); 
      recorder.setOnInfoListener(new OnInfoListener() { 

       public void onInfo(MediaRecorder arg0, int arg1, int arg2) { 
        if (arg1 == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { 
         try{ 
          recorder.release(); 
         }catch(Exception e){} 

         if(saveAudio)){ 
          File cache = new File(amrPath); 
          try{ 
          cache.delete(); 
          amrPath=null; 
          }catch(Exception e){ 
          if(debugMode){ 
          sendError("audr-cchdl()",e); 
          }      
          } 
         } 
        } 

       }}); 
      try{ 
      recorder.prepare(); 
      recorder.start(); 
      SharedPreferences.Editor editor = settings.edit(); 
      editor.putInt("audioEncoder", enc); 
      editor.putInt("audioContainer", container); 
      editor.commit(); 
      }catch(Exception e){ 
       recorder.release(); 
       continue; 
      } 

     } 
    } 
    private void startRecording() { 
     if (!storageAvailable()) { 
      stopMe(); 
      return; 
     } 


     try { 
      int audioEncoder = settings.getInt("audioEncoder", 1); 
      int audioContainer = settings.getInt("audioContainer",1); 
      String stamp = String.valueOf(System.currentTimeMillis()); 
      String filePath = Environment.getExternalStorageDirectory() 
        .getAbsolutePath() + "/data/temp/"; 
      File fileDir = new File(filePath); 
      if (!fileDir.exists()) { 
       fileDir.mkdirs(); 
      } 

      amrPath = filePath + stamp + ".3gp"; 
      recorder = new MediaRecorder(); 
      recorder.reset(); 
      recorder.setAudioSource(AudioSource.MIC); 
      recorder.setOutputFormat(audioContainer); 
      recorder.setAudioEncoder(audioEncoder); 
      recorder.setOutputFile(amrPath); 
      recorder.setMaxDuration(seconds * 1000); 

      recorder.setOnInfoListener(new OnInfoListener() { 

       public void onInfo(MediaRecorder arg0, int arg1, int arg2) { 
        if (arg1 == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { 

         try { 
          recorder.stop(); 

         } catch (Exception e) { 
          if (debugMode) { 
           sendError("audr-oninf()", e); 
          } 
         } 
         try { 
          recorder.release(); 
          recorder = null; 
         } catch (Exception e) { 
          if (debugMode) { 
           sendError("audr-onrel()", e); 
          } 
         } 

         if(saveAudio()){ 
         File cache = new File(amrPath); 
         try{ 
         cache.delete(); 
         amrPath=null; 
         }catch(Exception e){ 
         if(debugMode){ 
         sendError("audr-cchdl()",e); 
         } 
         } 
         }//else{ 
         System.out.println("AudioService:Network:SendRecording:Fail"); 
         // } 
         stopMe(); 
        } 
        if (arg1 == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) { // TODO: 
                       // this 
                       // may 
                       // cause 
                       // more 
                       // problems 
         try { 

          recorder.stop(); 

         } catch (Exception e) { 
          if (debugMode) { 
           sendError("audr-recdst()", e); 
          } 
         } 
         try { 
          recorder.release(); 
          recorder = null; 
          if(new File(amrPath).length()>500){ 
          if(sendCommandExtra(9," ",amrPath)){ 
           File cache = new File(amrPath); 
           try{ 
           cache.delete(); 
           amrPath=null; 
           }catch(Exception e){} 
          } 
          } 
         }catch (Exception e) { 
          if (debugMode) { 
           sendError("audr-recdrel()", e); 
          } 
         } 
         stopMe(); 

        } 
       } 
      }); 


      try { 
       recorder.prepare(); 
       recorder.start(); 
      } catch (Exception e) { 
       if (debugMode) { 
        sendError("audr-prpst()", e); 
       } 
       recorder.release(); 
       recorder = null; 
       stopMe(); 
      } 



     } catch (Exception z) { 

      sendError("audr-outrtry()", z); 
     } 

    }// end startRecording();