-2

I am recording frames (screen buffer) as NumPy arrays during the game which runs on the resolution of "400x225". Each frame array is a size of 270.1 kB.

After saving those frames, I create an mp4 file with the following bash command (The game runs in 35 FPS (frames/second)):

ffmpeg -r 35 -f image2 -i frame%05d.png -vcodec libx264 -crf 1 video.mp4

Then I have used a tool to generate a CSV file of frame data from the video created with the command above. The output is here below. The weird this is that, if we sum those first 35 frames (video was recorded with "-r 35" parameter because game runs in 35 FPS), we get approximately 18k kbit.

18k kbit/sec bitrate is super high for a 400x225 video. What am I doing wrong while generating the video? I appreciate any help, thanks!

enter image description here

bbasaran
  • 364
  • 3
  • 15
  • 2
    Why `-crf 1`? `-crf 0` is lossless, which makes **huge** files. `-crf 18` or so is lossy, but "visually lossless". Use the highest value that provides an acceptable quality. – llogan Feb 04 '21 at 23:20
  • I will use the output csv to train my machine learning model. I thought that losing quality would affect my model performance but there is no other way I guess. I wouldn't imagine crf 1 could give this high results so I thought there is another thing wrong. I wonder something: Do the parameters "crf" and "-b:v" end up in the same point? I mean if I increase the "crf", I see the kbps of the video decreases. Instead of using "crf", if I pass "-b:v 500k" let's say, would this also affect in the same way? – bbasaran Feb 05 '21 at 11:01
  • 1
    `-crf` and `-b:v` are two different methods of "rate control", or in other words they determine how bits are allocated and therefore control the quality and output file size. They are mutually exclusive, so if you use both options one will be ignored. To over silmplify: `-crf` lets you set a quality, but with no guarantee on file size, while `-b:v` allows you determine the file size, but not a specific quality. If you are concerned about quality, why not just give it the original PNG files? `ffmpeg -framerate 35 -i frame%05d.png -c copy output.mkv` Or do you have file size restriction? – llogan Feb 05 '21 at 19:00
  • 1
    More info about `-crf` at [FFmpeg Wiki: H.264](https://trac.ffmpeg.org/wiki/Encode/H.264). – llogan Feb 05 '21 at 19:10
  • "-crf lets you set a quality, but with no guarantee on file size, while -b:v allows you determine the file size, but not a specific quality." I couldn't understand this part clearly. I just tested both options separately to see their effects. Let's say, my goal is to have 640kbps. As far as I understood, I can either use "-b:v 640k", or "-crf 35" (just an assumption, like I tried 35 and see the resulting video is 640kbps). So what is the difference between using these commands then? – bbasaran Feb 05 '21 at 22:56
  • I was concerned about the quality at the beginning but "-crf 1" gave me unrealistic results. I'd like my video to be approximately 640kbps because its resolution is "400x225". I am using now in this way: ffmpeg -r 35 -f image2 -i frame%05d.png -vcodec libx264 -b:v 640k video.mp4 I pass "-r 35" because of the video fps, and "-b:v 640k" together. It is a valid usage, isn't it? because with the former one, I say: "my video is recorded with 35 frame per sec", and with the latter one I say: "encode it according to 640kbps". – bbasaran Feb 05 '21 at 23:03
  • 1
    What is it that you are trying to achieve? It appears this discussion may become a back and forth of many comments about explaining x264 rate control methods without an actual, concrete problem to address. If you tell us what exactly you want to do we can give you an appropriate command. – llogan Feb 05 '21 at 23:39
  • I'm sorry if I made you confused. I have a set of png files (frames of screen buffer) that were saved during a gameplay. The game runs on 35 FPS, which means I have 35 pngs for each second. I am trying to merge them to create a video with approximately 640kbps bitrate. I am using "ffmpeg -r 35 -f image2 -i frame%05d.png -vcodec libx264 -b:v 640k video.mp4" now, and it works. I just confused with your second comment. I wonder if it is ok to pass both "-r 35" and "-b:v 640k" together. – bbasaran Feb 06 '21 at 01:03
  • 1
    Yes, you can use both "-r 35" and "-b:v 640k" together. Although I don't know where you came up with 640k (why not choose a certain quality and let the encoder choose bitrate?). 1-pass with -b:v is not accurate, not the best quality (since it has to guess), and applies the same bitrate to everything, even if it doesn't need it. If you absolutely require a certain bitrate (why?), then use 2-passes as shown in [FFmpeg Wiki: H.264](https://trac.ffmpeg.org/wiki/Encode/H.264). Otherwise, just use -crf like 98% of the other users. – llogan Feb 06 '21 at 18:09
  • Thank you for your detailed, helpful answers! Upon your advice, I've decided to use crf 24, which provides me a certain quality with minimum size. – bbasaran Feb 08 '21 at 11:16

1 Answers1

1

Why is the output file size so big?

-crf allows you to set a specific quality. x264 will then apply the appropriate number of bits to achieve the desired quality. You're using -crf 1 which is almost lossless. This requires a huge amount of bits. The CRF scale is logarithmic from 0 to 51. 0 is lossless, ~18 is visually lossless, 23 is default, 51 is highest value and worst quality. So -crf 1 is going to be many times bigger than -crf 18 even if you can't visually tell a difference.

Which -crf value should I use?

Use the highest -crf value that provides an acceptable quality unless you have specific needs or if a lossless output is required.

See FFmpeg Wiki: H.264 for more info and examples.

llogan
  • 121,796
  • 28
  • 232
  • 243