Browsing: Uncategorized

My Attempts at Comparing Compression Between ffmpeg’s x264, x265 and av1 Encoders

This post assumes you have a basic understanding of how encoding a video works, and what the popular codecs are. There are many great guides on this if you want to learn about it in detail. In short, CRF compresses a video based on visual quality, rather than targeting a specific bitrate/file size. x264 is an older incredibly widely supported codec for viewing video. x265 is the newer version of x264, and is supported by any modern video player. AV1 is a codec that was announced in 2015, and had commercial hardware support released to the public in June 2022. It is the new hotness to x264’s old reliable.

I recently came across the desire to compare various compression levels for the two most popular video codecs to the most popular up and coming one. I’m a simple guy, there’s a couple of good research papers for this specific topic, so my test setup is not going be rigorous. At best, it will be representative. I wanted to see just what a difference a codec can make on a video file size using comparable quality levels. On to the setup!

The source file is a 4k x264 I had laying around with a runtime of 1 hour and 33 minutes and a bitrate of 95.5mbp. I mostly chose it due to the fact that it was filmed, and that it was similar enough to a 4k security camera output that i could reasonably expect similar or smaller (since security cameras have a lot less dynamic motion) bitrates for security footage archival purposes. If the results work out well, I may end up grabbing an arc video card, so I am not worried about encode speed for these tests.

The source video file is being converted from from 4k to 1080p. The goal isn’t to see how small I can get the file. The goal is to see how the three results compare to each other. To that end, I will also be excluding audio and subtitles from the conversion.

This website says that x264 is considered visually lossless at 18 crf, and x265 is visually lossless at 25. The ffmpeg page for av1 says that a crf of 23 matches the visual quality of x264 at 19. Since i’m looking for a quick and dirty comparison, this is good enough, especially since various sources disagree on what crf equals what quality level anyways.

Here’s my x264 ffmpeg command:

ffmpeg.exe -i source.2160p.mkv
-map 0:v:0
-map -0:a -map -0:s -map_metadata -1
-c:v libx264
-preset slower
-vf scale=w=1920:-2
-crf 18
dest.1080p.x264.mkv

Here’s my x265 ffmpeg command:

ffmpeg -i source.2160p.mkv
-map 0:v:0
-map -0:a -map -0:s -map_metadata -1
-c:v libx265
-preset slower
-vf scale=w=1920:-2
-crf 25
dest.1080p.x265.mkv

And finally, here’s my av1 command:

ffmpeg -i source.2160p.mkv
-map 0:v:0
-map -0:a -map -0:s -map_metadata -1
-c:v libsvtav1
-preset 3
-vf scale=w=1920:-2
-crf 23
dest.1080p.av1.mkv

On to the results! after an overnight encode session, or two, I ended up with the following sizes;
* the x264 encode ended up being 10.8 gigabytes with an average bitrate of 16,666kbps.
* the x265 encode ended up being 1.08 gigabytes with an average bitrate of 1,656kbps.
* the av2 encode ended up being 1.6 gigabytes with an average bitrate of 2,458kbps.

Hold on, the av1 codec is supposed to be more efficient than the other two. What gives? A relatively long check with FFMetrics later, and we have results. Here’s a great article explaining the numbers further, but in short, they check various metrics against the source material to try and get a number that matches the visual fidelity loss that encoding a video gives.

PSNR does a little math to see how much has changed from the source and approximates the human perception of reconstruction quality. The score is typically between 30 and 50, with the higher number being better.
SSIM compares brightness, contrast and structure to the original source. It’s values are between 0 and 1, with 1 being the most similar to the source video.
VMAF attempts to predicts subjective video quality based on a reference and a distorted video sequence. It is a newer algorithm developed by Netflix with the University of Southern California, University of Nantes IPI/LS2N lab, and The University of Texas at Austin Laboratory for Image and Video Engineering (LIVE). The values for it are also considered to be better the higher the number is.

All of this to say, my crf values were off, by a technically noticeable amount and I need to redo my work. The av1 file is considered best quality by all the digital algorithms I have access to, and needs to be reduced in order to match the other two codecs. But this brings me to a new problem. What is a good target range for each of these values to be considered “visually lossless”? Instead of trusting that the numbers are right, as they clearly aren’t entirely, I need to first define what my levels of bad, good enough, and visually lossless actually are. I also need to learn what a badly compressed video looks like so I can detect the less obvious but still there compression artifacts. Finally, I need to choose a new source video, because dang, these took way to long to encode on my poor computer.

