avconv tool executed from Java run time stops enco

2019-09-11 16:01发布

问题:

Here I am trying to encode live rtmp stream coming from Flash Media Server and broadcasting low bit rate stream by using avconv tool of Libav. Libav is installed on Ubuntu OS. The encoded stream runs for 8 mins only. As avconv tool is started by using java run time environment. The Java Code is given below -

    public class RunnableStream implements Runnable
    {
        String inStream,outStream,width,height,bitRate,frameRate,fname,line,ar,audioBitRate,audioChannel;
        public RunnableStream(String fname,String inStream,String outStream,String ar,String audioBitRate,String audioChannel,String width,String height,String bitRate,String frameRate)
        {
            this.fname=fname;
            this.inStream=inStream;
            this.outStream=outStream;
            this.width=width;
            this.height=height;
            this.bitRate=bitRate;
            this.frameRate=frameRate;
            this.ar=ar;
            this.audioBitRate=audioBitRate;
            this.audioChannel=audioChannel;

        }

        public void run() {
            Process pr;
            try {
                pr = Runtime.getRuntime().exec("avconv -async 15  -i  "+inStream+" -shortest -s "+width +"*"+height +"  -r " +frameRate+" -b:v "+bitRate+" -ab "+audioBitRate+" -ac "+audioChannel+" -ar "+ar+" -f flv "+outStream);

               InputStream in1 = pr.getInputStream();
               InputStream in = pr.getErrorStream();
    int c1;
    while ((c1 = in1.read()) != -1)
    {
        System.out.print((char)c1);
    }

    int c;
    while ((c = in.read()) != -1)
    {
        System.out.print((char)c);
    }
    pr.waitFor();
    in.close();
    in1.close();

            }catch(Exception e){e.printStackTrace();}
        }
    }

But when same encoding scheme or command is applied directly to command prompt then it can run for atleast 1 hour. Command line statement as given below -

avconv -async 15 -i  rtmp://IP/live/streamname -shortest -s 176*144  -r 10 -b:v 56k  -ab 12k -ac 1 -ar 22050 -f flv rtmp://IP/live/streamname2

回答1:

I assume this code is meant to drain stdout/stderr from the process:

int c1;
while ((c1 = in1.read()) != -1)
{
    System.out.print((char)c1);
}

int c;
while ((c = in.read()) != -1)
{
    System.out.print((char)c);
}

Unfortunately, it will only actually read from in1 (stdout) until the process has finished, then it will read from in (stderr). That means if the process is writing more data to stderr than its buffer can accommodate, it will block - exhibiting exactly the behaviour you're seeing. That isn't definitely the cause, but it seems likely to me.

You should be reading from these streams in different threads, basically - that way you'll read from both streams without having to wait for the process to finish.



回答2:

    public class RunnableStream implements Runnable
    {
        String inStream,outStream,width,height,bitRate,frameRate,fname,line,ar,audioBitRate,audioChannel;
        public RunnableStream(String fname,String inStream,String outStream,String ar,String audioBitRate,String audioChannel,String width,String height,String bitRate,String frameRate)
        {
            this.fname=fname;
            this.inStream=inStream;
            this.outStream=outStream;
            this.width=width;
            this.height=height;
            this.bitRate=bitRate;
            this.frameRate=frameRate;
            this.ar=ar;
            this.audioBitRate=audioBitRate;
            this.audioChannel=audioChannel;

        }

        public void run() {
            Process pr;
            try {
                pr = Runtime.getRuntime().exec("avconv -async 15  -i  "+inStream+" -shortest -s "+width +"*"+height +"  -r " +frameRate+" -b:v "+bitRate+" -ab "+audioBitRate+" -ac "+audioChannel+" -ar "+ar+" -f flv "+outStream);

            StreamGobbler errorGobbler = new StreamGobbler(pr.getErrorStream(), "ERROR");             

                StreamGobbler outputGobbler = new StreamGobbler(pr.getInputStream(), "OUTPUT"); 

                errorGobbler.start(); 
                outputGobbler.start(); 

                int exitVal = pr.waitFor(); 
                System.out.println("ExitValue: " + exitVal); 

            }catch(Exception e){e.printStackTrace();}
        }


    }


    class StreamGobbler extends Thread { 
        InputStream is; 
        String type; 

        StreamGobbler(InputStream is, String type) { 
            this.is = is; 
            this.type = type; 
        } 

        public void run() { 
            try { 
                InputStreamReader isr = new InputStreamReader(is); 
                BufferedReader br = new BufferedReader(isr); 
                String line=null; 
                while ( (line = br.readLine()) != null) 
                    System.out.println(type + ">" + line);     
                } catch (IOException ioe) 
                  { 
                    ioe.printStackTrace();   
                  } 
        } 
    } 
}