执行exe并读取OutputStream

时间:2014-09-30 18:07:28

标签: java parsing ffmpeg inputstream apache-commons

我有一个名为FFprobe的程序,它可以探测媒体(文件/实时流...)并以不同的格式输出结果,例如:

ffprobe.exe -i test.ts -print_format xml -show_programs

给出了这个输出:

    <?xml version="1.0" encoding="UTF-8"?>
<ffprobe>
    <programs>
        <program program_id="1201" program_num="1201" nb_streams="2" pmt_pid="1000" pcr_pid="2011" start_pts="45394227044" start_time="45394.227044">
            <tag key="service_name" value="Arabica TV"/>
            <tag key="service_provider" value="Nilesat"/>
            <streams>
                <stream index="10" codec_name="mpeg2video" codec_long_name="MPEG-2 video" profile="Main" codec_type="video" codec_time_base="1/50" codec_tag_string="[2][0][0][0]" codec_tag="0x0002" width="720" height="576" has_b_frames="1" sample_aspect_ratio="16:15" display_aspect_ratio="4:3" pix_fmt="yuv420p" level="8" timecode="08:28:54:09" id="0x7db" r_frame_rate="25/1" avg_frame_rate="25/1" time_base="1/90000" start_pts="4085542516" start_time="45394.916844" max_bit_rate="2348000">
                    <disposition default="0" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0"/>
                </stream>
                <stream index="4" codec_name="mp2" codec_long_name="MP2 (MPEG audio layer 2)" codec_type="audio" codec_time_base="1/48000" codec_tag_string="[0][0][0][0]" codec_tag="0x0000" sample_fmt="s16p" sample_rate="48000" channels="2" channel_layout="stereo" bits_per_sample="0" id="0xbcf" r_frame_rate="0/0" avg_frame_rate="0/0" time_base="1/90000" start_pts="4085480434" start_time="45394.227044" bit_rate="384000">
                    <disposition default="0" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0"/>
                </stream>
            </streams>
        </program> 
... more programs 

在java中检索此信息我使用了ProcessBuilder和一个扫描程序,然后在结果正常后id写入文件...但它不是:

 Process proc = new ProcessBuilder("ffprobe.exe","-i", ... same arguments );
 Scanner sc = new Scanner (proc.getInputStream()) // im 100% sure its not errorStream
 while(sc.hasNext()){
   System.out.println(sc.nextLine());
 }

应用程序只是挂起而没有输出,我知道它的悬挂因为该过程仍在运行而扫描仪接下来,但是,我不知道为什么会这样做?如果我在cmd中执行相同的操作我会得到好的结果,我可以使用&#34;&gt;&#34;写入文件。

我已经尝试了-print_format选项,它在错误的数据库中以纯文本形式提供信息(我知道它的错误因为我能用2&gt;而不是&gt;&gt;写),我能够在java中读取错误流,但它并不意味着解析cuz非常无组织。

   Input #0, mpegts, from 'PBR_REC_20140426094852_486.ts':
  Duration: 00:13:34.30, start: 7791.344722, bitrate: 42154 kb/s
  Program 1201 
    Metadata:
      service_name    : Arabica TV
      service_provider: Nilesat
    Stream #0:19[0x7db]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv), 720x576 [SAR 16:15 DAR 4:3], max. 2348 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:3[0xbcf]: Audio: mp2, 48000 Hz, stereo, s16p, 384 kb/s
  Program 1202 
    Metadata:
      service_name    : NBN
      service_provider: NILESAT
    Stream #0:10[0x7d1]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv), 720x576 [SAR 16:15 DAR 4:3], max. 2600 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:11[0xbba](eng): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 125 kb/s
  Program 1203 
    Metadata:
      service_name    : Heya TV
      service_provider: NILESAT
    Stream #0:5[0x7d2]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv), 720x576 [SAR 16:15 DAR 4:3], max. 2600 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:6[0xbbc](eng): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, mono, s16p, 125 kb/s
  Program 1204  ... more programs

现在它似乎有条理并且可以解析&#34;我实际上做了一个解决方案,有点工作,但有时它不坚持这个结构,破坏了整个解析,它为什么我需要一个xml / json ......

-print_format确保输出到输出流。

我没有请求如何使用FFprobe的帮助,因为这不是这个地方的目的,我问为什么我无法从java获取输出流,而如果我在Windows中执行它肯定是输出。

我也尝试过apache commons-exec,因为我知道processbuilder可能很痛苦,它确实执行完美并在System.in中显示(黑色表示输入,红色表示错误),但是使用apache获取流是我无法做到的事情# 39;理解,我试过这个example

我已经处理过的xml解析器,简单地说我只需要从java执行第一个命令并读取输出,但由于某种原因它无法正常工作。

1 个答案:

答案 0 :(得分:1)

我通常使用此实用方法的变体:

public static void runProcess(ProcessBuilder pb) throws IOException {
    pb.redirectErrorStream(true);
    Process p = pb.start();
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}

即使您不想打印错误流,也需要使用它,否则会阻止该过程。在这种情况下,您需要在单独的线程中使用它,并且只打印来自主线程的输入流。