2013-04-19 32 views
14

Tôi đã quản lý để biên dịch halfninja ffmpeg scripts cho NDK của Android bằng cách sử dụng phiên bản NDK r5c. (Thật không may bất kỳ nỗ lực để biên dịch với NDK trước đó tạo ra một số lỗi), tôi cũng không phải là rất am hiểu về toàn bộ quá trình NDK, vì vậy nó là một chút hit-n-miss cho tôi.Các tệp mp4 liên quan trong Android sử dụng halfninja ffmpeg

kịch bản của ông được biên soạn phiên bản ffmpeg N-30.996-gf925b24 (cam kết cụ thể ông đã làm các kịch bản cho)

Tiến về phía trước để ứng dụng thực tế của tôi. tôi quản lý để cắt video mà không vấn đề, bây giờ tôi cần phải tham gia/tiếp nhau chúng nhưng bất kỳ attemp việc sử dụng bất kỳ và một số sự kết hợp của các lệnh tìm thấy trên những 3 liên kết (link1, link2, link3) tạo ra các lỗi như cat is not valid, > is undefinined, unknown option filter_complex hoặc cố gắng ghi đè lên một số tệp đầu vào.

Có ai biết nếu có thể và (cách thực hiện), tham gia/ghép nối video mp4 (tất cả cùng codec, kích thước, chất lượng, v.v.) bằng cách sử dụng biên dịch một nửa ninja của ffmpeg trên Android hoặc cách biên dịch/có được một ffmpeg cho Android bằng cách sử dụng mã nguồn mới nhất?

Tôi cũng đã thử nhanh trên mp4Parser mà không thành công nhiều.

cuối cùng tôi đã cố gắng để có được điều này giả phương pháp làm việc:

public static File concatenate(String[] inputPaths, String outputPath){ 

    // ... do stuff do generate ffmpeg commands.... 
    VideoKit v = new VideoKit(); 
    v.run(cmds); 

    File f = new File(outputPath); 
    return f; 
} 
+0

tôi quản lý để lập dự án nửa ninja, nhưng bây giờ tôi muốn để nén file video lớn, nhưng trước hết tôi đã cố gắng để có được âm thanh từ một tệp âm thanh, lệnh chạy không may không hoạt động, cung cấp lỗi sau, 12-20 13: 31: 26.958: W/ActivityManager (290): Loại bỏ ActivityRecord {2c0322f0 uk.co.halfninja.videokit/.MainActivity}: ứng dụng đã chết, không có trạng thái nào được lưu bất kỳ lý do cụ thể nào ?? –

Trả lời

2

chuỗi này sẽ mp4 mèo trên CLI. của nó từ trang ffmpeg faq trên nối ...

$FFMPEG_HOME/ffmpeg -i gpsclip_seg1.mp4 -vn -f u16le -acodec pcm_s16le -ac 1 -ar 44100 - > temp1.a < /dev/null 
$FFMPEG_HOME/ffmpeg -i gpsclip_seg2.mp4 -vn -f u16le -acodec pcm_s16le -ac 1 -ar 44100 - > temp2.a < /dev/null 
$FFMPEG_HOME/ffmpeg -i gpsclip_seg3.mp4 -vn -f u16le -acodec pcm_s16le -ac 1 -ar 44100 - > temp3.a < /dev/null 
cat temp1.a temp2.a temp3.a > all.a 

$FFMPEG_HOME/ffmpeg -i gpsclip_seg1.mp4 -an -f yuv4mpegpipe - > temp1.v < /dev/null & 
$FFMPEG_HOME/ffmpeg -i gpsclip_seg2.mp4 -an -f yuv4mpegpipe - < /dev/null | tail -n +2 > temp2.v 
$FFMPEG_HOME/ffmpeg -i gpsclip_seg3.mp4 -an -f yuv4mpegpipe - < /dev/null | tail -n +2 > temp3.v 
cat temp1.v temp2.v temp3.v > all.v 

$FFMPEG_HOME/ffmpeg -f u16le -acodec pcm_s16le -ac 1 -ar 44100 -i all.a -f yuv4mpegpipe -i all.v -same_quant -y output.mp4 

tôi nhìn 'Android.mk' của halfninja ... và để thử nghiệm, bạn sẽ có thể sử dụng adb để đẩy 'ffmpeg' thực thi từ halfninja xây dựng đến/data/local/... trên điện thoại. Khi xây dựng dự án, tôi nghĩ rằng tệp thực thi sẽ nằm trong thư mục ../output, phía trên thư mục JNI trong dự án của anh ấy.

