6

ffmpegを呼び出すJAVEを使用して、*。movファイルを*.mp4ファイルにトランスコードしようとしています。入力ファイルと出力ファイルはどちらもInputStream形式とOutputStream形式です。つまり、入力ストリームと出力ストリームをffmpegの-iおよび-yパラメーターとして渡す必要があります。それ、どうやったら出来るの ?

    //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の場合)、それは非常に役立ちます

ありがとう

4

1 に答える 1

4

それはそのようには機能しません。

JAVE は単に ffmpeg 実行可能ファイルのラッパーとして機能することを思い出してください。つまり、ターゲット エンコーディング、ラウドネスなどのパラメータを指定してから、基本的に Java メソッドを使用して fmpeg を呼び出して設定を渡すように伝えます。Java メソッドを使用して ffmpeg へのパラメータとして入力します。実行可能。

このステップでは、指定する設定が次のようになっている必要があります。 1. シリアライズ可能 2. ffmpeg 実行可能ファイルに既知

このInputStreamに対応する低レベルのファイル記述子があるため、FileInputStreamのような少なくともいくつかのInputStreamは何らかの形でシリアライズ可能であると主張できますが、ByteArrayInputStreamを検討してください-Javaが各プラットフォームでどのように実装されているかわかりませんが、どういうわけか疑問に思います、対応するファイル記述子があること。

ただし、重要な点は、ffmpeg 実行可能ファイルは、タイプ InputStream の Java オブジェクトが何であるかを認識しておらず、認識してはならないということです。(少なくとも posix システムでは) できる最善の方法は、整数 (File DescriptorE) を取り、そこからデータを読み取ろうとすることです。ただし、File Descriptor を使用する場合、多くのことがうまくいかない可能性があります。たとえば、ソケットから読み取られたデータを実際に表している場合は、ファイルであるかどうかなど、シーク可能である可能性があります。

幸いなことに、Posix システムでは、すべてのプロセスに少なくとも 3 つのファイル記述子 (STDIN、STDOUT、および STDERR) があります。これは、あるプロセスから別のプロセスに入出力をパイプできるという概念に対応しています。これがWindowsで機能するかどうか、またはどのように機能するかはわかりませんが、OSXまたはLinuxでは、データをffmpeg実行可能ファイルにパイプできます。これは実際には、ffmpeg に STDIN ファイル記述子から読み取るように指示することを意味します。

残念ながら、JAVE は ffmpeg のこの特定の機能を実装していません。つまり、データを ffmpegs STDIN にパイプする方法はありません。

ふぅ。Inputstream と OutputStream の両方を保持するJNI ( http://en.wikipedia.org/wiki/Java_Native_Interface ) を使用して、ネイティブ (c/c++) コードを記述し、Java オブジェクト 'DecodeFeed' を渡すことができます。

記述する必要があるネイティブ コードには、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を参照してください。

于 2014-02-17T14:20:03.407 に答える