Fair warning: Just like kerning, once you learn what bad encodes look like, you lose your ability to watch what most people consider to be good enough encodes without hating the video quality. If you enjoy youtube or netflix a lot, and don’t mind their compression, you are a prime candidate for getting mad at their encoding choices if you continue reading.

So, first, my new video is the 2012 blender open movie project, Tears of Steel. I grabbed the 4k source file, which is 12 minutes, 14 seconds long, 3840 pixels wide, and has an average bitrate of 73,227kbps. Instead of using the promised visually lossless crf values this time, I’m going to use the worst possible crf value to get an idea of what a badly compressed version of this video looks like. My new crf values will be 63, 51, and 51, for av1, x265, and x264 respectively.

The resulting file sizes were actually pretty amazing. The x264 file was 15.7MB, the x265 file was 8.38MB and the av1 file was 16.1MB. Essentially, the file size dropped to practically nothing for all of them. However, the x264 and x265 files were both unwatchable. You would have gained more edetail from a lossless 240p encode than what you got from these encodes. The real star was the av1 encode. Yes, it had a lot of blur around the edges of movement, and basically all of the details were removed and smeared into gradients of color, but the video itself was still very much understandable. Because the videos are so small, I feel comfortable sharing the results here without using a third party video host.

To pixel peep picture quality, I ran the following command on all the videos;

ffmpeg -i source.video -vf fps=1/60 codec%04d.png

The end results was twelve images from each video, demonstrating the various compression methods used. x264 turns everything into blocks, particularly around movement. x265 turns everything into blocks and triangles, also particularly around movement. av1 smooths out colors to cartoon levels, and also turns movements into blocks, but to a much lesser extent than the other two codecs.

In short, av1 does a very good job of compressing the video using methods that are better at hiding the compression to the human eye than the old x264/5 methods. Now that we know what extreme compression looks like, my next goal is to decide on a crf level that does a ‘good enough’ job of hiding the compression. For me, that means if I pixel peep i’ll find compression artifacts, but by and large, they won’t be obvious when just watching the video. Considering how well av1 has done so far, I won’t be surprised if its crf is a lot higher than the other two when i stop trying for better quality. I’ll encode by steps of 3 crf values, and try and pick the value that makes the most subjective sense to me.

My choices were as follows:

crfav1 KBx265 KBx264 KB
18419,261 632,079685,217 – visually lossless
21352,337390,358 – visually lossless411,439
24301,517250,426263,524 – good enough
27245,685165,079 – good enough176,919
30205,008110,062122,458
33168,19273,52886,899
36139,379 – visually lossless48,51663,214
39116,09631,67047,161
4297,365 – good enough20,63635,801
4581,80513,59827,484
4869,0449,72620,823
5158,3168,586 – worst possible16,120 – worst possible
5448,681
5739,113
6029,062
6316,533 – worst possible

av1 is tricky because it’s compression adds border pixellation, but it also slowly removes details from object. At it’s worst, this turns people into clay, and the borders into a janky mess. However, at more reasonable levels it’s actually pretty hard to notice the clay conversion effect. I personally noted compression artifacts while watching the video for av1 at a crf of 45, so I consider an av1 crf of 42 to be good enough for things like security camera footage, my grandmother’s house, or my tablet. Not good for archival, but damn good for less important things. The good enough av1 file size was 97Mb.

The x264 and x265 compression artifacts are a lot easier to find compared to av1. Check the borders of moving objects for pixellation. If it’s there, you can see the artifacts. I was unable to notice artifacts for x264 without pixel peeping at a crf level of 24. The file size for the video at that level was 263MB.

I was unable to notice artifacts for x265 without pixel peeping at the crf level of 27. The file size for the video at that level was 165MB.

Here is a slideshow of screenshots from my ‘good enough’ choices. You may notice compression in them, but with my eyes, while just playing the video, it wasn’t really something I could pick out easily, if at all.

So then, what do I consider to be visually lossless? From the results I got, I feel safe in agreeing with ffmpeg’s documentation regarding x264’s crf choice of 18 (685MB). You’ll probably want to go lower than the recommended 25 with x265, by at least three though. I couldn’t see any artifacts playing the crf 27 x265 video, but 25 is too close to that for me to confidently say it is visually lossless. You’re probably better off going with crf 21 (390MB) or 22 to consider it visually lossless.

For av1, I feel confident in saying that, even if you pixel peep, and compare it to the original frame by frame, you won’t find compression artifacts at the crf level of 36 which was just 139MB in size. Here’s some screenshots to compare the original to my visually lossless choices. Feel free to check my conclusions yourself.

