Comprimir vídeos utilizando FFMPEG y JNI
Quiero crear una aplicación de Android que puede localizar un archivo de vídeo (que es más de 300 mb) y comprimirlo a menor tamaño de archivo mp4.
ya he intentado hacerlo con esto
- Cómo utilizar correctamente NDK-Build en Android Studio 2.2 Vista previa 1
- Android MediaRecorder para grabar una superficie (no la cámara)
- Redireccionamiento de STDIN y STDOUT del programa C en Android
- Defragment H264 NAL corriente (originalmente 1722 avb paquetes)
- Asignación simple que viene con valor incorrecto
Este tutorial es muy efectivo ya que está comprimiendo un video de tamaño pequeño (inferior a 100 mb)
Así que intenté implementarlo usando JNI.
me las arreglé para construir ffmpeg usando esto
Pero actualmente lo que quiero hacer es comprimir videos. No tengo muy buen conocimiento en JNI. Pero traté de entenderlo usando el siguiente enlace
Si alguien me puede guiar los pasos para comprimir el video después de abrir el archivo que utiliza JNI que whould realmente genial, gracias
- ¿Cómo funciona NDK en Android - ¿Cuál es la orden que NDK, JNI etc se utilizan?
- La opción CheckJNI no funciona
- Cómo crear jni y Android.mk?
- Error de segmentación en la biblioteca nativa cuando se ejecuta bajo Android antes de 4.0.3
- No se invoca el método Java cuando se llama desde pthread nativo
- La aplicación de Android NDK no puede acceder a ningún punto de interrupción
- C ++ y JNI - Cómo pasar una matriz en un jfloatArray
- Cómo crear un archivo de encabezado C utilizando la herramienta Javah
Suponiendo que tiene el camino de cadena del archivo de entrada, podemos realizar su tarea con bastante facilidad. Asumo que usted tiene una comprensión de los fundamentos de NDK: Cómo conectar un archivo .c nativo a native
métodos native
en un archivo .java correspondiente (Déjeme saber si eso es parte de su pregunta). En su lugar me centraré en cómo utilizar FFmpeg dentro del contexto de Android / JNI.
Visión general de alto nivel:
#include <jni.h> #include <android/log.h> #include <string.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #define LOG_TAG "FFmpegWrapper" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) void Java_com_example_yourapp_yourJavaClass_compressFile(JNIEnv *env, jobject obj, jstring jInputPath, jstring jInputFormat, jstring jOutputPath, jstring JOutputFormat){ // One-time FFmpeg initialization av_register_all(); avformat_network_init(); avcodec_register_all(); const char* inputPath = (*env)->GetStringUTFChars(env, jInputPath, NULL); const char* outputPath = (*env)->GetStringUTFChars(env, jOutputPath, NULL); // format names are hints. See available options on your host machine via $ ffmpeg -formats const char* inputFormat = (*env)->GetStringUTFChars(env, jInputFormat, NULL); const char* outputFormat = (*env)->GetStringUTFChars(env, jOutputFormat, NULL); AVFormatContext *outputFormatContext = avFormatContextForOutputPath(outputPath, outputFormat); AVFormatContext *inputFormatContext = avFormatContextForInputPath(inputPath, inputFormat /* not necessary since file can be inspected */); copyAVFormatContext(&outputFormatContext, &inputFormatContext); // Modify outputFormatContext->codec parameters per your liking // See http://ffmpeg.org/doxygen/trunk/structAVCodecContext.html int result = openFileForWriting(outputFormatContext, outputPath); if(result < 0){ LOGE("openFileForWriting error: %d", result); } writeFileHeader(outputFormatContext); // Copy input to output frame by frame AVPacket *inputPacket; inputPacket = av_malloc(sizeof(AVPacket)); int continueRecording = 1; int avReadResult = 0; int writeFrameResult = 0; int frameCount = 0; while(continueRecording == 1){ avReadResult = av_read_frame(inputFormatContext, inputPacket); frameCount++; if(avReadResult != 0){ if (avReadResult != AVERROR_EOF) { LOGE("av_read_frame error: %s", stringForAVErrorNumber(avReadResult)); }else{ LOGI("End of input file"); } continueRecording = 0; } AVStream *outStream = outputFormatContext->streams[inputPacket->stream_index]; writeFrameResult = av_interleaved_write_frame(outputFormatContext, inputPacket); if(writeFrameResult < 0){ LOGE("av_interleaved_write_frame error: %s", stringForAVErrorNumber(avReadResult)); } } // Finalize the output file int writeTrailerResult = writeFileTrailer(outputFormatContext); if(writeTrailerResult < 0){ LOGE("av_write_trailer error: %s", stringForAVErrorNumber(writeTrailerResult)); } LOGI("Wrote trailer"); }
Para el contenido completo de todas las funciones auxiliares (las de camelCase), vea mi proyecto completo en Github . ¿Tiene preguntas? Estoy feliz de elaborar.
- Draw Rectangle Over ImageView para resaltar que puede ser zoom in-out en android
- Android: ¿Cómo comprobar si el archivo es imagen?