windows - Passerer FileInputStream og FileOutputStream til ffmpeg til transcode (ved hjælp af JAVE-Java Audio Video Encoding)

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at omdanne en * .mov-fil til en * .mp4-fil ved hjælp af JAVE, som kalder ffmpeg.
Både input fil og output fil er i InputStream og OutputStream formularer.
Det betyder, at jeg skal passere InputStream og OutputStream som -i og -y paratere til ffmpeg.
Hvordan gør jeg det ?


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


Men jeg fortsætter med at få 'IOException: rør er lukket' fejl. Kunne nogen hjælpe mig ud?
Alternativt, hvis der er nogen JAVA API, der kunne gøre denne transcoding (på Windows og RedHat Linux), ville det være meget nyttigt


Tak

Bedste reference


Det vil ikke fungere på den måde.


Husk at JAVE kun virker som en wrapper til en ffmpeg eksekverbar,
Det er du forsyner parametre, som målkodning, lydstyrke osv. og
Fortæl så grundlæggende JAVE at ringe til fmpeg og videregive de indstillinger, du har indtastet
ved hjælp af Java-metoder som parametre til den eksekverbare ffmpeg.


Dette trin kræver, at de indstillinger, du angiver, er
1. Serializable
2. Kendt til ffmpeg eksekverbar


Nu kan du argumentere for, at i det mindste nogle InputStreams, som FileInputStream
er på en eller anden måde serialiserbar, da der er et lavt niveau File Descriptor, der svarer til
til denne InputStream, men overvej et ByteArrayInputStream - jeg ved ikke hvordan
Java implementerer på hver platform, men jeg tvivler på en eller anden måde, at der er en
tilsvarende filbeskrivelse


Det afgørende punkt er imidlertid, at en ffmpeg eksekverbar ikke og bør
ved ikke, hvad et Java-objekt af typen InputStream er. Det bedste, det kunne gøre
(i hvert fald på posix-systemer) er et heltal (File DescriptorE)
og prøv at læse data fra den. Men mange ting kan gå galt, hvornår
arbejder med en filbeskrivelse For eksempel kan det være søgbart, hvis det er
en fil, for eksempel eller ej, hvis det rent faktisk repræsenterer data læst fra en stikkontakt.


Med Posix systemer er der med glæde for hver proces mindst 3 File Descriptors,
det er STDIN, STDOUT og STDERR. Dette svarer til et koncept, hvor du kan
pipe input/output fra en proces til en anden. Jeg ved ikke, om eller hvordan dette virker
på Windows, men på OSX eller Linux kan du pipe data til en ffmpeg eksekverbar. Dette
betyder faktisk, at du instruerer ffmpeg til at læse fra STDIN File Descriptor.


Desværre implementerer JAVE ikke denne særlige funktion af ffmpeg, det er der
ingen metode, der fører data til ffmpegs STDIN.


FWIW. Du kunne skrive nogle native (c/c ++) kode og sende ned et Java Object 'DecodeFeed' ved hjælp af
JNI (http://en.wikipedia.org/wiki/Java\_Native\_Interface), der indeholder både en Inputstream
og en OutputStream [2]


Den oprindelige kode, du skal skrive kunne indeholde ffmpeg-kilderne og bruge dem
at afkode/transcode input, der læses fra DecodeFeed.in og derefter skrives tilbage til
DecodeFeed.out.


Det gør jeg i et Android-projekt, vil du måske se på som reference.
https://github.com/fscz/FFmpeg-Android[3]


Alternativt kan du gaffel JAVE og implementere denne funktion selv.
Som du måske ved, tilbyder Java en måde at køre en eksekverbar ved at ringe
Runtime.exec. Dette opkald vil returnere en forekomst af Process klasse som
tilbyder Process.getOutputStream. Hvis du skriver til denne Outputstream, skal du
faktisk skrive til den netop oprettede proces s STDIN.


Se http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html
til dokumentation om, hvordan man gyder og skriver til en proces. [4]


Og se http://ffmpeg.org/ffmpeg.html
for de tilgængelige kommandolinjeindstillinger (inklusive læsning fra STDIN)
for ffmpeg. [5]