Прежде всего, небольшая мелочь с вашим кодом ... когда вы создаете FileOutputStream
, вы создаете его, используя строку, а не File
, когда вы уже создали File
ранее, так что вы можете а также переработайте это вместо того, чтобы заставлять FileOutputStream
создавать экземпляр самого File
.
Другим небольшим придиркой является тот факт, что при записи аудиофайла вы должны заключить его в блок try
и закрыть выходной поток в блок finally
. Если вам разрешено добавлять новую библиотеку в ваш проект, вы можете использовать Guava , у которого есть метод Files.write(byte[],File)
, который позаботится обо всем грязном управлении ресурсами для вас.
Единственное, что я вижу, что похоже на определенную ошибку - это то, что вы игнорируете поток ошибок ffmpeg. Если вы блокируете ожидание ввода на стандартный вывод ffmpeg, то он не будет работать.
Самый простой способ устранить эту ошибку - использовать 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();
, чтобы убедиться, что оно успешно завершено.
Еще одна вещь, которую вы, возможно, захотите сделать, когда она будет завершена, запишите, что она выводит в файл журнала, чтобы у вас была запись о том, что произошло, на случай, если что-то случится.