3

我正在使用 Java 中的 ProcessBuilder 运行 SoX,它将 WAV 文件修剪为 30 秒长的 WAV 文件。

SoX 正在运行,因为我可以成功修剪文件的前 30 秒并保存为新文件,但它停在那里,但它仍在运行。

这是命令生成的代码:

command.add (soxCommand);
    if (SoxWrapper.getMetadata (srcFile, MetadataField.SAMPLE_RATE) != 16000) {
        command.add ("-V3");
        command.add ("-G");
        command.add (FilenameUtils.normalize (srcFile.getAbsolutePath ()));
        command.add ("-b 16");
        command.add (FilenameUtils.normalize (destFile.getAbsolutePath ()));
        command.add ("channels");
        command.add ("1");
        command.add ("rate");
        command.add ("16000");
        command.add ("trim");
        command.add (startTime.toString ());
        command.add ('=' + endTime.toString ());
    } else {
        command.add ("-V3");
        command.add (FilenameUtils.normalize (srcFile.getAbsolutePath ()));
        command.add ("-b 16");
        command.add (FilenameUtils.normalize (destFile.getAbsolutePath ()));
        command.add ("trim");
        command.add (startTime.toString ());
        command.add ('=' + endTime.toString ());
    }

这是进程创建的代码:

    private static Process createProcess (List<String> command) {

    ProcessBuilder soxProcessBuilder = new ProcessBuilder (command);
    soxProcessBuilder.redirectErrorStream (true);

    Process soxProcess = null;
    try {
        soxProcess = soxProcessBuilder.start ();

        int soxreturn = soxProcess.waitFor ();
        soxLogger.info ("SoX returned: " + soxreturn);

    } catch (IOException t) {
        logger.error ("SoX Process failed", t);
    } catch (InterruptedException e) {
        logger.error ("Failed to wait for SoX to finish", e);
    }

    return soxProcess;
}
4

1 回答 1

3

它被阻塞是因为它正在向标准输出写入内容,缓冲区已填满,因此进程正在等待缓冲区为其腾出空间,但您的程序没有读取它,因此缓冲区保持满状态。由于您将 stderr 重定向到 stdout,因此可能会出现某种错误并且您不知道它,因为您没有从流中读取。您需要从进程中读取getInputStream,例如:

new Thread(new Runnable() {
    @Override public void run() {
        try {
            org.apache.commons.io.IOUtils.copy(soxProcess.getInputStream(), System.out);
        } catch (IOException e) {
            e.printStackTrace(System.err);
        }
    }    
}).start();

(这里您需要将 soxProcess 设为 final,以便内部类方法可以看到它。)

或者,使用新的 JDK,您现在可以选择让 processBuilder 将输出重定向到文件

于 2011-08-11T13:38:16.517 回答