Don’t feel like trusting my eyes for it? Let’s see what FFMetrics says about my choices;

That’s a lot better than my first attempt. However, just to be certain, I’m going to drop the CRF level until it reaches parity with the VAMF test.

Dang, that’s a much different crf level than my novice eyes are able to see. Maybe a better comparison method is needed? I recently found out about imgsli, which is a better image comparison tool than what ive been doing up until now. Let’s keep it simple, my visually lossless choice vs VAMF’s visually lossless number.

crfav1 KBx265 KBx264 KB
18419,261 632,079685,217 – visually lossless
21352,337390,358 – visually lossless411,439
24301,517 – VAMF visually lossless250,426263,524 – good enough
27245,685165,079 – good enough176,919
30205,008110,062122,458
33168,19273,52886,899
36139,379 – My visually lossless48,51663,214
39116,09631,67047,161
4297,365 – good enough20,63635,801
4581,80513,59827,484
4869,0449,72620,823
5158,3168,586 – worst possible16,120 – worst possible
5448,681
5739,113
6029,062
6316,533 – worst possible

After comparing them, I still stand by my choice. If you pixel peep the crf 36 and compare it to the the crf 24 results, you can see extremely minor differences in her jacket, but overall, nothing of value is actually lost in translation.

I had a lot of fun playing around with these comparisons. Hopefully, you found it interesting too.

{ Comments are closed }

I commissioned an art piece

It was by Amirai of amarai.net. The theme I asked for was Avatar bending, with a focus on how powerful bending is compared to the actual people doing it. And also blue. I like blue.

Amirai - commission - downscaled

 

Quite frankly, I absolutely love the result and wholly recommend the artist to anyone interested in paying for some quality art.

{ Comments are closed }

WPA Password Verification Tool

I was going through my computer projects and realised that I never shared this one on my website. It’s a tool, coded in C++ that checks a text file for WPA/WPA2 password compatibility. It is most helpful in network security applications / pentesting when you have a password list and aren’t sure just how much of the list is actually a legitimate password.

For example, we have a text file with these contents:

Good Password
good password

Good Password 1234567890
good password 1234567890

GoodPassword
goodpassword

BadPass
badpass
badpa55

badpas™
BadPas™
B3dPas™

This is a bad password because the character length is way above the maximum limit of 63 characters, and WPA won’t allow such horrible things to exist in the first place anyways.

If we run the tool on it, we get these results:

A picture of the tool in action

 

Finally, here is the source code of the project. It should be able to be compiled with just about any compiler on any operating system.

#include <iostream>
#include <fstream>
#include <string>

int help(char *argv[]) {
std::cout << “Usage: ” << argv[0] << ” <PasswordFile> [Options]” << std::endl;
std::cout << ”  Options:” << std::endl;
std::cout << ”    -wpa  Verify password list using WPA Rules (WPA uses same rules as WPA2)” << std::endl;
//std::cout << ”    -clean    Automatically delete invalid passwords from file” << std::endl;
std::cout << ”    -goodlist Print all valid passwords” << std::endl;
std::cout << ”    -badlist  Print all invalid passwords” << std::endl;
std::cout << ”  Example:” << std::endl;
std::cout << ”    ” << argv[0] << ” passwordlist.txt -wpa -badlist” << std::endl;

return(1);
}

int does_exist(char *filetouse) {
//first check to see if the cfg file exists
FILE * pFile;
if(pFile = fopen (filetouse,”r”)) {
//the file exists
return(1);
} else {
//the file doesnt exist
return(0);
}
}

