繁体   English   中英

将FileInputStream和FileOutputStream传递给ffmpeg进行转码(使用JAVE-Java音频视频编码)

[英]Passing FileInputStream and FileOutputStream to ffmpeg to transcode(using JAVE-Java Audio Video Encoding)

我试图使用调用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();  

但我一直收到“IOException:管道已关闭”错误。 有人可以帮帮我吗? 或者,如果有任何JAVA API可以执行此转码(在Windows和RedHat Linux上),那将非常有帮助

谢谢

这不会那样。

请记住,JAVE只是作为ffmpeg可执行文件的包装器,即您提供参数,如目标编码,响度等,然后基本上告诉JAVE调用fmpeg并传递设置,您使用Java方法作为参数输入到ffmpeg可执行文件。

此步骤要求您指定的设置为1.可序列化2.已知ffmpeg可执行文件

现在你可以争辩说至少有一些InputStream,比如FileInputStream在某种程度上是可序列化的,因为有一个低级文件描述符对应于这个InputStream,但考虑一个ByteArrayInputStream - 我不知道Java如何在每个平台上实现,但我不知何故怀疑,有一个相应的文件描述符。

然而关键的一点是,ffmpeg可执行文件不会也不应该知道InputStream类型的Java对象是什么。 它能做的最好(至少在posix系统上)是一个整数(文件描述符)并尝试从中读取数据。 但是,在使用文件描述符时,很多事情都可能出错。 例如,如果它是一个文件,它可能是可搜索的,例如,如果它实际上代表从套接字读取的数据。

很高兴,在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',该JNI同时包含Inputstream和OutputStream

您必须编写的本机代码可以包含ffmpeg源,并使用它们来解码/转码从DecodeFeed.in读取的输入,然后写回DecodeFeed.out。

我在Android项目中这样做,您可能希望查看以供参考。 https://github.com/fscz/FFmpeg-Android

或者,您可以自行分叉JAVE并实现此功能。 您可能知道Java提供了一种通过调用Runtime.exec来运行可执行文件的方法。 此调用将返回提供Process.getOutputStream的Process类的实例。 如果您写入此Outputstream,您实际上写入刚刚创建的进程的STDIN。

有关如何生成和写入进程的文档,请参阅http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html

有关ffmpeg的可用命令行选项(包括从STDIN读取),请参阅http://ffmpeg.org/ffmpeg.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM