Run the FFMPEG command in windows,
D:/tools/FFMPEG/bin> ffmpeg.exe-I "Download URL of a video file"-F FLV D:/1.flv
You can directly convert the Input Source of the download link to 1.flv.
String raw2flvcmd = "D:/tools/FFMPEG/bin/ffmpeg.exe-I \" Download URL of a video file \ "-F FLV 1.flv" invalid runtime.getruntime(cmd.exe C (raw2flvcmd );
It can be called successfully.
Run the FFMPEG command in Linux,
/Usr/local/FFMPEG/bin/FFMPEG-I "Download URL of a video file"-F FLV/usr/userfile/FFMPEG/tempfile/1.flv
You can also directly convert the Input Source of the download link to 1.flv.
String raw2flvcmd = "/usr/local/FFMPEG/bin/FFMPEG-I \" Download URL of a video file \ "-F FLV/usr/userfile/FFMPEG/tempfile/1.flv" ;runtime.getruntime(cmd.exe C (raw2flvcmd );
FFmpeg reports the following error:
No such file or directory: "Download URL of a video file ".
Someone on stackoverflow encountered a similar problem:
FFmpeg "No such file or directory" on Android
I am trying to use the FFMPEG binary and call it via a native Linux Command in Android. most of the commands work fine but the problem is that when I need to pass an http url as an input to the-I option I get "No such file or directory" for the URL.
The URL however is existing and running the same command on a Mac does the job as expected.
But no one finally gives the correct solution.
Why is the Java call suspended when terminal runs the same command line statement normally? It seems that Java does not convey the programmer's intentions to the underlying layer.
After many tests, I finally found a solution. Since terminal can be successfully executed, start the shell and then pass the custom command line as a parameter to the shell interpreter. Shell knows how to convey the programmer's intent to the underlying layer. Use sh-C, use the custom cmd line as its parameter, and finally use Java. Lang. runtimeexec (string [] cmdarray ):
String raw2flvcmd = "/usr/local/FFMPEG/bin/FFMPEG-I \" Download URL of a video file \ "-F FLV/usr/userfile/FFMPEG/tempfile/1.flv" ;runtime.getruntime(cmd.exe C (New String [] {"sh ", "-c", raw2flvcmd });
Solve the problem.
Runtime.getruntime(cmd.exe C (raw2flvcmd); a sub-process is started. If the current thread wants to continue to execute after the sub-process is executed, it can call Java. lang. waitfor () method of process:
Process = NULL; try {string raw2flvcmd = "/usr/local/FFMPEG/bin/FFMPEG-I \" Download URL of a video file \ "-F FLV/usr/userfile/FFMPEG/tempfile/1.flv"; process = runtime.getruntime(cmd.exe C (New String [] {"sh", "-c", raw2flvcmd}); process. waitfor ();} catch (exception e) {// do some thing}
The current thread will wait for the sub-process to complete and then continue to execute.
It is worth noting that the FFMPEG process generates a large amount of output information during execution. If we do not output the stream in time, the cache for storing this information will soon fill up, then the process waits for us to output the information, but we are also waiting for the process to end (process. waitfor (); it is obvious that process will not end because it is also waiting for us), so a classic deadlock case is generated.
In this case, our sub-process is blocked, and the thread that we start this sub-process stops with the statement because it never gets the waitfor () response.
Therefore, we need to constantly read data from the input stream in the child process to ensure that it will not block.
When runtime.exe C () won't
Navigate yourself around pitfalls related to the runtime.exe C () method
This article provides an in-depth analysis and provides recommended solutions. Based on this article, we finally improved the Java call FFMPEG in Linux:
Process = NULL; try {string raw2flvcmd = "/usr/local/FFMPEG/bin/FFMPEG-I \" Download URL of a video file \ "-F FLV/usr/userfile/FFMPEG/tempfile/1.flv"; process = runtime.getruntime(cmd.exe C (New String [] {"sh", "-c", raw2flvcmd}); streamgobbler errorgobbler = new streamgobbler (process. geterrorstream (), "error"); errorgobbler. start (); // kick off stderr streamgobbler outgobbler = new streamgobbler (process. getinputstream (), "stdout"); outgobbler. start (); // kick off stdout process. waitfor ();} catch (exception e) {// do some thing}
The source code of streamgobbler is:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; public class StreamGobbler extends Thread {InputStream is;String type;OutputStream os;public StreamGobbler(InputStream is, String type) {this(is, type, null);}public StreamGobbler(InputStream is, String type, OutputStream redirect) {this.is = is;this.type = type;this.os = redirect;}@Overridepublic void run() {try {PrintWriter pw = null;if (os != null)pw = new PrintWriter(os);InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);String line = null;while ((line = br.readLine()) != null) {if (pw != null)pw.println(line);System.out.println(type + ">" + line);}if (pw != null)pw.flush();} catch (IOException ioe) {ioe.printStackTrace();}}}
Finally, disable all Io input/output, error streams, and the destroy () method that calls process to close sub-processes. Otherwise, the program may see "Java. Io. ioexception: Error = 24, too program open files ".