I create lots of 4K 60fps 3D animations, and every frame of these animations are exported as separate PNG files to my disk drive. These PNG files use their own lossless compression method, but the file sizes are still quite large (a 30 second animation can take anywhere between 4 and 18 GB). I'm interested in alternative lossless compression formats to reduce the file sizes even further.
The reason I'm interested in lossless compression is because I create a LARGE variety of animations, and lossy algorithms are not always consistent in terms of visual fidelity (what doesn't create visible artifacts for one animation might for another).
Do you have good recommendations for general purpose lossless video codecs that can achieve superior performance to storing the PNG frames individually?
So far, I have attempted to use h.265 lossless using ffmpeg:
ffmpeg -r 60 -i out%04d.png -c:v libx265 -preset ultrafast -x265-params lossless=1 OUTPUT.mp4
But the result was a 15.4GB file when the original PNG files themselves only took up 5.77 GB in total. I assume this was because, for this particular animation, interframe compression was far worse than intraframe compression, but I don't really know.
I understand that this is highly dependent on the content I'm attempting to compress, but I'm just hoping that I can find something that's better than storing the frames individually.
For lossless archival of RGB inputs, I suggest you try x264's RGB encoder.
ffmpeg -framerate 60 -i out%04d.png -c:v libx264rgb -qp 0 OUTPUT.mp4
Related
So i'm tried to reduce video filesize by scale down video -vf 640:-2, but nothing changes. Scale down or up doesnt affect video filesize
I've read ffmpeg wiki about Scaling but it dont have any information about scale and filesize.
When i'm scale down images, filesize have big drop but for video, nothing changes
You can use -crf option to reduce final video size.
The range of the CRF scale is 0–51, where 0 is lossless (for 8 bit only, for 10 bit use -qp 0), 23 is the default, and 51 is worst quality possible.
-crf 23 (for default)
You have to use H.264 encoder. this will help almost all type of video. works batter in mp4 videos.
I’d like to convert a movie to a lossy JPEG 2000 sequence with FFmpeg using libopenjpeg. I found -compression_level to control the compression but I‘m looking for a kind of variable bitrate control like -crf. Is this possible?
I don't think J2K has any quality controls like that. CRF is not an FFmpeg thing, the actual encoders need to support it. libx264 or libx265 have it, but I don't know any image encoders that work like that.
I am wondering when I convert a .mp4 to .mkv using the following command if the quality changes.
ffmpeg -i in.mp4 out.mkv
The input file, in.mp4 has a file size of 297 megabytes, while the out.mkv file has a size of 249 megabytes, ~15% lower. Upon manual inspection, the resolution, video, and audio streams are the same before/after (as I would have expected given my (limited) knowledge of ffmpeg).
Is the 15% size decrease by simply converting to mkv actually not affect the quality of the video? If so this seems like a very reasonable way of freeing up some space on my computer.
The quality gets worse
This is due to generation loss because you are re-encoding the video and audio to lossy formats. But you may not notice the difference.
The output file size will vary depending on the input format, if it was encoded well or badly, your output format, and the settings you use.
MP4 to MKV without quality loss
You can just re-mux and avoid re-encoding by using stream copy mode:
ffmpeg -i input.mp4 -c copy output.mkv
You can think of it like a copy and paste. The video and audio is untouched and just put into a new container.
I am using ffmpeg to rotate videos 90 or 180 degrees in a Python script. It works great. But, I am curious as to why the output file would be a smaller amount of bytes than the input file.
Here are the commands I use:
180 degrees:
ffmpeg -i ./input.mp4 -preset veryslow -vf "transpose=2,transpose=2,format=yuv420p" -metadata:s:v rotate=0 -codec:v libx264 -codec:a copy ./output.mp4
90 degrees:
ffmpeg -i ./input.mp4 -vf "transpose=2" ./output.mp4
For example, a GoPro Hero 3 MP4 file was originally 2.0 GB. The resulting output file was 480.9 MB. Another GoPro file was 2.0 and its resulting file was 671.5 MB. Is this maybe because the GoPro files were 2.0 but contains empty space, sort of like how some NTFS filesystems make a minimal 4k file, even when there is less bytes in it?
If this isn't the GoPro Hero 3, how do I rotate the files 90 or 180 degrees but ensure the output file size is the same? Or, is data loss expected? Does the data loss have to do with the format?
Note that the quality of the video doesn't appear to be damaged, which is good. So, I am interested in learning more about why this is happening, then I can read the section of ffmpeg documentation that is relevant to this.
Thank you!
Bitrate is ignored from the start
ffmpeg fully decodes the input into uncompressed raw video and audio (except when stream copying – more about that below). The input format or bitrate does not matter: it does this for all formats. The encoder then works from these raw, decoded frames. See diagram.
H.264 vs H.264
Your input and output are both H.264. A format, such as H.264, is created by an encoder. Anyone can make an encoder. However, not all encoders are equal. Given the same input, the output from one H.264 encoder may have the same quality as an output from another H.264 encoder, but the bitrate may be several times smaller.
The GoPro H.264 encoder was made to work on a platform with limited hardware. That means bitrate (file size) is sacrificed for speed and quality. x264 is the ultimate H.264 encoder: nothing can beat its quality-to-bitrate ratio.
Rotate without re-encoding
You can stream copy (re-mux) and rotate at the same time. The rotation is handled by the metadata/sidedata:
ffmpeg -i input.mp4 -metadata:s:v rotate=90 -c copy output.mp4
Downside is your player/device may ignore the rotation, so you may have to physically rotate with filters which requires re-encoding, and therefore stream copy can't be used.
I had the same rotation issue once...
I fixed it by "resetting" the rotation instead...
ffmpeg ...... -metadata:s:v rotate="0" ......
Encoding with ffmpeg and libx264, are there presets or flags that will optimize decoding speed?
Right now it seems that videos transcoded with similar file sizes are decoded at very different speeds using Qtkit, and I was wondering whether there are options for encoding such that the decoding speed will be maximal.
There is --tune fastdecode in x264 (or -tune fastdecode if using ffmpeg) if you want optimize for decoding speed at the cost of quality/compression efficiency. In libx264 tune setting is available as one of the params for x264_param_default_preset.
I've used this in the past:
-b (to remove B Frame calculations)
-maxrate 8M (I find this is important because sometimes the averages have a large distribution in bitrate and so if you set 8M as an average, you may still find 15M peaks)
-tune fastdecode (already explained above)