Jag*_*n S 6 java linux windows transcode ffmpeg
我试图使用调用ffmpeg的JAVE将*.mov文件转码为*.mp4文件.输入文件和输出文件都是InputStream和OutputStream形式.这意味着我需要将InputStream和OutputStream作为-f和-y parematers传递给ffmpeg.我怎么做 ?
//Read a movfile.mov converted into a FileInputStream
InputStream fileInputStream = getFileInputStream();
OutputStream fileOutputStream = new FileOutputStrea(outputMP4File) //Output
Process p = Runtime.exec("ffmpeg -i - -y -");
InputStream pInStrm = p.getInputStream();
OutputStream pOutStrm = p.getOutputStream();
int vin = 0, vout = 0;
Thread read = new Thread() {
byte[] buff = new byte[4096];
void run() {
while ((vin=fileInputStream.read(buf))!=-1) {
pOutStrm.write(buf, 0, vin);
}
}
}; read.start();
Thread write = new Thread() {
byte[] buff = new byte[4096];
void run() {
while ((vout=pInStrm.read(buf))!=-1) {
fileOutputStream.write(buf, 0, vout);
}
}
}; write.start();
Run Code Online (Sandbox Code Playgroud)
但我一直收到"IOException:管道已关闭"错误.有人可以帮帮我吗?或者,如果有任何JAVA API可以执行此转码(在Windows和RedHat Linux上),那将非常有帮助
谢谢
那是行不通的。
请记住,JAVE 仅充当 ffmpeg 可执行文件的包装器,即您提供参数,例如目标编码、响度等,然后基本上告诉 JAVE 调用 fmpeg 并传递设置,您使用 Java 方法作为参数输入到 ffmpeg可执行的。
此步骤要求您指定的设置为 1. 可序列化 2. ffmpeg 可执行文件已知
现在你可能会说至少有一些InputStreams,比如FileInputStream是可以序列化的,因为有一个低级文件描述符对应于这个InputStream,但是考虑一个ByteArrayInputStream - 我不知道Java是如何在每个平台上实现的,但我以某种方式怀疑,有一个相应的文件描述符。
然而关键的一点是,ffmpeg 可执行文件不知道也不应该知道 InputStream 类型的 Java 对象是什么。它能做的最好的事情(至少在 posix 系统上)是获取一个整数(文件描述符 E)并尝试从中读取数据。然而,使用文件描述符时,很多事情都可能出错。例如,如果它是一个文件,它可能是可查找的,例如,如果它实际上表示从套接字读取的数据,则它可能是可查找的。
令人高兴的是,在 Posix 系统上,每个进程至少有 3 个文件描述符,即 STDIN、STDOUT 和 STDERR。这对应于一个概念,您可以通过管道将输入/输出从一个进程传输到另一个进程。我不知道这是否或如何在 Windows 上工作,但在 OSX 或 Linux 上,您可以将数据通过管道传输到 ffmpeg 可执行文件中。这实际上意味着,您指示 ffmpeg 从 STDIN 文件描述符中读取。
遗憾的是,JAVE 没有实现 ffmpeg 的这一特定功能,即没有方法将数据通过管道传输到 ffmpegs STDIN。
FWIW。您可以编写一些本机 (c/c++) 代码并使用同时保存输入流和输出流的JNI ( http://en.wikipedia.org/wiki/Java_Native_Interface )传递 Java 对象“DecodeFeed”
您必须编写的本机代码可以包含 ffmpeg 源,并使用它们来解码/转码从 DecodeFeed.in 读取的输入,然后写回到 DecodeFeed.out。
我正在Android项目中这样做,你可能想看看以供参考。 https://github.com/fscz/FFmpeg-Android
或者,您可以分叉 JAVE 并自己实现此功能。您可能知道 Java 提供了一种通过调用 Runtime.exec 来运行可执行文件的方法。此调用将返回提供 Process.getOutputStream 的 Process 类的实例。如果写入此输出流,实际上是写入刚刚创建的进程的 STDIN。
有关如何生成和写入进程的文档,请参阅http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html 。
有关 ffmpeg 的可用命令行选项(包括从 STDIN 读取),请参阅http://ffmpeg.org/ffmpeg.html 。
归档时间: |
|
查看次数: |
2075 次 |
最近记录: |