Skip to main content

ffmpeg - Convert AVI (Xvid) to MP4 (H.264) keeping the same quality


I want to compress an AVI file to MP4 using an h.264 codec. I could not get the same quality. How can I compress it?


Original Video:


Original Video Screen:



FFmpeg console output (ffmpeg -i input.avi):


FFmpeg version SVN-r26402, Copyright (c) 2000-2011 the FFmpeg developers
built on Dec 28 2012 10:03:40 with gcc 4.4.6 20120305 (Red Hat 4.4.6-4)
configuration: --enable-shared --enable-gpl --enable-version3 --enable-nonfree --enable-pthreads --enable-x11grab --enable-libopencore-amrnb --enable-libopenc ore-amrwb --enable-libdc1394 --enable-libfaac --enable-libmp3lame --enable-libop enjpeg --enable-libspeex --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libxvid --enable-zlib --enable-filter=drawtext
libavutil 50.36. 0 / 50.36. 0
libavcore 0.16. 1 / 0.16. 1
libavcodec 52.108. 0 / 52.108. 0
libavformat 52.93. 0 / 52.93. 0
libavdevice 52. 2. 3 / 52. 2. 3
libavfilter 1.74. 0 / 1.74. 0
libswscale 0.12. 0 / 0.12. 0
[mpeg4 @ 0x626b50] Invalid and inefficient vfw-avi packed B frames detected
Input #0, avi, from 'input.avi':
Metadata:
encoder : VirtualDubMod 1.5.10.2 (build 2542/release)
Duration: 01:32:38.13, start: 0.000000, bitrate: 2094 kb/s
Stream #0.0: Video: mpeg4, yuv420p, 720x304 [PAR 1:1 DAR 45:19], 23.98 tbr, 23.98 tbn, 23.98 tbc
Stream #0.1: Audio: ac3, 44100 Hz, 5.1, s16, 384 kb/s
At least one output file must be specified

Test 1


FFmpeg command:


ffmpeg -i input.avi -vcodec libx264 -vpre lossless_slow -crf 25 -acodec libfaac -threads 0 -t 60 1.mp4

Test 1 Screen:



FFmpeg console output (ffmpeg -i 1.mp4)


    FFmpeg version SVN-r26402, Copyright (c) 2000-2011 the FFmpeg developers
built on Dec 28 2012 10:03:40 with gcc 4.4.6 20120305 (Red Hat 4.4.6-4)
configuration: --enable-shared --enable-gpl --enable-version3 --enable-nonfree --enable-pthreads --enable-x11grab --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libdc1394 --enable-libfaac --enable-libmp3lame --enable-libopenjpeg --enable-libspeex --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libxvid --enable-zlib --enable-filter=drawtext
libavutil 50.36. 0 / 50.36. 0
libavcore 0.16. 1 / 0.16. 1
libavcodec 52.108. 0 / 52.108. 0
libavformat 52.93. 0 / 52.93. 0
libavdevice 52. 2. 3 / 52. 2. 3
libavfilter 1.74. 0 / 1.74. 0
libswscale 0.12. 0 / 0.12. 0
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '1.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 1970-01-01 00:00:00
encoder : Lavf52.93.0
Duration: 00:01:00.01, start: 0.000000, bitrate: 618 kb/s
Stream #0.0(und): Video: h264, yuv420p, 720x304 [PAR 1:1 DAR 45:19], 437 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc
Metadata:
creation_time : 1970-01-01 00:00:00
Stream #0.1(und): Audio: aac, 44100 Hz, 5.1, s16, 176 kb/s
Metadata:
creation_time : 1970-01-01 00:00:00
At least one output file must be specified

Test 2


FFmpeg command:


ffmpeg -y -i input.avi -pass 1 -vcodec libx264 -vpre slow -b 2000k -threads 0 -t 60 -f mp4 -an -y /dev/null
ffmpeg -y -i input.avi -pass 2 -vcodec libx264 -vpre slow -b 2000k -threads 0 -t 60 -acodec libfaac -ab 128k -ac 2 2.mp4

Test 2 Screen:



FFmpeg console output (ffmpeg -i 2.mp4)


FFmpeg version SVN-r26402, Copyright (c) 2000-2011 the FFmpeg developers
built on Dec 28 2012 10:03:40 with gcc 4.4.6 20120305 (Red Hat 4.4.6-4)
configuration: --enable-shared --enable-gpl --enable-version3 --enable-nonfree --enable-pthreads --enable-x11grab --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libdc1394 --enable-libfaac --enable-libmp3lame --enable-libopenjpeg --enable-libspeex --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libxvid --enable-zlib --enable-filter=drawtext
libavutil 50.36. 0 / 50.36. 0
libavcore 0.16. 1 / 0.16. 1
libavcodec 52.108. 0 / 52.108. 0
libavformat 52.93. 0 / 52.93. 0
libavdevice 52. 2. 3 / 52. 2. 3
libavfilter 1.74. 0 / 1.74. 0
libswscale 0.12. 0 / 0.12. 0
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '2.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 1970-01-01 00:00:00
encoder : Lavf52.93.0
Duration: 00:01:00.01, start: 0.000000, bitrate: 1097 kb/s
Stream #0.0(und): Video: h264, yuv420p, 720x304 [PAR 1:1 DAR 45:19], 1028 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc
Metadata:
creation_time : 1970-01-01 00:00:00
Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 63 kb/s
Metadata:
creation_time : 1970-01-01 00:00:00
At least one output file must be specified

Answer



First of all, install a more recent version of FFmpeg – grab a static build from the download page.


