I've tried to enode one still image at 25 fps with h.264(ffmpeg). WHy the codec produces DIFFERENT images?
This is my syntetic still image example:
ffmpeg -framerate 1 -r 25 -i ttest%.jpg -vcodec libx264 -crf 25 -pix_fmt yuv420p still_image.mp4
I've checked the result file with probe (and another software), and found that all images in the encoded sequnce is different!
I understand that h.264 is lossy encoder, and may be by default the algorithm compresses some MB in different way, but I want to produce file with all MB is B_skip or P_skip in all slices except the first IDR frame. Is it possible?
Currently I am using this command to convert
ffmpeg -i <srcfile> -vcodec libx264 -profile:v main -level 3.1 -preset slower -crf 18 -x264-params ref=4 -acodec copy -movflags +faststart <outfile>
to convert some dashcam footage for viewing on an iOS device.
The above command took about 30 min to complete on a 2017 Macbookpro with 16G of RAM.
I want to speed it. One thing I tried is to harness the GPU in the computer. Therefore I added the flag -c:v h264_videotoolbox
It sped up by a lot. I can complete the conversion in 1 min.
However, when I inspected the output, the GPU version suffers from banding and blurry.
Here is a screenshot. CPU version on the left and GPU version on the right.
To highlight the difference, here are the parts of the videos
Trees in reflections
corrugated iron sheet wall
Is there any switch that I can manipulate to make the GPU version clearer?
This is a simplistic H.264 encoder compared to x264, so you're not going to get the same quality per bitrate. h264_videotoolbox is optimized for speed and does not support -crf.
You can view some options specific to this encoder with ffmpeg -h encoder=h264_videotoolbox, but as they are probably already set to "auto" (I didn't confirm via source code and I don't have the hardware to try it) these additional options may not make much of a difference.
So you'll just have to increase the bitrate, such as with -b:v 8000k.
Or continue to use libx264 with a faster -preset.
I see the question's been answered and nearly two years ago. Jumping in for others who might stumble on the thread. I get great results with VideoToolbox as encoder, using either GPU or software to accelerate, depending which machine I am using.
As already mentioned, setting a constant bitrate, and adjusting it upward is key to producing a result that is nearly indistinguishable from a large source file. A constant bitrate is as effective as two-pass encoding for high-quality output, when paired with other key parameters, and is much quicker than two-pass.
May seem counter-intuitive, but a computer running on all threads, full throttle, to encode a video won't give you best results. Several researchers have demonstrated that quality actually goes down if all cpu threads are engaged in encoding; better to use fewer threads and even throttle ffmpeg with a 3rd party app (encoding does not slow down significantly, in my experience). So limit threads on newer multithread desktops and laptops.
Common practice for target bitrates (seen on Netflix, Amazon) vary with resolution, naturally: at least 5,000kbps for 1080p; 3,500 for 720p. For a noticeable improvement in video quality, the encoder bitrate should be set to at least 1.5 times those common practice bitrates: ie, 7,500 for 1080p, 5,250 for 720p. Similarly for 4K GoPros or dash cams.
Often I work with large movie files from my bluray library, and create slimmed-down versions that are 1/3 to 1/2 the size of the original (20G original gives way to a file of 8-10GB with no perceptible loss of quality. Also: framerate. Maintaining the same framerate from source to slimmed-down file is essential, so that parameter is important. Framerate is either 24fps, 25fps, or 30fps for theatrical film, European tv, and North American tv, respectively. (Except in transferring film to a tv screen, 24fps becomes 23.976fps, in most cases.) Of course 60fps is common for GoPro-like cameras, but here 30fps would be a reasonable choice.
It is this control of framerate and bitrate the keeps ffmpeg in check, and gives you predictable, repeatable results. Not an errant, gigantic file that is larger than the one you may have started with.
I work on a Mac, so there may be slight differences on the command line, and here I use VideoToolbox as software encoder, but a typical command reads:
ffmpeg -loglevel error -stats -i source.video -map 0:0 -filter:v fps\=24000/1001 -c:v h264_videotoolbox -b:v 8500k -profile 3 -level 41 -coder cabac -threads 4 -allow_sw:v 1 -map 0:1 -c:a:0 copy -disposition:a:0 default -map 0:6 -c:s:0 copy -disposition:s:0 0 -metadata:g title\=“If you want file title in the metadata, goes here” -default_mode passthrough ‘outfile.mkv’
-loglevel error (to troubleshoot errors)
-stats (provides progess status in terminal window)
-i infile (source video to transcode)
-map 0:0 (specify each stream in the original to map to output)
-filter:v fps\=24000/1001 (framerate of 23.976, like source)
-c:v h264_videotoolbox (encoder)
-b:v (set bitrate, here I chose 8500k)
-profile 3 -level 41 (h264 profile high, level 4.1)
-coder cabac (cabac coder chosen)
-threads 4 (limit of 4 cpu threads, of 8 on this laptop)
-allow_sw:v 1 (using VideoToolbox software encoding for accleration; GPU is not enabled)
-map 0:1 -c:a:0 copy -disposition:a:0 default (copies audio stream over, unchanged, as default audio)
-map 0:6 -c:s:0 copy -disposition:s:0 0 (copies subtitle stream over, not as default ... ie, will play subtitles automatically)
-metadata:g (global metadata, you can reflect filename in metadata)
-default_mode passthrough (allow audio w/o further processing)
outfile (NOTE: no dash precedes filename/path. Chose mkv format to
hold my multiple streams; mp4 or other formats work just fine ... as
long as contents are appropriate for format.)
In addition of llogan's answer I'd recommend set 'realtime' property to zero (this can increase quality in motion scenes)
As llogan says, bitrate option is good parameter in this situation.
ffmpeg -i input.mov -c:v h264_videotoolbox -b:v {bitrate} -c:a aac output.mp4
if you want to set 1000kb/s bitrate, command is like this
ffmpeg -i input.mov -c:v h264_videotoolbox -b:v 1000k -c:a aac output.mp4
I am streaming(live chat) with FFmpeg using the following parameters.
ffmpeg -f dshow -rtbufsize 100M -i video="device":audio="device" \
-c:v libx264 -crf 30 -preset ultrafast -tune zerolatency \
-c:a aac -f mpegts udp://127.0.0.1:1234
Unexpectedly, when CRF is lowered from 30 to 20, step-by-step. The stream quality decreases dramatically. When the CRF is about 20, sudden changes in the picture (like a head movement), seems to make the image green, gray or very distorted. I tried using CRF 30, and the problems seems to be gone. Why is this happening ?
I don't think it is a bandwidth issue given that I am on localhost. Also I didn't change anything based on I-frames.
Edit: I checked the file sizes given CRF 20 and CRF 30 on libx265.
10 Second video.
CRF 20: 1.7M
CRF 30: 350kb
Is 1.7M really bad for a 10 second stream that localhost or any other live streaming sevice can't handle ?
I don't know what the resolution is, but it seems to be a performance issue for encoding.
CRF=20 can also be used up to MAX 20 Mbps as a criterion of 720p.
As a suggestion, do not use CRF but specify proper bitrates according to resolution.
720p -> 2.5Mbps
1080p -> 4Mbps
And 'dshow' is not very fast capture either. You have to take it into consideration.
I recommand DX10's swap-chain. It's super fast capturer.
When I transcode video to H265 with following command, I get a bitrate about 600K and the quality is almost the same as the original.
ffmpeg -i data2.mp4 -c:v libx265 -c:a copy d2.mp4
However when I use the hevc_nvenc, I get a very high bitrate (about 2M), I need to have a bitrate as low as possible and keeping almost the same quality.
ffmpeg -i data2.mp4 -c:v hevc_nvenc -c:a copy d3.mp4
It works if I specify the output bitrate, but I want to know how to figure out the proper bitrate?
There is no such thing as "proper bitrate". You get to choose the bitrate. if you don't, the encoder will choose on for you. In this case, you are using two different encoders, so you get different bitrates. You can change this by adding -b:v option to ffmpeg.
But that's probably not what you want. You probably want to use a constant quality factor by setting -crf to a value between 0 (Great quality large file) to 51 (bad quality small file)
Note that hevc_nvenc will almost produce larger files than libx265 at a given quality because it not as efficient as an encoder.
I have a series of JPEG images named 0000.jpg 0001.jpg 0002.jpg...
I used the following command to turn these into a slideshow video, each frame playing for 1 second.
ffmpeg -framerate 1 -i %04d.jpg -c:v libx264 -vf fps=1 -pix_fmt yuv420p out.mp4
This works fine except that the resulting video is 6x larger than what I get if I encode the exact same frames at normal framerate (e.g. 25 FPS)
I'm looking for a way to effectively get the same efficient encoding as when encoding 25fps but with each frame showing for 1 second.
H.264 is a video codec that is inter-coded i.e. frames rely on other frames in order to get decoded. What x264, a H.264 encoder, does, at a basic level, is observe the changes in the picture content between frames and then save only that difference.
In the CRF ratecontrol mode, which is what's used by default when no rate control mode is expressly specified (-b:v, -crf, -x264opts qp), x264 is sensitive to framerate. When given an input at 25 fps, each frame is displayed for 40 milliseconds, so the viewer isn't that sensitive to image quality of each individual frame, so x264 compresses it quite a bit. But when that input is encoded at 1 fps, each output frame will be on display for a whole second, so x264 is much less aggressive with its compression.
The workaround is to encode at 25 fps and then remux at the lower fps.
#1
ffmpeg -framerate 25 -i %04d.jpg -c:v libx264 -pix_fmt yuv420p out.264
#2 Using mp4box*, part of GPAC, remux with the lower rate:
mp4box -add out.264:fps=1 -new out.mp4
*normally, this would be possible using ffmpeg, but it does not correctly remux H.264 raw streams with out-of-order frame storage i.e. those with B-frames.