2012-02-19 2 views
6

Я пытаюсь перекодировать файл * .mov в файл * .mp4 с помощью JAVE, который вызывает ffmpeg. Оба входных файла и выходной файл находятся в формах InputStream и OutputStream. Это означает, что мне нужно передать InputStream и OutputStream как -i и -y parematers для ffmpeg. Как это сделать?Передача FileInputStream и FileOutputStream в ffmpeg для перекодирования (с использованием кодирования аудио Java JAVE-Java)

//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: pipe is closed». Может ли кто-нибудь помочь мне? Кроме того, есть ли JAVA API, которые могли бы сделать это перекодирование (на Windows, и RedHat Linux), это было бы очень полезно

Благодаря

ответ

3

, что не собирается работать таким образом.

Помните, что Jave выступает лишь в качестве оболочки к FFmpeg исполняемого, , который вы поставляете параметры, как целевая кодировка, громкость и т.д. и то в основном говорят Jave позвонить fmpeg и передать параметры, вы ввели с помощью Java-методы как параметры исполняемого файла ffmpeg.

Этот шаг требует настройки, необходимо указать в 1. Сериализуемый 2. Известные в FFmpeg исполняемому

Теперь можно утверждать, что по крайней мере некоторые InputStreams, как FileInputStream каким-то образом сериализации, так как есть файловый дескриптор низкого уровня, который соответствует этому InputStream, но рассмотрим ByteArrayInputStream - я не знаю, как Java реализует на каждой платформе, но я почему-то сомневаюсь, что есть соответствующий файл дескриптора .

Важным моментом является то, что исполняемый файл ffmpeg не должен и должен не знать, что такое объект Java типа InputStream. Лучшее, что могло бы сделать: (по крайней мере, в системах posix), принимает целое число (File DescriptorE) и пытается прочитать данные из него. Однако многое может пойти не так, если работает с файловым дескриптором. Например, он может быть доступен для поиска, если это файл , например, или нет, если он фактически представляет данные, считанные из сокета.

С радостью, в системах Posix для каждого процесса есть не менее 3 дескрипторов файлов, , которые являются STDIN, STDOUT и STDERR. Это соответствует концепции, в которой вы можете использовать входной/выходной сигнал трубы от одного процесса к другому. Я не знаю, работает ли или как это работает в Windows, но на OSX или Linux вы можете передавать данные в исполняемый файл ffmpeg. Этот фактически означает, что вы укажете ffmpeg для чтения из дескриптора файла STDIN.

К сожалению, JAVE не реализует эту особенность ffmpeg, то есть нет метода, который передает данные в ffmpegs STDIN.

FWIW.Вы можете написать некоторые родные (C/C++) код и передать вниз объект Java «DecodeFeed», используя JNI (http://en.wikipedia.org/wiki/Java_Native_Interface), который содержит одновременно InputStream и OutputStream

Нативный код, вы должны написать может включать в себя источники ffmpeg и использовать их для декодирования/перекодирования ввода, который считывается с DecodeFeed.in, а затем записывается обратно в DecodeFeed.out.

Я делаю это в проекте Android, вы можете посмотреть на ссылку. https://github.com/fscz/FFmpeg-Android

В качестве альтернативы вы можете использовать вилку JAVE и реализовать эту функцию самостоятельно. Как вы знаете, Java предлагает способ запуска исполняемого файла, вызывая Runtime.exec. Этот вызов возвращает экземпляр класса Process, который предлагает Process.getOutputStream. Если вы пишете в этот выходной поток, вы написали только STDIN только что созданного процесса.

См. http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html для документации о том, как порождать и записывать в процесс.

И увидеть http://ffmpeg.org/ffmpeg.html для доступных параметров командной строки (включая чтение из STDIN) для FFmpeg.

Смежные вопросы