【问题标题】:ProcessBuilder handling process outputProcessBuilder 处理流程输出
【发布时间】:2019-09-18 13:45:18
【问题描述】:

我想从我的代码中启动一个 ffmpeg 进程,然后处理结果输出。 ffmpeg 进程将打印出进度信息,我想将该信息发送回另一个应用程序。

我正在尝试使用 ProcessBuilder API 来实现这一点。基于这个答案ProcessBuilder: Forwarding stdout and stderr of started processes without blocking the main thread我尝试了以下代码

@Service
class ProcessExecutorService(@Autowired private val configProps: AppConfigurationProperties) {

    private val logger: Logger = Logger.getLogger(ProcessExecutorService::class.qualifiedName)

    fun execute(command: List<String>): Int {
        logger.info("Executing command $command")

        val processBuilder = ProcessBuilder()
        processBuilder.command(command)
        processBuilder.directory(File(configProps.encoding.workDirectory))

        val process = processBuilder.start()
        Thread(StreamGobbler(process.inputStream, logger::info)).start()

        return process.waitFor()
    }

    inner class StreamGobbler(private val inputStream: InputStream, private val consumer: (String) -> Unit): Runnable {

        override fun run() {
            BufferedReader(InputStreamReader(inputStream) as Reader)
                    .lines()
                    .forEach(consumer)
        }

    }
}

但这不会记录任何输出。当我把它改成做

@Service
class ProcessExecutorService(@Autowired private val configProps: AppConfigurationProperties) {

    private val logger: Logger = Logger.getLogger(ProcessExecutorService::class.qualifiedName)

    fun execute(command: List<String>): Int {
        logger.info("Executing command $command")

        val processBuilder = ProcessBuilder()
        processBuilder.command(command)
        processBuilder.directory(File(configProps.encoding.workDirectory))
        processBuilder.inheritIO()

        val process = processBuilder.start()

        return process.waitFor()
    }
}

然后我看到了 ffmpeg 输出,但我无法对这个输出做任何有用的事情。

关于为什么第一种方法可能不起作用的任何建议?

【问题讨论】:

  • 是 Kotlin,不是吗?
  • 在第一种情况下,BufferedReader 是否正确关闭? (如果没有,它可能有未刷新的数据,这可以解释为什么你没有看到它。)我会尝试使用 Kotlin 扩展 forEachLine()useLines() 而不是 Java 流 useLines(),因为它们应该会自动关闭信息流。
  • 我尝试了这个建议,但我仍然没有看到输出。

标签: spring kotlin processbuilder


【解决方案1】:

如果您只运行“ffmpeg”,进程对象将写入错误流,因此您还需要记录该流。例如,“ffmpeg -version”不会以错误状态返回,因此它应该被您的 StreamGobbler 类捕获。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-19
    • 2011-10-28
    • 1970-01-01
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    相关资源
    最近更新 更多