当前位置: 首页 > 面试题库 >

从Apache Commons-Exec捕获大量输出

翟棋
2023-03-14
问题内容

我正在通过执行Java ffmpeg并将其输出捕获到标准输出来用Java编写视频应用程序。我决定使用Apache Commons-
Exec而不是Java的Java Runtime,因为它看起来更好。但是,我很难捕获所有输出。

我认为使用管道将是可行的方法,因为它是html" target="_blank">进程间通信的标准方法。但是,我的设置使用PipedInputStreamPipedOutputStream是错误的。它似乎有效,但仅适用于流的前1042个字节,奇怪的是恰好是的值PipedInputStream.PIPE_SIZE

我不喜欢使用管道,但是我想避免使用磁盘I / O(如果可能),因为数据的速度和数据量(512x384分辨率的1m 20s视频可产生690
M的管道数据)。

您是否想到了处理管道中大量数据的最佳解决方案?我的两个班级的代码如下。(是的,sleep是不好的。对思想?
wait()notifyAll()?)

WriteFrames.java

public class WriteFrames {
    public static void main(String[] args) {
        String commandName = "ffmpeg";
        CommandLine commandLine = new CommandLine(commandName);
        File filename = new File(args[0]);
        String[] options = new String[] { 
                "-i",
                filename.getAbsolutePath(),
                "-an",
                "-f",
                "yuv4mpegpipe",
                "-"};

        for (String s : options) {
            commandLine.addArgument(s);
        }



        PipedOutputStream output = new PipedOutputStream();
        PumpStreamHandler streamHandler = new PumpStreamHandler(output, System.err);
        DefaultExecutor executor = new DefaultExecutor();

        try {
            DataInputStream is = new DataInputStream(new PipedInputStream(output));
            YUV4MPEGPipeParser p = new YUV4MPEGPipeParser(is);
            p.start();

            executor.setStreamHandler(streamHandler);
            executor.execute(commandLine);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

YUV4MPEGPipeParser.java

public class YUV4MPEGPipeParser extends Thread {

    private InputStream is;
    int width, height;

    public YUV4MPEGPipeParser(InputStream is) {
        this.is = is;
    }

    public void run() {
        try {
            while (is.available() == 0) {
                Thread.sleep(100);
            }

            while (is.available() != 0) {
                // do stuff.... like write out YUV frames
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

问题答案:

问题出在YUV4MPEGPipeParser类的run方法中。有两个连续的循环。如果流上当前没有可用数据,则第二个循环立即终止(例如,到目前为止,所有输入均已由解析器处理,并且ffmpeg或流泵的速度不足以为其提供一些新数据->
available()== 0 ->循环终止->泵螺纹结束)。

只需摆脱这两个循环并进入睡眠状态,然后执行一个简单的阻塞read()即可,而不是检查是否有任何数据可用于处理。因为解析器代码是在单独的线程上启动的,所以可能也不需要wait()/
notify()甚至sleep()。

您可以像这样重写run()方法的代码:

public class YUV4MPEGPipeParser extends Thread {

    ...

    // optimal size of buffer for reading from pipe stream :-)
    private static final int BUFSIZE = PipedInputStream.PIPE_SIZE;

    public void run() {
        try {
            byte buffer[] = new byte[BUFSIZE];
            int len = 0;
            while ((len = is.read(buffer, 0, BUFSIZE) != -1) {
                // we have valid data available 
                // in first 'len' bytes of 'buffer' array.

                // do stuff.... like write out YUV frames
            }
         } catch ...
     }
 }


 类似资料:
  • 除非你开发的是非常简单的控制台应用, 否则你应该不希望php脚本代码产生的输出 直接被扔到激活的终端上. 捕获这些输出和你刚才用以覆写启动处理器的方法类似. 在sapi_module_struct中还有⼀些有用的回调: typedef struct _sapi_module_struct { ... int (*ub_write)(const char *str, unsigned

  • 问题内容: 我正在生成大量的XML,当用户单击表单按钮时,这些XML将作为发布变量传递到API。我还希望能够事先向用户显示XML。 该代码有点像以下结构: 我的XML正在生成一些while循环和其他内容。然后需要在两个位置(预览和表单值)中显示它。 我的问题是。我如何在变量中捕获生成的XML或其他内容,所以我只需要生成一次,然后将其打印出来就可以在预览中生成,然后在表单值中生成? 问题答案:

  • 我想在php$变量中获取返回值 我现在得到的是这样的 ok true 10007.20 cd3f2d61-c929-4a6e-a587-33878fb2b836 200 虽然我想在变量中得到它: > $value 1='ok'; $value 2='true'; $value 3='10007.20'; Echo html实体($内容); ok true 10005.20 4ce81f05-31c

  • 问题内容: 我正在尝试从Python内部进行比特币付款。在bash中,我通常会这样做: 因此,例如: 如果成功,我会得到一个交易ID作为输出,但是如果我尝试转账大于我的比特币余额的金额,则会得到以下输出: 现在,在我的Python程序中,我尝试按以下方式进行付款: 如果有足够的余额,则可以正常工作,但是如果没有足够的余额,则会输出以下内容: 它不包括我在命令行中得到的错误。所以我的问题是;如何从P

  • 问题内容: Commons exec提供了PumpStreamHandler,它将标准输出重定向到Java进程的标准输出。如何将命令的输出捕获到字符串中? 问题答案: 他是我发现的东西:

  • 问题内容: 我想在Windows中使用rsync.exe,并在Python中打印标准输出。 我的代码可以运行,但是直到文件传输完成后才能捕获进度!我想实时打印每个文件的进度。 既然我听说使用Python 3.1,现在应该会更好地处理IO。 问题答案: 一些经验法则。 永远不要使用。它不必要地调用额外的shell进程来调用您的程序。 调用进程时,参数作为列表传递。sys.argv在python中是一