Сжатие видео с использованием FFMPEG и JNI

Я хочу создать приложение для Android, которое может найти видеофайл (более 300 мб) и сжать его до файла mp4 меньшего размера.

Я уже пытался это сделать с этим

Этот учебник очень эффективен, поскольку вы сжимаете видео небольшого размера (менее 100 мб)

Поэтому я попытался реализовать его с помощью JNI.

Мне удалось построить ffmpeg, используя это

Но в настоящее время я хочу сжать видео. Я не очень хорошо знаю JNI. Но я попытался понять это, используя следующую ссылку

Если кто-то может направить меня на шаги, чтобы сжать видео после открытого файла, он использует JNI, что действительно здорово, спасибо

Solutions Collecting From Web of "Сжатие видео с использованием FFMPEG и JNI"

Предполагая, что у вас есть путь String входного файла, мы можем выполнить вашу задачу довольно легко. Я предполагаю, что у вас есть понимание основ NDK: Как подключить собственный .c-файл к native методам в соответствующем .java-файле (дайте мне знать, если это часть вашего вопроса). Вместо этого я сосредоточусь на том, как использовать FFmpeg в контексте Android / JNI.

Обзор высокого уровня:

 #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"); } 

Полный контент всех вспомогательных функций (в CamelCase) см. В моем полном проекте Github . Есть вопросы? Я рад разработать.