2012-02-19 9 views
6

Próbuję transkodować plik * .mov do pliku * .mp4 przy użyciu JAVE, który wywołuje ffmpeg. Zarówno plik wejściowy, jak i plik wyjściowy są w formularzach InputStream i OutputStream. Oznacza to, że muszę przekazać InputStream i OutputStream jako -i i -y parematers dla ffmpeg. Jak to zrobić?Przekazywanie FileInputStream i FileOutputStream do ffmpeg w celu transkodowania (przy użyciu JAVE-Java Audio Video Encoding)

//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(); 

ale wciąż otrzymuję "IOException: rura jest zamknięty" błąd. Czy ktoś może mi pomóc? Alternatywnie, jeżeli istnieje jakikolwiek Java API, które mogłyby to zrobić transkodowania (w systemach Windows i Linux RedHat), że byłoby bardzo pomocne

Dzięki

Odpowiedz

3

To nie będzie działać w ten sposób.

Pamiętaj, że Jave jedynie działa jako owijki do ffmpeg wykonywalnego, który jest podać parametry, takie jak kodowanie docelowej, głośność itp i następnie w zasadzie powiedzieć Jave zadzwonić fmpeg i przekazać te ustawienia, używając wprowadzony Metody Java jako parametry pliku wykonywalnego ffmpeg.

Ten etap wymaga ustawienia, można określić to 1. Serializable 2. Znany wykonywalnego ffmpeg

Teraz można argumentować, że przynajmniej niektóre InputStreams, jak FileInputStream są jakoś serializacji, jak tam jest deskryptor pliku niskiego poziomu, który odpowiada temu strumieniowi wejściowemu, ale rozważmy ByteArrayInputStream - nie wiem jak implementuje Java na każdej platformie, ale mam wątpliwości, że istnieje odpowiedni deskryptor pliku.

Najważniejsze jednak jest to, że plik wykonywalny ffmpeg nie powinien i powinien być nie wiedzieć, co to jest obiekt Java typu InputStream. Najlepsze co można zrobić (przynajmniej na systemach posix) jest pobranie liczby całkowitej (Deskryptor pliku) i próba odczytania z niej danych. Jednak wiele rzeczy może pójść źle, gdy pracuje z deskryptorem pliku. Na przykład może być widoczny, jeśli jest to plik, na przykład czy nie, jeśli faktycznie reprezentuje dane odczytane z gniazda.

Chętnie, w systemach Posix dla każdego procesu istnieją co najmniej 3 deskryptory plików, czyli STDIN, STDOUT i STDERR. Odpowiada to koncepcji, w której można wprowadzać/wyprowadzać rury z jednego procesu do drugiego. Nie wiem, czy i jak to działa w systemie Windows, ale w systemach OSX i Linux można przesyłać dane do pliku wykonywalnego ffmpeg. Ten w rzeczywistości oznacza, że ​​instruujesz ffmpeg, aby odczytał deskryptor pliku STDIN.

Niestety, JAVE nie implementuje tej konkretnej funkcji ffmpeg, tj. Nie ma metody , która przetwarza dane do ffmpegs STDIN.

FWIW.Można napisać rodzimych (C/C++) kod i przejść w dół JavaObject „DecodeFeed”, używając JNI (http://en.wikipedia.org/wiki/Java_Native_Interface), która posiada zarówno InputStream i OutputStream

kod natywny, trzeba napisać mogłyby obejmować źródła ffmpeg i użyj ich do odszyfrowania/transkodowania wejścia odczytywanego z DecodeFeed.in, a następnie odesłania do DecodeFeed.out.

Robię to w projekcie Android, możesz zajrzeć do niego w celach informacyjnych. https://github.com/fscz/FFmpeg-Android

Możesz też samodzielnie rozwidlić JAVE i zaimplementować tę funkcję. Jak być może wiesz, Java oferuje sposób uruchomienia pliku wykonywalnego przez wywołanie Runtime.exec. To wywołanie zwróci instancję klasy Process, która oferuje Process.getOutputStream. Jeśli piszesz do tego strumienia wyjściowego, to wpisujesz do STDIN właśnie utworzonego procesu.

Zobacz http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html , aby uzyskać dokumentację dotyczącą odrodzenia i napisania do procesu.

I zobaczyć http://ffmpeg.org/ffmpeg.html dla dostępnych opcji wiersza poleceń (w tym czytania z stdin) dla ffmpeg.

Powiązane problemy