int verify(int argc, char *argv[]) {
//variables for later usage
//booleans for user options
bool wpa = false;
//bool clean = false;
bool goodlist = false;
bool badlist = false;
//strings for file reading
std::string password;
std::ifstream infile;
//strings for password statistics
int numberoflines = 0;
int numberoftolong = 0;
int numberoftoshort = 0;
int numberofbadchar = 0;
int numberofgood = 0;
int numberofempty = 0;

const char *filetouse = argv[1];

//check all the options
for (int i = 0; i < argc; i++) {
//options are -wpa -clean -goodlist -badlist
std::string options[4] = {“-wpa”,”-clean”,”-goodlist”,”-badlist”};
if(argv[i] == options[0]) {
wpa = true;
}
/*if(argv[i] == options[1]) {
clean = true;
}*/
if(argv[i] == options[2]) {
goodlist = true;
}
if(argv[i] == options[3]) {
badlist = true;
}
}

//read the file line by line and check to see if the passwords are right
infile.open(filetouse); //open the user file
while(getline(infile, password)) { //while not the end of the file
//getline(infile,password); //read the current line to std::string password

//count the lines in the password field
numberoflines += 1;

//check password
if(wpa == true) { //if checking WPA Rules
if(password == “”) { //empty line
//skip empty lines
numberofempty += 1;
} else if(password.size() > 63) {
//password is to big to be used
if(badlist == true) {
std::cout << password << std::endl;
}
numberoftolong += 1;
} else if(password.size() < 8) {
//password is to small to be used
if(badlist == true) {
std::cout << password << std::endl;
}
numberoftoshort += 1;
} else if (password.find_first_not_of(“!\”#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ “) != std::string::npos) {
//password contains a bad character
if(badlist == true) {
std::cout << password << std::endl;
}
numberofbadchar += 1;
} else {
if(goodlist == true) {
std::cout << password << std::endl;
}
numberofgood += 1;
}
}
}
infile.close();

std::cout << “Checked ” << numberoflines << ” passwords.” << std::endl;
std::cout << ”  ” << numberofempty << ” lines contained no text” << std::endl;
std::cout << ”  ” << numberoftoshort << ” lines were to short” << std::endl;
std::cout << ”  ” << numberoftolong << ” lines were to long” << std::endl;
std::cout << ”  ” << numberofbadchar << ” lines contained illegal characters” << std::endl;
std::cout << ”  ” << numberofgood << ” lines contained good passwords” << std::endl;

return(0);
}

int main(int argc, char *argv[]) {
if(argc <= 1){ //not enough options so help is shown
if(help(argv)) {
std::cout << “Fatal error. Quitting program.” << std::endl;
return(1);
} //else program is working fine
} else { //plenty of options, better check to see if they are the right ones
if(argv[1] == std::string(“help”)) {//display help
if(!help(argv)) {
std::cout << “Fatal error. Quitting program.” << std::endl;
return(1);
} //else program is working fine
} else {
if(does_exist(argv[1])){
verify(argc, argv);
} else {
std::cout << “Invalid file” << std::endl;
}
}
}
}

 

{ Comments are closed }

How I Explain Bitcoin

On a group of tropical island there are three native tribes each with their own chief and tribesmen. The first island tribe produces fruit and other agricultural foods. The second tribe is able to provide animals as well as meat. The third tribe provides cloth and small kitchen appliances.

Rather than fight and war over these essentials, the three tribe leaders have a meeting to decide the best way to trade their products. One tribe leader says that the best way is to trade in equal measures of weight. This would not work because the cloth and small kitchen appliances tribe would not be able to provide enough weight to get enough things of value.

The second tribe leader suggested they have a monthly trade of equal use between each other. One tribe supplies enough of their item to the other two tribes to last the month. While this would work between the hunters and the farmers, it would not work between the cloth and kitchen appliance tribe because kitchen appliances tend to last longer than meat and corn.

The third tribe leader suggests they use a form of currency. Thus far this is the most agreeable method, but they have a hard time picking a good item to use as money. Gold is too rare, and it was hard for them to make something easy to trade but hard to duplicate.

Then one of them has another idea. Why not go to the mainland and mine large stones to use as money? They would be hard to get, and everyone would agree to use them as trade items. The other two agree on this and the tribes finish their meeting.

The three tribes are happy to spare a few tribesmen to go and mine large stones to use as currency from the mainland, and since they are hard to get, nobody has any issue with gaining to many stones to quickly. However, moving these stones between the islands is a huge pain and a hassle to do. So rather than moving them every time someone buys a a cow or small kitchen appliance, they just decide to say that the stone in a certain spot belongs to this one guy.
This works out well for them. The tribes all agree that each stone has it’s own owner, and that the stone can change hands just by telling the other chief about the exchange. The stone never actually moves, but the trade is easily made, and all the tribes know about it.

On one particular mining trip, the boat carrying the stone and the tribesman gets caught in a storm. The tribesmen survive, but they are forced to drop the stone in the ocean. When they come back and tell the other tribes, they all agree that even though the stone is at the bottom of the ocean, the tribesmen still earned it, and it can still be used as currency. Bitcoins are like the stones. They have no real value, other than what we agree on. There is no real benefit from mining them alone, but they are usable nonetheless. Everyone has a record of who owns what bitcoin, and this record is called the block chain, or history of transfers. There are people who can mine more bitcoins, but it is a huge effort, and not always worth it.

{ Comments are closed }

SMBC Comic Challenge

So, on one of my favorite web comics I read this. The comic is about a an application a person created. The application, dubbed “Conception Connection” takes your birthday, and tells you what events may have aroused you parents when they conceived you. It makes for a great little joke at the end.

Now here is where I come in. At the end of the comic there is a red dot. If you mouse over this dot you will see the text “50 internet points to whoever makes it!”. Being challenged thus, I could not refuse and I created this. It is one of the things I am more proud of, because not only does it work, it looks good doing it. Needless to say, I am very happy with the way it turned out.

You can see the source code for the main script over here, highlighted and looking pretty. Once it has your birthday, it goes over to On This Day and takes the events they have so wonderfully made available for us. It then parses the correct html and makes it available similar to the way shown in the comic. However, the script has to go through about forty different pages looking for events that mach the date correctly, so it takes a lot of bandwidth.

That is why I emailed the owners of On This Day, and asked permission to leave it up and make available for everyone else. To my utter delight, they replied and said it was perfectly fine as long as I put a link to their website on it. Here’s the proof.

I hope you guys enjoy messing with my new toy, I know it was a lot of fun making it. I also know it’s been a little while since I posted anything worthwhile, but I do have other project ideas percolating in my head, one of which I have already started on.  Until then, I wish you all a good morning.

{ Comments are closed }

Site Issues

Hey guys, guess what happened?

 

I don’t know either. I think what happened to my site was the host (which I would still recommend) stopped my site from taking to much processor on their shared hosting. I understand. If I had a server, I wouldn’t want anyone taking more then his fair share either.

 

I think the processor hogging was caused by somebody stealing my WordPress password, or to many spam bots. whatever, I changed my passwords and added some security plugins, so it should be okay.

{ Comments are closed }

Interesting Recent Doings

Hey guys, sorry it has taken me so long to make another post or update anything, but its getting close to the end of the school year so I have been fairly busy. Anyways, I figured I needed to give you guys some info on what I’ve been doing lately, or some of the stuff that I have been involved in.

Recently (for a while actually), I have been working with a company called ‘Kanyon‘, and they do (mostly) java software development. I found them through their (java) autotyper, and we hit it off. The java autotyper isn’t open source, but it is free  and it has an almost completely different feature set from my autotyper. We are also working three other projects at Kanyon. If just for the autotyper that can run on any pc with java, you should go check them out.

I have also been working on a project with another guy online (we started it ourselves) called IntrepidZ. Basically it is a Open Source zombie survival game based on the project OctaForge. We have been getting our story for it all set up and have been working on some basic map work for it. If you are any sort of game designer (mapping, graphics design, audiophile, etc) then we would love to have you.

So that’s it. go check out Kanyon and see what you think of the autotyper, and if you can come and help us out with IntrepidZ.

{ Comments are closed }

Linux Autotyper 1.1 Released

Alrighty guys! I have finished the latest and greatest version of my Linux autotyper! Some of the main changes are to the menus, and to the OSD. The OSD now has more info for you, and i made the menus a little better. I also added a suffix / prefix form. All the info is in the readme.

I added a countdown for the OSD, and you can now stop / pause / play the text sending with it. (This removes the need for start/stop function keys.)

As for the suffix / prefix form, It lets you add some text to the end and beginning of the text you send. Some games require you to press enter to type the text, and then enter again to send it. This form (Window?) allows you to do that easily.

Anyway, here is the download link:

//sourceforge.net/projects/rsautosayer/files/Linux/1.1/

There is also a detailed install file with instructions for installing the Linux autotyper.

{ 1 Comment }

Installing / Running The Linux Autotyper

It was recently brought to my attention that I do not have clear instructions for installing the linux autotyper. Well, this post fixes that. So without further adieu, the instructions.

 

1: First, you need gambas2 installed. I may have a script fixing this later, but not right now. To install gambas2:

1a: Open the terminal by pressing “ctrl” and “Shift” and “t” on your keyboard at the same time.

2: Enter this code in the terminal (command prompt for you new-to-linux people)
sudo apt-get install gambas2

You may or may not have to press ‘y’ to confirm that you want to have gambas2 on your system.

3: Download the latest version of the linux autotyper by clicking this link:
Download here.

4: Extract the downloaded zip file to your desktop.
5: Browse to the extracted folder on your desktop, and open it.
6: Open the folder called “Executable”

7: there are two files, DaGeek247s_Autotyper,gambas, and readme.txt.
Make DaGeek247s_Autotyper.gambas executable.

{ Comments are closed }