![](/img/trans.png)
[英]issue starting ffmpeg screen capture on OSX (AVFoundation) from Java
[英]FFMPEG in Java issue
我在Java Web服务中有以下代码:
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 ins设置为null,知道发生了什么吗?
首先,用代码编写一个小的nitpick ...当您创建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();
确保它成功完成。
您可能想要做的另一件事是,一旦完成,将其输出内容写入日志文件,以便您记录发生的情况,以防万一。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.