Как очень быстро кодировать изображения JPEG в H264 (преобразовывать изображения в видео)

У меня есть 30 изображений в формате JPEG (.jpg) с разрешением 480 x 640. Каждое изображение занимает около 20 КБ (все они занимают около 600 КБ).

Я использую команду FFmpeg для кодирования этих изображений в видео в формате H264.

Мне нужно, чтобы это было сделано очень быстро - около 1 секунды.

Используя классическую команду:

ffmpeg -y  -f  image2   -r 1/5   -i image_%d.jpg   -c:v libx264   -r 30   video.mp4

занимает около 90 секунд.

После добавления -preset ultrafast:

ffmpeg -y  -f  image2   -r 1/5   -i image_%d.jpg   -c:v libx264   -preset ultrafast    -r 30   video.mp4

кодирование занимает около 15 секунд, что намного лучше, но все же недостаточно

Я пробовал и другие параметры, например:

-profile:v baseline

-qscale:v

-b:v 1000k

-crf 24

но время кодирования не опускается ниже 10 секунд.

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

Качество видео должно быть в порядке, не должно быть идеальным.

В качестве примечания: я запускаю эти команды в приложении Android, где у меня есть исполняемый файл ffmpeg, используя ProcessBuilder.

Ответ 1 (Роберту Раунтри):

ArrayList<String> l2 = new ArrayList<String>();

        //l2.add("ffmpeg");
        l2.add("/data/data/" + packageName + "/ffmpeg");
        l2.add("-y");
        l2.add("-loop");
        l2.add("1");

        l2.add("-i");
        l2.add("frame_%d.jpg");

//            l2.add("-t");
//            l2.add(strngs[3]);

        l2.add("-r");
        l2.add("1/2");
        l2.add("-preset");
        l2.add("superfast");
        l2.add("-tune");
        l2.add("zerolatency");

//            l2.add("-pass");
//            l2.add(Integer.valueOf(pass).toString());

        l2.add("-vcodec");
        l2.add("libx264");
        l2.add("-b:v");
        l2.add("200k");
        l2.add("-bt");
        l2.add("50k");
        l2.add("-threads");
        l2.add("0");
        l2.add("-b_strategy");
        l2.add("1");

//            if(pass ==1){
//                l2.add("-an");
//            } else {
//                l2.add("-acodec");
//                l2.add("copy");
//            }

        l2.add("-f");
        l2.add("mp4");
        l2.add("-strict");
        l2.add("-2");
//            l2.add("-passlogfile");
//            l2.add(strngs[4]);

//            if(pass ==1){
//                l2.add("/dev/null");
//            } else {
//                l2.add(strngs[5]);
//            }

        l2.add("video.mp4");
        //return l2;

person Paul    schedule 14.06.2013    source источник
comment
Мне нужно быстрое решение. Меня не так волнует качество видео. Т.к.   -  person Paul    schedule 15.07.2013


Ответы (3)


Как насчет того, чтобы избавиться от -r 1/5? Это ускорило мое кодирование.

person av501    schedule 15.06.2013
comment
Да, кажется, что мне не нужен первый -r, потому что он используется для принудительной настройки частоты кадров входного файла (действительно только для необработанных форматов), а у меня есть файлы jpecg. - person Paul; 18.06.2013
comment
Я не уверен, как использовать второй r (потому что мне нужно указать fps для файла putput), чтобы иметь 5 кадров в секунду. Я использовал 1/02, но кажется, что не все кадры включены в видео, и я не знаю, почему... у вас есть идеи, почему это происходит? - person Paul; 18.06.2013
comment
Разве -r 5 не дает вам 5 кадров в секунду, используя все входные кадры? - person av501; 18.06.2013

IMO - ffmpeg на Android по-прежнему полностью программный (без графического процессора или аппаратного ускорения). Вы можете попробовать просмотреть libstagefright/ffmpeg в сочетании android">вопросы. В любом случае, если вы заинтересованы в скорости, вы должны найти решение для аппаратного ускорения на Android. В противном случае ffmpeg на ограниченной платформе (срок службы батареи, маломощный процессор) будет довольно медленным по сравнению с любой другой платформой.

также см. принятый ответ здесь и это тоже

Я отказался от Android из-за нехватки скорости и остановился на облачном экземпляре для загрузки мультимедиа, а затем для кодирования ffmpeg перед загрузкой на устройство Android. Было бы интересно услышать, получите ли вы быстрый результат на Android.

