2011-02-17 65 views
0

我在Java Web服務下面的代碼:FFMPEG在Java中的問題

public boolean makeFile(String fileName, String audio) 
    { 
     if (makeUserFolder()) 
     { 
      File file = new File(getUserFolderPath() + fileName + amr); 
      FileOutputStream fileOutputStream = null; 
      try 
      { 

       file.createNewFile(); 
       fileOutputStream = new FileOutputStream(file); 
       fileOutputStream.write(Base64.decode(audio)); 

       return true; 

      } 
      catch(FileNotFoundException ex) 
      { 
       return false; 
      } 
      catch(IOException ex) 
      { 
       return false; 
      } 
      finally{ 
       try { 
        fileOutputStream.close(); 
        convertFile(fileName); 
       } catch (IOException ex) { 
        Logger.getLogger(FileUtils.class.getName()).log(Level.SEVERE, null, ex); 
      } 
} 

     } 
     else 
      return false; 

    } 

    public boolean convertFile(String fileName) 
    { 
     Process ffmpeg; 
     String filePath = this.userFolderPath + fileName; 
     try { 
      ProcessBuilder pb = new ProcessBuilder("ffmpeg","-i",filePath + amr,filePath + mp3); 
      pb.redirectErrorStream(); 
      ffmpeg = pb.start(); 
     } catch (IOException ex) { 
      return false; 
     } 
     return true; 
    } 

它用來工作,現在它根本不會執行出於某種原因ffmpeg的轉換。我認爲這是我的文件的問題,但從終端運行命令後沒有錯誤拋出或任何東西,認爲這可能是權限問題,但所有的權限已被授予我保存文件的文件夾。我注意到輸入的BufferedReader在運行這個過程後被設置爲null,任何想法發生了什麼?

回答

4

首先,小挑剔你的代碼...當你創建FileOutputStream創建它使用一個字符串,而不是一個File,當你已經創建前File,所以你還不如回收,與其比強制FileOutputStream實例化File本身。

另一個小挑剔是,當你寫出音頻文件時,你應該把它包含在try塊中,並在finally塊中關閉輸出流。如果允許您將新庫添加到項目中,則可以使用Guava,該方法的方法爲Files.write(byte[],File),該方法將爲您處理所有髒資源管理。

我可以看到,看起來像一個確定的錯誤的唯一的事實是,你忽略了ffmpeg的錯誤流。如果您阻止在ffmpeg的stdout上等待輸入,那麼它將不起作用。

處理此錯誤的最簡單方法是使用ProcessBuilder而不是Runtime

ProcessBuilder pb = new ProcessBuilder("ffmpeg","-i",filePath+amr,filePath+mp3); 
pb.redirectErrorStream(); // This will make both stdout and stderr be redirected to process.getInputStream(); 
ffmpeg = pb.start(); 

如果以這種方式啓動它,那麼您當前的代碼將能夠完全讀取兩個輸入流。由於沒有閱讀,stderr可能隱藏了一些你無法看到的錯誤。

如果這不是你的問題,我會建議使用與ffmpeg的絕對路徑...換句話說:

String lastdot = file.getName().lastIndexOf('.'); 
File mp3file = new File(file.getParentFile(),file.getName().substring(0,lastdot)+".mp3"); 
ProcessBuilder pb = new ProcessBuilder("ffmpeg","-i",file.getAbsolutePath(),mp3file.getAbsolutePath()); 
// ... 

如果不行,我會改變的ffmpeg是絕對路徑好(爲了排除路徑問題)。

編輯:進一步的建議。

我會親自將寫代碼重構爲自己的方法,以便您可以在其他地方使用它。在其他換句話說:

public static boolean write(byte[] content, File to) { 
    FileOutputStream fos = new FileOutputStream(to); 
    try { 
     fos.write(content); 
    } catch (IOException io) { 
     // logging code here 
     return false; 
    } finally { 
     closeQuietly(fos); 
    } 
    return true; 
} 
public static void closeQuietly(Closeable toClose) { 
    if (toClose == null) { return; } 
    try { 
     toClose.close(); 
    } catch (IOException e) { 
     // logging code here 
    } 
} 

,我所做的closeQuietly(Closeable)方法的原因是由於這樣的事實:如果不以這種方式關閉它,有可能是一個例外將由close()方法拋出,並且該例外將會掩蓋原來拋出的異常。如果你把它們放在一個實用程序類中(儘管查看你的代碼,我假設它當前所在的類名爲FileUtils),那麼無論何時需要處理文件輸出,你都可以在整個應用程序中使用它們。

這將允許你重寫塊爲:

File file = new File(getUserFolderPath() + fileName + amr); 
file.createNewFile() 
write(Base64.decode(audio),file); 
convertFile(fileName); 

我不知道你是否應該這樣做,但是如果你想要的ffmpeg的過程已完成可以肯定的,那麼你應該說ffmpeg.waitFor();以確保它已完成。如果你這樣做,那麼你應該檢查ffmpeg.exitValue();以確保它成功完成。

您可能想要做的另一件事是一旦完成,將其輸出寫入日誌文件,以便記錄發生的情況,以防萬一發生。

+0

謝謝,目前我回家了,所以我明天就得測試這個代碼。事情是你上面看到的代碼上週工作,今天當我去做另一個測試,因爲我做了一些改變(不是在這部分代碼)它失敗了,不會轉換音頻文件,認爲這是一個權限問題,但從終端執行命令工作。我會告訴你結果 – 8vius 2011-02-18 02:00:59