Быстрое сжатие видео, как WhatsApp

Мне нужно ускорить сжатие видео в моем приложении для Android. Я использую FFMPEG и мне нужно 3 минуты, чтобы сжать 80 МБ видео. Кто-нибудь знает лучшее решение?

Команда, которую я использую:

/data/data/com.moymer/app_bin/ffmpeg -y -i /storage/emulated/0/DCIM/Camera/VID_20150803_164811363.mp4 -s 640x352 -r 25 -vcodec mpeg4 -ac 1 -preset ultrafast -strict -2 /storage/emulated/0/DCIM/Camera/compressed_video.mp4

Я запускаю эту команду, используя FFMPEG для Android из этого репозитория github:https://github.com/guardianproject/android-ffmpeg-java

Код для использования FFMPEG в моем проекте находится внутри AsyncTask и скопирован ниже:

@Override
protected Object doInBackground(Object... params) {

    ItemRoloDeCamera compressedVideo = new ItemRoloDeCamera();

    File videoInputFile = new File(video.getSdcardPath());

    File videoFolderFile = videoInputFile.getParentFile();

    File videoOutputFile = new File(videoFolderFile, "video_comprimido_moymer.mp4");

    if (videoFolderFile.exists())
        android.util.Log.e("COMPRESS VIDEO UTILS", "video folder exist");
    else
        android.util.Log.e("COMPRESS VIDEO UTILS", "video folder DON'T exist");

    if (videoInputFile.exists())
        android.util.Log.e("COMPRESS VIDEO UTILS", "video input file exist");
    else
        android.util.Log.e("COMPRESS VIDEO UTILS", "video input file DON'T exist");

    if (videoOutputFile.exists())
        android.util.Log.e("COMPRESS VIDEO UTILS", "video output file exist");
    else
        android.util.Log.e("COMPRESS VIDEO UTILS", "video output file DON'T exist");

    FfmpegController ffmpegController;

    try {

        ffmpegController = new FfmpegController(context, videoFolderFile);

        Clip clipIn = new Clip(videoInputFile.getAbsolutePath());

        ffmpegController.getInfo(clipIn, new ShellUtils.ShellCallback() {
            @Override
            public void shellOut(String shellLine) {
                videoInfo.add(shellLine);
            }

            @Override
            public void processComplete(int exitValue) {
                videoInfo.add(String.valueOf(exitValue));
            }
        });

        int rotate = getRotateMetadata();

        Clip clipOut = new Clip(videoOutputFile.getAbsolutePath());
        clipOut.videoFps = "24";
        clipOut.videoBitrate = 512;
        clipOut.audioChannels = 1;
        clipOut.width = 640;
        clipOut.height = 352;

        if (rotate == 90)
            clipOut.videoFilter = "transpose=1";
        else if (rotate == 180)
            clipOut.videoFilter = "transpose=1,transpose=1";
        else if (rotate == 270)
            clipOut.videoFilter = "transpose=1,transpose=1,transpose=1";

        millisDuration = getVideoDuration(videoInputFile.getAbsolutePath());

        float secondsDuration = millisDuration / 1000f;

        clipOut.duration = secondsDuration;

        ffmpegController.processVideo(clipIn, clipOut, true, new ShellUtils.ShellCallback() {
            @Override
            public void shellOut(String shellLine) {

                android.util.Log.e("COMPRESS VIDEO UTILS", "shellOut - " + shellLine);

                float percentage = getTimeMetadata(shellLine);

                if (percentage >= 0f)
                    publishProgress(percentage);

            }

            @Override
            public void processComplete(int exitValue) {
                android.util.Log.e("COMPRESS VIDEO UTILS", "proccess complete - " + exitValue);
            }
        });


    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {

        if (videoOutputFile.exists()) {

            android.util.Log.e("COMPRESS VIDEO UTILS", "finished ffmpeg ---> video output file exist");

            compressedVideo.setSdcardPath(videoOutputFile.getAbsolutePath());

            return compressedVideo;

        } else
            android.util.Log.e("COMPRESS VIDEO UTILS", "finished ffmpeg ---> video output file DON'T exist");

    }

    return compressedVideo;

}

private float getTimeMetadata(String shellLine) {

    float percentage = -1;

    if (shellLine.contains("time=")) {

        String[] timeLine = shellLine.split("=");

        String time = timeLine[5];
        time = time.replace("bitrate", "");
        time = time.trim();

    //            String source = "00:10:17";
        String[] tokens = time.split(":");
        int secondsToMs = (int) (Float.parseFloat(tokens[2]) * 1000);
        int minutesToMs = Integer.parseInt(tokens[1]) * 60000;
        int hoursToMs = Integer.parseInt(tokens[0]) * 3600000;
        long timeInMillis = secondsToMs + minutesToMs + hoursToMs;

        percentage = (timeInMillis * 100.0f) / millisDuration;

    }

    return percentage;

}

private int getRotateMetadata() {

    int rotate = 0;

    String durationString = "";

    for (String shellLine : videoInfo) {

        if (shellLine.contains("rotate")) {

            //rotate          : 270

            String[] rotateLine = shellLine.split(":");

            rotate = Integer.parseInt(rotateLine[1].trim());

        }

    }

    return rotate;

}

public static long getVideoDuration(String videoPath) {

    MediaMetadataRetriever retriever = new MediaMetadataRetriever();

    retriever.setDataSource(videoPath);

    String time = retriever
            .extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);

    long timeInmillisec = Long.parseLong(time);

    return timeInmillisec;

}

Единственное изменение, которое я сделал в методе processVideo, заключалось в добавлении следующих строк при создании команды:

cmd.add("-preset");
cmd.add("ultrafast");

Ответы на вопрос(0)

Ваш ответ на вопрос