2013-04-19 8 views
14

Udało mi się skompilować halfninja ffmpeg scripts dla systemu Android NDK przy użyciu wersji NDK r5c. (Niestety, każda próba kompilacji z wcześniejszym NDK spowodowała pewien błąd), także nie mam zbyt dużej wiedzy na temat całego procesu NDK, więc jest to dla mnie za mało.Łączenie plików mp4 w systemie Android za pomocą programu halfninja ffmpeg

Jego skrypty są kompilacji wersji ffmpeg N-30996-gf925b24 (specyficzna popełnienia zrobił skrypty FOR)

naprzód do mojego rzeczywistej aplikacji. udaje mi się przycinać filmy bez problemów, teraz muszę dołączyć/złączyć je, ale żadnej attemp przy użyciu żadnych i kilka kombinacji poleceń znajdujących się na tych 3 linków (link1, link2, link3) generują błędy, takie jak cat is not valid, > is undefinined, unknown option filter_complex lub próbuje zastąpić niektóre pliki wejściowe.

Czy ktoś wie, czy jest to możliwe i (jak to zrobić), dołączać/łączyć filmy MP4 (cały ten sam kodek, rozmiar, jakość itp.) Za pomocą kompilacji ffmpeg na Androida lub kompilacji/zdobyć ffmpeg na Androida z wykorzystaniem najnowszych kodów źródłowych?

Podałem też szybką próbę na mp4Parser bez większego sukcesu.

ostatecznie starałem się uzyskać ten pseudo-metody pracy:

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

udało mi się skompilować projekt pół-ninja, ale teraz chcę do kompresji dużych plików wideo, ale przede wszystkim starałem się uzyskać dźwięk z plik audio, komenda run unfortutaly nie działa, podaje następujący błąd, 12-20 13: 31: 26.958: W/ActivityManager (290): Wymuś usunięcie ActivityRecord {2c0322f0 uk.co.halfninja.videokit/.MainActivity}: aplikacja zginęła, brak zapisanego stanu jakiś szczególny powód? –

Odpowiedz

2

to sekwencja będzie kot mp4 jest na CLI. jej ze strony ffmpeg FAQ na łączenie ...

$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 

Spojrzałem na „Android.mk” halfninja ... i do testów, powinieneś być w stanie korzystać adb push „ffmpeg” wykonywalny z halfninja budowie do/data/local/... przez telefon. Podczas budowania projektu, myślę, że plik wykonywalny znajdzie się w folderze ../output, nad folderem JNI w swoim projekcie.

Zakładając, że możesz uzyskać root na urządzeniu, możesz następnie przetestować interfejs CLI w telefonie, uzyskując powłokę, a następnie uruchamiając root za pomocą "su", a następnie kopiując wyrażenia cli z wątków ffmpeg/MP4/concat, np. jako ten one i uruchamianie ich w telefonie z wyjściami do folderu, do którego masz dostęp.

W trybie testowym, jeśli możesz uzyskać żądany wynik, używając wywołań CLI krok po kroku, jak pokazano w zaakceptowanej odpowiedzi łącza, możesz wrócić do interfejsów JNI, wywołując pakiet "videokit" halfninja, implementując te same sekwencje poleceń, które zostały użyte w teście.

Dodany Uwaga na wielu połączeń ...

Ponieważ będziesz wzywając do ffmpeg lib w JNI wiele razy, należy zdawać sobie sprawę z tego issue które mogą mieć wpływ wiele połączeń do ffmpeg thru JNI. Jeśli półninja nie przeprowadził już mediacji w tym temacie, może zajść konieczność zmiany struktury systemu Android.mk w celu implementacji omawianej biblioteki otoki w wątku, aby można było ładować/usuwać wymagane biblioteki współdzielone pomiędzy każdym wywołaniem ffmpeg za pośrednictwem interfejsu JNI .

android i „kot”

trzeba mieć dowiązania w/system/bin na telefon

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

jeśli nie, spróbuj „BusyBox” zainstalować w telefonie, dzięki czemu można symulować włączony na cli przez telefon.

+0

cześć. Dzięki za próbę, ale nie jestem pewien, czy zrozumiałeś całe pytanie. Nie mam problemów z kompilowaniem, instalowaniem lub uruchamianiem kompilacji halfninja ffmpeg. Mogę też z łatwością nazwać "public native void run (String [] args);" z VideoKit.java, aby na przykład przyciąć wideo. Pytanie brzmi: jaki jest konkretny "String []", który mogę przekazać, aby scalić wideo? – Budius

+0

http://stackoverflow.com/questions/12817198/ffmpeg-1-0-android-ndk-r8b U może wypróbować to, aby zbudować nowszą ffmpeg na Androidzie zawierającą "concat" ... powód, dla którego została osadzona specyficzna wersja ffmpeg jest to niechlujny proces, w którym można zamieniać się źródłowymi źródłami na ffmpeg i oczekiwać, że edycje linków w Android.mk będą działały. –

+0

zmieniono moje orig. odpowiedzieć –

4

Odpowiedź udzielona przez LordNeckbeard jest naprawdę drogą do zrobienia.

How to concatenate flv file into one?

Praca z ograniczeniami

  • bez -f concat
  • bez -c
  • nie -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

cześć. Po prostu próbuję tego. '-c' zawsze zawiedzie, zastąpiłem' -vcodec' i '-acodec', a następnie dało mi' Nierozpoznaną opcję bsf', a następnie bez 'bsf' otrzymuję' av_interleaved_write_frame(): Operacja niedozwolona'. Wypróbuję komentarz @Robert Rowntree, aby użyć tego tematu: http://stackoverflow.com/questions/12817198/ffmpeg-1-0-android-ndk-r8b, ale zajmie mi to trochę czasu, ponieważ 1) jest to osobisty projekt, który robię w wolnym czasie i przenoszę kraj, więc wolny czas nie nastąpi szybko i 2) dopóki nie obejrzę go i nie zrozumiem, co jest grane przy wszystkich poleceniach. – Budius

+1

Witaj, Steve, jestem naprawdę szczęśliwy, że zdobyłeś połowę/nagrodę, ponieważ mogłem zobaczyć twój wysiłek i naprawdę to doceniam. Niestety, moje życie postanowiło nieco przewrócić się do góry nogami, ponieważ przeprowadzam się do kraju i po prostu nie mogłem go przetestować. Ale na pewno przetestuję i dam ci znać. Również jeśli/kiedy uda mi się uzyskać coś działającego, dam odpowiedź. – Budius

1

Ponieważ wersja programu FFmpeg w wersji HalfNinja nie może korzystać z funkcji łączonej, radzę zaktualizować bibliotekę FFmpeg do wersji co najmniej w wersji 1.1.

Moim zdaniem masz dwie opcje:

  • spróbować skompilować nowszej wersji FFmpeg, używając jednego z tych dwóch Compiling FFmpeg on Android przewodników. Wtedy prawdopodobnie potrzebujesz również nowszej wersji Androida NDK. To najprostsze rozwiązanie.

  • Lub spróbuj wdrożyć nowszą wersję FFmpeg w bibliotekach półninja, co jest trudniejsze, ale możesz zachować prawie ten sam interfejs.

0

Witam mam tę duszę. Używam Mp4parser bibliotekę

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

} 

i wywołać z:

Mp4ParserWrapper.append(firstfilename,secondfilename); 
+0

do której biblioteki należy dołączyć, aby ten kod działał – Mavie

Powiązane problemy