使用java调用FFMPEG进行转码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class TestFFmpeg {
static String ffmpeg_cmd = "/home/andrew/Work/FFmpeg/ffmpeg-3.2/ffmpeg";
//static String in = "/home/andrew/Work/FFmpeg/ffmpeg-3.2/test_2200kbps.flv";
//static String out = "/home/andrew/Work/FFmpeg/ffmpeg-3.2/test_out.flv";
static String in = "rtmp://223.203.1.34:1936/live?vhost=cc.com/stream1_1";
static String out = "rtmp://223.203.1.34:1936/live?vhost=cc.com/stream2";
static Process p;
public static void main(String[] args) {
Runtime rt = Runtime.getRuntime() ;
int r = -1;
Thread stoppingThread;
Thread errorStream;
Thread inputStream;
System.out.println(in);
System.out.println(out);
String[] cmd1 = new String[] {ffmpeg_cmd, "-re", "-i", in, "-acodec", "aac", "-ar", "44100", "-vcodec", "copy", "-report" , "-y", "-f", "flv", out};
//String cmd1 = ffmpeg_cmd + " -re" + " -i " + in + " -acodec", " aac", " -ar" + " 44100" + " -vcodec" + " copy" + " -report" + " -y"," -f" + " flv " + out;
try {
System.out.println(cmd1);
p = rt.exec(cmd1);
StopTranscoder stopRunnable = new StopTranscoder(p);
stoppingThread = new Thread(stopRunnable);
stoppingThread.start();
final InputStream is1 = p.getErrorStream ();
final InputStream is2 = p.getInputStream ();
//启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流
GetStream streamErr = new GetStream(is1);
errorStream = new Thread(streamErr);
errorStream.start();
GetStream streamIn = new GetStream(is2);
inputStream = new Thread(streamIn);
inputStream.start();
System.out.println("waiting for");
try {
r = p.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(r);
p.destroy();
}
}
class StopTranscoder implements Runnable {
private Process process = null;
public StopTranscoder(Process proc){
this.process = proc;
}
public void run() {
try {
System.out.println("kill before sleep");
Thread.sleep(10000);
System.out.println("kill after sleep");
this.process.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class GetStream implements Runnable {
private InputStream is;
public GetStream(InputStream stream) {
is = stream;
}
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
try {
String line = null;
while ((line = br.readLine()) != null) {
if (line != null){
System.out.println(line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
执行FFMPEG
启动FFMPEG进程,Runtime.getRuntime().exec(cmd)
启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流
当Runtime对象调用exec(cmd)后,JVM会启动一个子进程,该进程会与JVM进程建立三个管道连接:标准输入,标准输出和标准错误流。假设该程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitfor()这里。
注释:
之前遇到过调用process.destroy()有可能无法使FFMPEG退出的情况,所以增加了类StopTranscoder()进行测试,但是没有复现之前的问题。
本文介绍如何使用Java调用FFmpeg工具进行流媒体转码。通过Runtime.getRuntime().exec(cmd)启动FFmpeg进程,并创建线程分别读取标准输出和错误流,确保进程不会阻塞。示例代码展示了从rtmp源转码到另一个rtmp目标的过程。
5万+

被折叠的 条评论
为什么被折叠?