Giả sử bạn có thể lấy gốc trên thiết bị, sau đó bạn có thể thử nghiệm trên giao diện CLI trên điện thoại bằng cách lấy vỏ, sau đó lấy root bằng 'su', sau đó sao chép các biểu thức cli từ chuỗi ffmpeg/MP4/concat như thế này one và chạy chúng trên điện thoại với đầu ra vào một thư mục mà bạn có quyền truy cập. Trong chế độ thử nghiệm, nếu bạn có thể nhận được kết quả mong muốn bằng cách sử dụng bước tại một thời điểm CLI invocations như được hiển thị trong câu trả lời được chấp nhận của liên kết, sau đó bạn có thể quay lại giao diện JNI, gọi gói 'videokit' của halfninja, triển khai thực hiện cùng một chuỗi các lệnh mà bạn đã sử dụng trong thử nghiệm.

Added Lưu ý về nhiều cuộc gọi ...

Vì bạn sẽ được gọi để lib ffmpeg trong JNI nhiều lần, bạn cần phải nhận thức issue này có thể ảnh hưởng nhiều cuộc gọi vào ffmpeg qua JNI. Nếu halfninja chưa thực hiện trung gian vấn đề này, bạn có thể phải thay đổi cấu trúc Android.mk để triển khai thư viện trình bao bọc trong chuỗi để bạn có thể tải/dỡ bỏ các lib được chia sẻ cần thiết giữa mỗi cuộc gọi đến ffmpeg qua JNI .

android và 'mèo'

bạn nên có một liên kết tượng trưng trong/system/bin trên điện thoại

lrwxr-xr-x root  shell    2012-07-09 13:02 cat -> toolbox 

nếu không, hãy thử 'busybox' cài đặt trên điện thoại, do đó bạn có thể mô phỏng kịch bản trên cli trên điện thoại.

+0

hi. Cảm ơn bạn đã thử nhưng tôi không chắc bạn đã hiểu toàn bộ câu hỏi chưa. Tôi không có vấn đề biên dịch, cài đặt hoặc thực hiện xây dựng halfninja của ffmpeg. Và tôi có thể dễ dàng gọi là 'public void void run (String [] args);' từ VideoKit.java để cắt video chẳng hạn. Câu hỏi đặt ra là: 'Chuỗi [] cụ thể là gì? Tôi có thể chuyển cho nó để làm cho nó hợp nhất các video? – Budius

+0

http://stackoverflow.com/questions/12817198/ffmpeg-1-0-android-ndk-r8b U có thể thử điều này để xây dựng ffmpeg gần đây hơn trên android có chứa 'concat' ... lý do halfninja nhúng phiên bản cụ thể của ffmpeg là nó là một quá trình lộn xộn để chuyển đổi trong các cây nguồn khác cho ffmpeg và mong đợi các chỉnh sửa liên kết trong Android.mk hoạt động. –

+0

sửa đổi orig của tôi. answer –

4

Câu trả lời được cung cấp bởi LordNeckbeard thực sự là cách để đi.

How to concatenate flv file into one?

Làm việc với những hạn chế của bạn

  • không -f concat
  • không -c
  • không -bsf
ffmpeg -i q.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb q.ts 
ffmpeg -i r.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb r.ts 
ffmpeg -i 'concat:q.ts|r.ts' -vcodec copy -acodec copy -absf aac_adtstoasc qr.mp4 

Joining H264 *without* re-encoding

+0

hi. Tôi chỉ có một thử trên này. '-c' luôn thất bại, tôi thay thế bằng' -vcodec' và '-acodec', sau đó nó cho tôi' tùy chọn không được nhận dạng bsf' và sau đó không có 'bsf' tôi nhận được' av_interleaved_write_frame(): Thao tác không được phép'. Tôi sẽ đưa ra một thử trên bình luận @Robert Rowntree để sử dụng chủ đề này http://stackoverflow.com/questions/12817198/ffmpeg-1-0-android-ndk-r8b nhưng nó sẽ đưa tôi một thời gian vì 1) đó là một dự án cá nhân mà tôi đang làm trong thời gian rảnh và tôi đang di chuyển đất nước vì vậy thời gian rảnh sẽ không xảy ra sớm và 2) cho đến khi tôi có được đầu xung quanh nó và hiểu những gì đang xảy ra với tất cả các lệnh. – Budius

+1

Xin chào Steve, tôi thực sự hạnh phúc vì bạn đã kiếm được một nửa/tiền thưởng vì tôi có thể thấy nỗ lực của bạn và tôi thực sự thực sự đánh giá cao nó. Thật không may cuộc sống của tôi đã quyết định biến một chút lộn ngược vì tôi đang di chuyển đất nước và tôi chỉ đơn giản là không thể kiểm tra nó. Nhưng tôi chắc chắn sẽ kiểm tra và cho bạn biết. Ngoài ra nếu/khi tôi quản lý để có được một cái gì đó làm việc tôi sẽ đặt một câu trả lời. – Budius

