5

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;
Paul
  • 3,812
  • 10
  • 50
  • 73

3 Answers3

0

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

av501
  • 6,645
  • 2
  • 23
  • 34
  • Yes, seems that I do not need first -r, because it it used to force the frame rate of the input file (valid for raw formats only) and I have jpecg files. – Paul Jun 17 '13 at 23:16
  • I'm not sure how to use the second r (because I need to specify a fps for the putput file) in order to have 5 frames / second. I've used 1/02 but seems that not all frames are included in the video and I do not know why... do you have any ideea why this is hapenning ? – Paul Jun 17 '13 at 23:17
  • Doesn't -r 5 give you 5 frames per second using all input frames? – av501 Jun 18 '13 at 07:32
0

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;
}
Community
  • 1
  • 1
Robert Rowntree
  • 6,230
  • 2
  • 24
  • 43
  • Hi. Thanks for your answer. I'm going to try your version in couple of hours. Could you please tell me how many frames you've tried to encode and time needed with the above command? – Paul Jun 17 '13 at 15:19
  • about 4 FPS i think on android... would need to be up around 25 FPS to even make android worthwhile platform for muxing videos. – Robert Rowntree Jun 17 '13 at 16:28
  • or 10 sec. of sound input with 2 pics and with -r 1/2 would take over 1 minute on android while about 4 seconds to mux on Heroku instance on the cloud. – Robert Rowntree Jun 17 '13 at 16:31
  • Hi, I've tried your code but the encoding never ends.. I think it keeps repeat the frames I have...anyway I could not use the exact command you wrote - I've updated my question with the command I've used. many of the parameters are unknown for me... – Paul Jun 17 '13 at 22:16
  • "-loop" that would be why its in a loop. – Robert Rowntree Jun 17 '13 at 22:50
  • i used -loop along with a "duration" parm.. its diff way of processing – Robert Rowntree Jun 17 '13 at 22:51
  • that was it! it takes now about 3 seconds on a S3 device, but the video quality is too lower.. also seems that not all the frames are in video...do you have any ideea why this is happening ? – Paul Jun 17 '13 at 23:15
0

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.

Community
  • 1
  • 1
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • Thanks for your reply and your links. unfortunately for the moment I need to use ffmpeg...maybe in the future I'll give a try with your suggestions and let u know about results. thanks – Paul Jul 17 '13 at 16:59
  • What about compiling ffmpeg to use stagefright? Or to use a multithreaded x264? – Alex Cohn Jul 17 '13 at 17:22
  • You can reach 60 VGA frames per second with hardware encoder on S3, and 30 with 2 threads for sw encoder. I don't know how much time will ffmpeg Jpeg decoder take. – Alex Cohn Jul 17 '13 at 17:34
  • I need a urgent, fast solution for the moment. – Paul Jul 17 '13 at 17:41