简体   繁体   中英

How to encode jpeg images to H264 very fast (transform images to video)

I have 30 JPEG images (.jpg) at a resolution of 480 x 640. Each image takes aboout 20KB (all of them takes about 600KB).

I am using FFmpeg command to encode these images into a video in H264 format.

I need this to be done very fast - about 1 second.

Using the classic command:

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

takes about 90 seconds .

After adding -preset ultrafast :

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

the encoding takes about 15 seconds which is much better, but still not enough

I've tried others parameters also, like:

-profile:v baseline

-qscale:v

-b:v 1000k

-crf 24

but the encoding time does not fall below 10 seconds.

I'm not familiar with FFmpeg commands nor with the parameters I need to use, and this is the reason I post here this question.

The video quality needs to be ok, doesn't need to be perfect.

As a note: I am running these commands in an Android application where I have the ffmpeg executable, using an ProcessBuilder.

Reply1 (to Robert Rowntree):

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;

How about getting rid of -r 1/5? It speeded up my encoding.

IMO - ffmpeg on android is still all software ( no gpu or Hardware accel ). You could try looking thru libstagefright/ffmpeg combined questions . At any rate, if u are interest in fast, you should find a hardware accel solution on android. Otherwise ffmpeg on the constrained platform ( battery life, low power CPU ) is gonna be quite slow in compare to any other platform.

also , see accepted answer here and this too

I gave up on android due to lack of speed and settled for a cloud instance to upload media to and then todo the ffmpeg encode there before download to the android device. Would be interest to hear whether u get fast result on android.

BTW, i used the 2-pass H264 expression u see below before giving up on android for the encode.

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;
}

You could try hardware encoder with recordvideo . You can download and compile the stagefright command-line tools even if you don't build the whole system. You will need the system libraries (from your device) to link. The resulting executable will convert YUV buffer into mp4. You still need to convert the series of JPEGs into a single YUV file. I think it will be fast enough with ffmpeg, but you can also use libjpeg-turbo for android .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM