简体   繁体   中英

What do I have to do to get the H.264 library to compress frames to 250Kb or under?

I'm using the H.264 library to compress a video frame by frame. It works, I can replay it back locally without any issue.

However, I need to send that video over the LAN and that LAN is rather busy already so I need to limit the size of each frame to a maximum of about 250Kb.

I use the following code to setup the parameters, but changing the bit rate values does not seem to have any effect on what the library does with the input frames:

x264_param_t param = {};
if(x264_param_default_preset(&param, "faster", nullptr) < 0)
{
    return -1;
}

param.i_csp = X264_CSP_I420;
param.i_width = 3840;
param.i_height = 2160;
param.i_keyint_max = static_cast<int>(f_frame_header.f_fps);
param.i_threads = X264_THREADS_AUTO;
param.b_vfr_input = 0;
param.b_repeat_headers = 1;
param.b_annexb = 1;

  // the following three parameters are the ones I tried to change with no results
  param.rc.i_bitrate = 100000;
  param.rc.i_vbv_max_bitrate = 100000;
  param.rc.i_vbv_buffer_size = 125000;

if(x264_param_apply_profile(&param, "high") < 0)
{
    return -1;
}

...enter loop reading frames and compressing them...

Changing the i_bitrate , i_vbv_max_bitrate and i_vbv_buffer_size parameters seems to have absolutely no effect on the size of the resulting frames. I still get some frames over 500Kb and in many even, rather large frames one after the other as the following sizes show:

20264
358875
218429
20728
25215
310230
36127
9077
29785
341541
222778
23542
21356
276772
25339
32459
421036
11179
6172
286070
193849

What I would need is the largest frame to be around 250,000 at its maximum. Now I understand that once in a while it go over a bit, but not 2×. That's just too much for my current available bandwidth.

What am I doing wrong in the parameters setup above?

I've seen this command line :

ffmpeg -i input -c:v libx264 -b:v 2M -maxrate 2M -bufsize 1M output.mp4

which would suggest that what I'm doing above should work (I tried all sorts of values including the ones one that command line). Yet the frame size does not really change between my runs.

I tried with a blur applied to each frame to see whether it work help. Yes. It did. The result is a movie which is 2.44 times smaller than the original.

To load each JPEG image from the original, I use ImageMagick++ (in C++), so I just do the following blur on each image:

image.blur(0.0, 5.0);

and that took about 10 hours total (without the blur the same processing took about 40 minutes) but it was worth it since in the end the compressed movie went from 1293272023 bytes to only 529556265 bytes (2.44218 times smaller). The blur added about 3.3 seconds of processing per frame and there are a little over 11,000 frames in the original.

Note: I used 5.0 for the blur because I have 4K images and although I can see a sharp difference when I look at one frame, when playing back the resulting movie, I don't notice the final blur. If you have smaller images, you probably want to use a smaller number. It looks like many people use a blur of just 0.05 and already have good results in compression ratios.

In C, use the BlurImage() function :

Image *BlurImage(const Image *image,const double radius,
                 const double sigma,ExceptionInfo *exception)

Here are some references about using a blur to further compress JPEG images as it helps eliminates sharp edges which do not compress well in the JPEG format (as sharp edge are not as natural):

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