scala - PipedInputStream/PipedOutputStream、ImageIO 和 ffmpeg

标签 scala amazon-ec2 ffmpeg pipe javax.imageio

我在 Scala 中有以下代码:

      val pos = new PipedOutputStream()
      val pis = new PipedInputStream(pos)

      Future {
        LOG.trace("Start rendering")
        generateFrames(videoRenderParams.length) {
          img ⇒ ImageIO.write(img, "PNG", pos)
        }
        pos.flush()
        IOUtils.closeQuietly(pos)
        LOG.trace("Finished rendering")
      } onComplete {
        case Success(_) ⇒ 
          LOG.trace("Complete successfully")
        case Failure(err) ⇒
          LOG.error("Can't render stuff", err)
          IOUtils.closeQuietly(pis)
          IOUtils.closeQuietly(pos)
      }

      val prc = (ffmpegCli #< pis).!(logger)

Future 只是将生成的图像一张一张地写入OutputStream。现在,ffmpeg 进程从 stdin 读取输入图像并将它们转换为 MP4 文件。

效果很好,但出于某种原因,有时我会得到以下堆栈跟踪:

I/O error Pipe closed for process: <input stream>
java.io.IOException: Pipe closed
    at java.io.PipedInputStream.checkStateForReceive(PipedInputStream.java:260)
    at java.io.PipedInputStream.receive(PipedInputStream.java:226)
    at java.io.PipedOutputStream.write(PipedOutputStream.java:149)
    at scala.sys.process.BasicIO$.loop$1(BasicIO.scala:236)
    at scala.sys.process.BasicIO$.transferFullyImpl(BasicIO.scala:242)
    at scala.sys.process.BasicIO$.transferFully(BasicIO.scala:223)
    at scala.sys.process.ProcessImpl$PipeThread.runloop(ProcessImpl.scala:159)
    at scala.sys.process.ProcessImpl$PipeSource.run(ProcessImpl.scala:179)

同时我从另一个流中收到以下错误:

javax.imageio.IIOException: I/O error writing PNG file!
    at com.sun.imageio.plugins.png.PNGImageWriter.write(PNGImageWriter.java:1168)
    at javax.imageio.ImageWriter.write(ImageWriter.java:615)
    at javax.imageio.ImageIO.doWrite(ImageIO.java:1612)
    at javax.imageio.ImageIO.write(ImageIO.java:1578)
    at 

所以似乎流在两者之间的某个地方中断了,所以 ffmpeg 无法读取数据,ImageIO 也无法写入数据。

更有趣的是 - 该问题只能在某些 Linux 服务器(亚马逊)上重现。它在其他 Linux 机器上完美运行。所以我想知道是否有人可以指出导致此错误的可能原因。

到目前为止我尝试了什么:

  • 使用 Oracle JDK 8 和 OpenJDK
  • 使用不同版本的FFMPEG

目前没有任何效果。

最佳答案

这个问题既可以预见又很奇怪。因此,安排了十个并发的 ffmpeg 进程来处理输入,而输入是一组数百张 FullHD 图片。显然这需要大量的计算能力,因此内核随机关闭 ffmpeg 进程,导致 Java 包装器同时报告损坏的输入和输出管道。

因此 /var/log/messages 包含许多如下日志:

Out of memory: Kill process 25778 (java) score 159 or sacrifice child
Killed process 25931 (ffmpeg) total-vm:2337040kB, anon-rss:966340kB, file-rss:104kB

减少并发 ffmpeg 进程的数量解决了这个问题。

关于scala - PipedInputStream/PipedOutputStream、ImageIO 和 ffmpeg,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29712315/

相关文章:

json - 使用 Circe 光学器件修改对象的所有字段或数组的所有项目

amazon-web-services - 将 ENI 主干附加到 cloudform 中的自定义安全组

amazon-web-services - 如何避免 S3 和 EC2 之间跨账户的数据传输成本?

node.js - fluent-ffmpeg display_aspect_ratio 没有改变

bash - 如何使用 FFMPEG 将输出和日志文件通过管道传输到 S3

scala - 是否有可以与组合器组合的最大数量的验证?

scala - Firebase 和 Play Framework (Scala) 有可能吗?

scala - 在Scala中, `println(1,2)`如何运作?

python - 在aws ec2上部署python代码有哪些方法?

streaming - “Hook” libMMS 到 FFmpeg 用于 iPhone 流媒体