The use of vpre presets (which is a way to set default values for ffmpeg settings, not encoder settings) is not really necessary; you usually want to use the -preset options defined by the encoders.


The reasons you get low output quality are the following, for your two cases respectively:




  1. In the first case you use crf 25, a Constant Rate Factor that's going to give you worse quality than the default for the x264 encoder (which is 23). The CRF controls the quality. Try setting a lower CRF, maybe 20, 18, etc. Here, lower means better quality, but it'll increase the file size. A change of 6 in the CRF gives you twice/half the original average bitrate, roughly speaking.


    You'll have to set a lower CRF because of the generation loss. You're encoding something that was already encoded, so you're again throwing away visual information. That's never good, but if you have to, you're going to have to set a higher quality so as not to remove too much information from the input video.




  2. In the second case you're trying to set a constant bit rate of 2 MBit/s. Your input video roughly has the same bit rate. Now, x264 delivers much better visual quality than an MPEG-4 Visual encoder for the same bitrate, but due to the generation loss, again, you might want to use an even higher bitrate than the original – otherwise you'll end up compressing away too much information.


    Furthermore, constant bitrate encoding might result in some passages looking good, but other parts of the video looking worse. If you don't let the encoder freely choose the amount of bits it wants to spend on something, you're going to sacrifice quality at the expense of knowing the target file size.


    x264 does have a constant bit rate mode, but it's considered inferior to the other encoding methods. Actually, two-pass encoding isn't meant to target optimal quality, so scratch that.




That all being said, try something along the following:


ffmpeg -i input.avi -c:v libx264 -crf 19 -preset slow -c:a libfdk_aac -b:a 192k -ac 2 out.mp4

If libfdk_aac is not available, use this instead:


ffmpeg -i input.avi -c:v libx264 -crf 19 -preset slow -c:a aac -b:a 192k -ac 2 out.mp4

The main quality control knob will be your CRF setting. Experiment with that and use a lower value if you need better quality.


You can also choose the veryslow preset, which will give you better compression, but the encoding will obviously take longer.


If you can't manage to get a decent quality file at a reasonable file size, then you're out of luck. Better keep the original file as-is, without re-encoding. There's no magic "keeping the same quality" tool when you're compressing something that's already compressed.


Comments

Popular Posts

How do I transmit a single hexadecimal value serial data in PuTTY using an Alt code?

I am trying to sent a specific hexadecimal value across a serial COM port using PuTTY. Specifically, I want to send the hex codes 9C, B6, FC, and 8B. I have looked up the Alt codes for these and they are 156, 182, 252, and 139 respectively. However, whenever I input the Alt codes, a preceding hex value of C2 is sent before 9C, B6, and 8B so the values that are sent are C2 9C, C2 B6, and C2 8B. The value for FC is changed to C3 FC. Why are these values being placed before the hex value and why is FC being changed altogether? To me, it seems like there is a problem internally converting the Alt code to hex. Is there a way to directly input hex values without using Alt codes in PuTTY? Answer What you're seeing is just ordinary text character set conversion. As far as PuTTY is concerned, you are typing (and reading) text , not raw binary data, therefore it has to convert the text to bytes in whatever configured character set before sending it over the wire. In other words, when y...

linux - Extract/save a mail attachment using bash

Using normal bash tools (ie, built-ins or commonly-available command-line tools), is it possible, and how to extract/save attachments on emails? For example, say I have a nightly report which arrives via email but is a zip archive of several log files. I want to save all those zips into a backup directory. How would I accomplish that? Answer If you're aiming for portability, beware that there are several different versions of mail(1) and mailx(1) . There's a POSIX mailx command, but with very few requirements. And none of the implementations I have seem to parse attachments anyway. You might have the mpack package . Its munpack command saves all parts of a MIME message into separate files, then all you have to do is save the interesting parts and clean up the rest. There's also metamail . An equivalent of munpack is metamail -wy .

performance - Single Threaded Qaud Core v.s Hyper-Threading Dual Core

Let's say we have two CPUs, One is Quad Core 3.2 Ghz with 4 Cores, and We have a Dual Core 3.2 Ghz with 2 Cores with 2 threads in each Core (Hyper-Threading). My assumption as a programmer will be, the 4 cores 4 threads should perform faster than 2 cores 4 threads since the second CPU needs to switch between threads in order to emulate 4 cores while the first one doesn't need to perform such switching as each core can perform independently and individually. I want to confirm that my assumption is true, if not please explain why one is better than the other. Answer I do believe thats true - since hyper threading does share some elements - specifically the main execution resources, you'll be able to run 4 full threads at once, rather than waiting for those resources to be freed up. The point of HT is to get better performance with a smaller use of die area - your quad core would generally be a bigger chip - say almost twice as large, than a non HT dual core chip, while a HT...

freeze - How do I stop windows 8.1 from freezing when the screen locks

This happens to me on a regular basis if I leave the computer for upwards of 10 minutes. It didnt do so at first but started after a couple of days. This is possibly related to further windows updates although nothing seems to tie in obviously when looking at my update history. I have to hold the power button in to power off. If the screens have switched off aswell they wont come back on, if they haven't I see the login picture and can move the mouse pointer but nothing happens and no combination of keyboard mashes or mouse clicks lets me see the login prompt. In the event log (type event viewer into the start menu) under system before every Critical problem (me powering down the machine without restarting) I get distributedCOM errors talking about this guid: "The server {BF6C1E47-86EC-4194-9CE5-13C15DCB2001} did not register with DCOM within the required timeout." I also get the same error for this 1B1F472E-3221-4826-97DB-2C2324D389AE. This seems to be a common theme and...