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
- Compilar Java para Android nativo en lugar de escribir en C
- Cómo pasar un mapa de bits de Java a C ++ con JNI en Android Development
- Android Equalizer para nivel de API <9
- Clases del editor de vídeo de Android
- Se produjo un error al agregar a la tabla ref de matrices JNI fijada (1024 entradas)
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
- Integración de Unity3d con android
- Android: Uso de JNI desde NativeActivity
- JNI / Android: llamada a un método no estático en Java desde C ++?
- Cómo agregar un servicio de sistema a Android Framework
- Cómo convertir char a jstring en JNI?
- Incluye la biblioteca Boost C ++ en android
- Android ICS: intento de error JNI para usar referencia local obsoleta 0x1
- ¿Cómo utilizar la biblioteca JNI compilada por NDK en una aplicación Java normal no Android?
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?