Кстати, я использовал двухпроходное выражение H264, которое вы видите ниже, прежде чем отказаться от Android для кодирования.

private ArrayList<String> mapFfmpegSwitches(String... strngs){
    ArrayList<String> l2 = new ArrayList<String>();
    l2.add("ffmpeg");
    l2.add("-y");
    l2.add("-loop");
    l2.add("1");
    l2.add("-i");
    l2.add(strngs[1]);
    l2.add("-i");
    l2.add(strngs[2]);
    l2.add("-t");
    l2.add(strngs[3]);
    l2.add("-r");
    l2.add("1/2");
    l2.add("-preset");
    l2.add("superfast");
    l2.add("-tune");
    l2.add("zerolatency");              
    l2.add("-pass");
    l2.add(Integer.valueOf(pass).toString());
    l2.add("-vcodec");
    l2.add("libx264");
    l2.add("-b:v");
    l2.add("200k");
    l2.add("-bt");
    l2.add("50k");
    l2.add("-threads");
    l2.add("0");
    l2.add("-b_strategy");
    l2.add("1");
    if(pass ==1){
        l2.add("-an");
    } else {
        l2.add("-acodec");
        l2.add("copy");
    }
    l2.add("-f");
    l2.add("mp4");
    l2.add("-strict");
    l2.add("-2");
    l2.add("-passlogfile");
    l2.add(strngs[4]);

    if(pass ==1){
        l2.add("/dev/null");
    } else {
        l2.add(strngs[5]);
    }       
    return l2;
}
person Robert Rowntree    schedule 17.06.2013
comment
Привет. Спасибо за Ваш ответ. Через пару часов попробую ваш вариант. Не могли бы вы сказать мне, сколько кадров вы пытались закодировать и сколько времени потребовалось с помощью вышеуказанной команды? - person Paul; 17.06.2013
comment
около 4 кадров в секунду, я думаю, на Android ... нужно было бы около 25 кадров в секунду, чтобы даже сделать Android полезной платформой для мультиплексирования видео. - person Robert Rowntree; 17.06.2013
comment
или 10 сек. ввода звука с 2 изображениями и с -r 1/2 займет более 1 минуты на Android, а мультиплексирование на экземпляре Heroku в облаке - около 4 секунд. - person Robert Rowntree; 17.06.2013
comment
Привет, я пробовал ваш код, но кодирование никогда не заканчивается. Я думаю, что оно продолжает повторять кадры, которые у меня есть... во всяком случае, я не мог использовать точную команду, которую вы написали - я обновил свой вопрос командой, которую я использовал. многие параметры мне неизвестны... - person Paul; 18.06.2013
comment
-loop, поэтому он в цикле. - person Robert Rowntree; 18.06.2013
comment
я использовал -loop вместе с параметром продолжительности.. это другой способ обработки - person Robert Rowntree; 18.06.2013
comment
это было! сейчас на устройстве S3 это занимает около 3 секунд, но качество видео слишком низкое.. также кажется, что не все кадры в видео... у вас есть идеи, почему это происходит? - person Paul; 18.06.2013

Вы можете попробовать аппаратный кодировщик с recordvideo< /а>. Вы можете загрузить и скомпилировать инструменты командной строки stagefright, даже если вы не собираете всю систему. Вам понадобятся системные библиотеки (с вашего устройства) для связи. Полученный исполняемый файл преобразует буфер YUV в mp4. Вам все еще нужно преобразовать серию JPEG в один файл YUV. Я думаю, что это будет достаточно быстро с ffmpeg, но вы также можете использовать libjpeg-turbo для Android .

person Alex Cohn    schedule 17.07.2013
comment
Спасибо за ваш ответ и ваши ссылки. к сожалению, на данный момент мне нужно использовать ffmpeg... возможно, в будущем я попробую ваши предложения и сообщу вам о результатах. Благодарность - person Paul; 17.07.2013
comment
Как насчет компиляции ffmpeg для использования stagefright? Или использовать многопоточный x264? - person Alex Cohn; 17.07.2013
comment
Вы можете достичь 60 кадров VGA в секунду с аппаратным кодировщиком на S3 и 30 с 2 потоками для кодировщика sw. Я не знаю, сколько времени займет декодер ffmpeg Jpeg. - person Alex Cohn; 17.07.2013
comment
Мне нужно срочное, быстрое решение на данный момент. - person Paul; 17.07.2013