1

Vì phiên bản halfninja của FFmpeg không thể sử dụng chức năng ghép nối, tôi khuyên bạn nên cập nhật thư viện FFmpeg thành ít nhất phiên bản 1.1.

Theo tôi bạn có hai lựa chọn:

  • Cố gắng để biên dịch một phiên bản mới hơn của FFmpeg sử dụng một trong hai Compiling FFmpeg on Android hướng dẫn này. Sau đó, bạn cũng có thể cần một phiên bản mới hơn của NDK của Android. Đây là giải pháp đơn giản nhất.

  • Hoặc cố gắng triển khai phiên bản FFmpeg mới hơn trong thư viện halfninja, điều này khó hơn, nhưng sau đó bạn có thể giữ gần như cùng một giao diện.

0

Xin chào tôi đã có linh hồn đó. Tôi Sử dụng Mp4parser thư viện

public class Mp4ParserWrapper { 

    public static final String TAG = Mp4ParserWrapper.class.getSimpleName(); 

    public static final int FILE_BUFFER_SIZE = 1024; 

    /** 
    * Appends mp4 audio/video from {@code anotherFileName} to {@code mainFileName}. 
    */ 
    public static boolean append(String mainFileName, String anotherFileName) { 
     boolean rvalue = false; 
     try { 
      File targetFile = new File(mainFileName); 
      File anotherFile = new File(anotherFileName); 
      if (targetFile.exists() && targetFile.length()>0) { 
       String tmpFileName = mainFileName + ".tmp"; 
       //mainfile=vishal0 
       //another file=vishal1 
       //tmpfile=vishal0.tmp 

       append(mainFileName, anotherFileName, tmpFileName); 
       copyFile(tmpFileName, mainFileName); 
       anotherFile.delete(); 
       new File(tmpFileName).delete(); 
       rvalue = true; 
      } else if (targetFile.createNewFile()) { 
       copyFile(anotherFileName, mainFileName); 
       anotherFile.delete(); 
       rvalue = true; 
      } 
     } catch (IOException e) { 
      Log.e(TAG, "Append two mp4 files exception", e); 
     } 
     return rvalue; 
    } 


    public static void copyFile(final String from, final String destination) 
      throws IOException { 
     FileInputStream in = new FileInputStream(from); 
     FileOutputStream out = new FileOutputStream(destination); 
     copy(in, out); 
     in.close(); 
     out.close(); 
    } 

    public static void copy(FileInputStream in, FileOutputStream out) throws IOException { 
     byte[] buf = new byte[FILE_BUFFER_SIZE]; 
     int len; 
     while ((len = in.read(buf)) > 0) { 
      out.write(buf, 0, len); 
     } 
    } 

    public static void append(
      final String firstFile, 
      final String secondFile, 
      final String newFile) throws IOException { 


     final FileInputStream fisOne = new FileInputStream(new File(secondFile)); 
     final FileInputStream fisTwo = new FileInputStream(new File(firstFile)); 
     final FileOutputStream fos = new FileOutputStream(new File(String.format(newFile))); 

     append(fisOne, fisTwo, fos); 

     fisOne.close(); 
     fisTwo.close(); 
     fos.close(); 
    } 



    // FIXME remove deprecated code 
    public static void append(
      final FileInputStream fisOne, 
      final FileInputStream fisTwo, 
      final FileOutputStream out) throws IOException { 

     final Movie movieOne = MovieCreator.build(Channels.newChannel(fisOne)); 
     final Movie movieTwo = MovieCreator.build(Channels.newChannel(fisTwo)); 
     final Movie finalMovie = new Movie(); 

     final List<Track> movieOneTracks = movieOne.getTracks(); 
     final List<Track> movieTwoTracks = movieTwo.getTracks(); 

     for (int i = 0; i <movieOneTracks.size() || i < movieTwoTracks.size(); ++i) { 
      finalMovie.addTrack(new AppendTrack(movieTwoTracks.get(i), movieOneTracks.get(i))); 
     } 

     final IsoFile isoFile = new DefaultMp4Builder().build(finalMovie); 
     isoFile.getBox(out.getChannel()); 
    } 

} 

Và gọi với:

Mp4ParserWrapper.append(firstfilename,secondfilename); 
+0

thư viện nào để đưa mã này vào hoạt động – Mavie

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