2012-02-19 32 views
6

Tôi đang cố chuyển mã tệp * .mov thành tệp * .mp4 bằng JAVE, gọi ffmpeg. Cả tệp đầu vào và tệp đầu ra đều ở dạng InputStream và OutputStream. Điều đó có nghĩa là tôi cần truyền InputStream và OutputStream dưới dạng parier -i và -y cho ffmpeg. Tôi làm như thế nào?Truyền FileInputStream và FileOutputStream tới ffmpeg để chuyển mã (sử dụng Mã hóa Video Âm thanh 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(); 

Nhưng tôi vẫn gặp lỗi "IOException: pipe closed". Ai đó có thể giúp tôi không? Ngoài ra nếu có bất kỳ JAVA API mà có thể làm chuyển mã này (trên Windows và Linux RedHat), mà sẽ rất hữu ích

Cảm ơn

Trả lời

3

Đó không phải là đi làm việc theo cách đó.

Hãy nhớ rằng Jave chỉ đơn thuần đóng vai trò như là một wrapper cho một thực thi ffmpeg, đó là bạn cung cấp các thông số, như mã hóa mục tiêu, độ ồn, vv và sau đó về cơ bản nói Jave gọi fmpeg và vượt qua các thiết lập, bạn cho vào sử dụng Các phương thức Java làm tham số cho tệp thực thi ffmpeg.

Bước này đòi hỏi rằng các thiết lập, bạn chỉ định là 1. Serializable 2. Được biết đến với ffmpeg thực thi

Bây giờ bạn có thể tranh luận rằng ít nhất một số InputStreams, như FileInputStream là bằng cách nào đó serializable, là có Trình mô tả tệp mức thấp tương ứng với InputStream này, nhưng hãy xem xét ByteArrayInputStream - Tôi không biết cách thực hiện Java trên mỗi nền tảng nhưng tôi nghi ngờ rằng có một Bộ mô tả tệp tương ứng .

Tuy nhiên, điểm quan trọng là, tệp thực thi ffmpeg không và nên không biết đối tượng Java loại InputStream là gì. Tốt nhất nó có thể làm (ít nhất là trên các hệ thống posix) là lấy một số nguyên (File DescriptorE) và cố gắng đọc dữ liệu từ nó. Tuy nhiên, rất nhiều thứ có thể sai, khi làm việc với Trình mô tả tệp. Ví dụ, nó có thể được tìm kiếm, nếu nó là một tập tin, ví dụ hay không, nếu nó thực sự đại diện cho dữ liệu đọc từ một ổ cắm.

Rất vui, trên hệ thống Posix, đối với mọi quá trình có ít nhất 3 Trình mô tả tệp, là STDIN, STDOUT và STDERR. Điều này tương ứng với một khái niệm mà bạn có thể nhập đầu vào/đầu ra ống từ quy trình này đến quy trình khác. Tôi không biết nếu hoặc làm thế nào điều này hoạt động trên Windows, nhưng trên OSX hoặc Linux bạn có thể đường ống dữ liệu vào một ffmpeg thực thi. Điều này thực sự có nghĩa là , mà bạn hướng dẫn ffmpeg để đọc từ STDIN File Descriptor.

Đáng buồn thay, JAVE không thực hiện tính năng cụ thể này của ffmpeg, nghĩa là, có không có phương pháp nào, đưa dữ liệu vào ffmpegs STDIN.

FWIW.Bạn có thể viết một số bản địa (c/C++) mã và vượt qua xuống một đối tượng Java 'DecodeFeed', sử dụng JNI (http://en.wikipedia.org/wiki/Java_Native_Interface) chứa cả một InputStream và một OutputStream

Các mã gốc, bạn phải viết có thể bao gồm các nguồn ffmpeg và sử dụng chúng để giải mã/chuyển mã đầu vào được đọc từ DecodeFeed.in và sau đó được viết lại thành DecodeFeed.out.

Tôi đang làm điều đó trong một dự án Android, bạn có thể muốn xem xét để tham khảo. https://github.com/fscz/FFmpeg-Android

Ngoài ra, bạn có thể tự ngã và tự mình thực hiện tính năng này. Như bạn có thể biết Java cung cấp một cách để chạy một tập tin thực thi bằng cách gọi Runtime.exec. Cuộc gọi này sẽ trả về một thể hiện của lớp Process mà cung cấp Process.getOutputStream. Nếu bạn viết vào Outputstream này, bạn thực sự ghi vào STDIN của quy trình vừa tạo.

Xem http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html để biết tài liệu về cách sinh sản và ghi vào quy trình.

Và xem http://ffmpeg.org/ffmpeg.html để biết các tùy chọn dòng lệnh khả dụng (bao gồm đọc từ STDIN) cho ffmpeg.

Các vấn đề liên quan