代码一共分两个类,分别是 CmdInputStreamRunnable 和 CmdUtils
CmdInputStreamRunnable.java
import java.io.*;
/**
* @author 张超
* 操作系统执行命令时会有输出,这些输出会被Java当作输入进行读取。
* 本类启动线程来读取操作系统执行命令时的输出,避免出现JVM线程卡死,但命令本身正常的情况。
*/
public class CmdInputStreamRunnable implements Runnable {
private StringBuffer stringBuffer;
private InputStream inputStream;
public CmdInputStreamRunnable(StringBuffer stringBuffer, InputStream inputStream) {
this.stringBuffer = stringBuffer;
this.inputStream = inputStream;
}
@Override
public void run() {
BufferedReader bufrIn = null;
try {
bufrIn = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
// 读取输出
String line = null;
while ((line = bufrIn.readLine()) != null) {
stringBuffer.append(line).append('\n');
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != bufrIn) {
bufrIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
CmdUtils.java
import java.io.*;
/**
* @author 张超
*/
public class CmdUtils {
/**
* 执行命令,返回系统输出的字符串
*
* @param cmd 要执行的执行命令。对于exe等可执行程序,建议在命令中写好绝对路径,或者在操作系统中设置好环境变量。
* @return 系统执行命令后输出的字符串
*/
public static String exec(String cmd) {
// 存放OS执行命令时的输出(对Java来说是输入)
StringBuffer result = new StringBuffer();
Process process = null;
try {
// 执行命令, 返回一个子进程对象(命令在子进程中执行)
process = Runtime.getRuntime().exec(cmd, null, null);
CmdInputStreamRunnable processInput = new CmdInputStreamRunnable(result, process.getInputStream());
CmdInputStreamRunnable processError = new CmdInputStreamRunnable(result, process.getErrorStream());
new Thread(processInput).start();
new Thread(processError).start();
// 方法阻塞, 等待命令执行完成(成功会返回0)
process.waitFor();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 销毁子进程
if (process != null) {
process.destroy();
}
}
// 返回执行结果
return result.toString();
}
/**
* 执行命令,返回系统输出的字符串
*
* @param cmd 要执行的执行命令。对于exe等可执行程序,建议在命令中写好绝对路径,或者在操作系统中设置好环境变量。
* @param timeout 子进程的存活时间,子进程超时后
* @param unit 过期时间的时间单位
* @return 系统执行命令后输出的字符串
*/
public static String exec(String cmd, long timeout, TimeUnit unit) {
// 存放OS执行命令时的输出(对Java来说是输入)
StringBuffer result = new StringBuffer();
Process process = null;
try {
// 执行命令, 返回一个子进程对象(命令在子进程中执行)
process = Runtime.getRuntime().exec(cmd, null, null);
CmdInputStreamRunnable processInput = new CmdInputStreamRunnable(result, process.getInputStream());
CmdInputStreamRunnable processError = new CmdInputStreamRunnable(result, process.getErrorStream());
new Thread(processInput).start();
new Thread(processError).start();
// 方法阻塞, 等待命令执行完成(成功会返回0)
process.waitFor(timeout, unit);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
logger.error("CmdUtils.exec ", e);
} catch (IOException e) {
e.printStackTrace();
logger.error("CmdUtils.exec ", e);
} catch (InterruptedException e) {
e.printStackTrace();
logger.error("CmdUtils.exec ", e);
} finally {
// 销毁子进程
if (process != null) {
process.destroy();
}
}
// 返回执行结果
return result.toString();
}
}
使用方法:
String liveUrl = "..."; // 根据具体业务确定直播流地址
String diskPath = "D:\\yourfolder\\a.mp4";
String cmdStr = "ffmpeg -timeout 9000000 -y -i " + liveUrl + " -vcodec libx264 -f mp4 -t 10 " + diskPath;
String cmdResult = CmdUtils.exec(cmdStr,10, TimeUnit.MINUTES);