Concatenar archivos mp4 en Android usando halfninja ffmpeg

He logrado compilar secuencias de comandos halfninja ffmpeg para Android NDK usando la versión NDK r5c. (Por desgracia, cualquier intento de compilar con anterior NDK generado algún error), también no estoy muy bien informado en todo el proceso de NDK, por lo que es un poco hit-n-miss para mí.

Sus scripts están compilando la versión ffmpeg N-30996-gf925b24 (el commit específico para el que hizo los scripts)

Avanzar a mi aplicación real. Puedo arreglar los videos sin problemas, ahora tengo que unir / concatenarlos, pero cualquier intento de usar una y varias combinaciones de los comandos encontrados en esos 3 enlaces ( link1 , link2 , link3 ) generan errores como cat is not valid , > is undefinined , la unknown option filter_complex o intentar anular algunos de los archivos de entrada.

¿Alguien sabe si es posible y (cómo hacerlo), para unirse / concatenar videos mp4 (codec todo, el mismo tamaño, calidad, etc) utilizando half-ninja compilar de ffmpeg en Android, o cómo compilar / obtener un ffmpeg para Android usando los últimos códigos fuente?

También he dado un rápido intento en el mp4Parser sin mucho éxito.

En última instancia estaba tratando de conseguir este pseudo-método para trabajar:

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

    La respuesta proporcionada por LordNeckbeard es realmente el camino a seguir.

    Cómo concatenar archivos FLV en uno?

    Trabajando con sus restricciones

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

    Unirse a H264 * sin * re-codificar

    Esta secuencia se cat mp4 en la CLI. Es de la página faq de ffmpeg en concatenación …

     $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 

    Miré halfninja 'Android.mk' … y para la prueba, usted debe ser capaz de utilizar adb para empujar 'ffmpeg' ejecutable de halfninja construir a / data / local / … en el teléfono. Al construir el proyecto, creo que el ejecutable estará en la carpeta ../output, por encima de la carpeta JNI en su proyecto.

    Suponiendo que puede obtener root en el dispositivo, puede realizar pruebas en la interfaz CLI en el teléfono obteniendo una shell, luego obteniendo raíz usando 'su', luego copiando las expresiones cli de ffmpeg / MP4 / concat threads como ésta y Ejecutándolos en el teléfono con salidas a una carpeta donde usted tiene acceso.

    En el modo de prueba, si puede obtener el resultado deseado utilizando las invocaciones CLI de paso a paso como se muestra en la respuesta aceptada del enlace, puede volver a sus interfaces JNI, invocando el paquete 'videokit' de halfninja, implementando la misma secuencia de comandos Que utilizó en la prueba.

    Nota añadida en varias llamadas …

    Dado que va a llamar a ffmpeg lib en el JNI varias veces, debe tener en cuenta este problema que puede afectar a varias llamadas en ffmpeg a través de JNI. Si halfninja aún no ha mediado este problema, puede que tenga que cambiar la estructura de Android.mk para implementar la biblioteca de contenedores hablada en el subproceso para que pueda cargar / descargar las bibliotecas compartidas necesarias entre cada llamada a ffmpeg a través de la JNI .

    Androide y 'gato'

    Usted debe tener un enlace simbólico en / system / bin en el teléfono

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

    Si no, intente 'busybox' instalar en el teléfono para que pueda simular scripting en el cli en el teléfono.

    Ffmpeg concat demuxer ha sido añadido a FFMPEG Fire Flower (Versión 1.1). Utilice la flor del fuego de FFmpeg o la magia para conseguir esta característica. Una vez que cree ffmpeg, utilice el demuxer. Lo que se explica en este http://ffmpeg.org/trac/ffmpeg/wiki/How%20to%20concatenate%20(join,%20merge)%20media%20files sitio como concat demuxer.

    Dado que la versión halfninja de FFmpeg no es capaz de utilizar la funcionalidad concatenar, te aconsejo que actualices la librería FFmpeg al menos a la versión 1.1.

    En mi opinión, usted tiene dos opciones:

    • Trate de compilar una versión más reciente de FFmpeg utilizando uno de estos dos Compilando FFmpeg en las guías de Android . Entonces es posible que también necesite una revisión más reciente de la Android NDK. Esta es la solución más simple.

    • O tratar de implementar una versión más reciente de FFmpeg en las bibliotecas halfninja, que es más difícil, pero luego se puede mantener casi la misma interfaz.

    Hola tengo esa alma. Uso de la biblioteca Mp4parser

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

    Y invocar con:

     Mp4ParserWrapper.append(firstfilename,secondfilename); 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.