One of the perennial complaints about MTGO streams and recordings is how difficult the cards are to read. And it's no surprise — pretty much any program would struggle with the requirements that Magic imposes. It has to combine sometimes obscene amounts of text with an eye-wateringly small rendering area of less than a dozen square centimeters.
This problem is exacerbated by the fact that most MTGO streamers record at the standard resolution of 1080p. There are simply not enough pixels available to legibly render a font in such a small area at such a low resolution. Here is an example of what I mean:
Left: 1080p Channel Fireball recording Middle: 4K recording, smallest hand size
Right: 4K recording, standard hand size
This is not meant to pick on Channel Fireball. Their content is impeccable, but much of it is hard to read unless you know exactly what is going on. To be clear, it's not just Channel Fireball; even professional content put out by Wizards of the Coast suffers from similar issues. Unless you follow Standard, I suspect you'll have a hard time telling me what these cards from the recent Magic Online Championship do:
Is 4K really that big of a deal?
YouTube displays recordings in a variety of resolutions, from 144p all the way up to 2160p (4K). It may not seem as if there is a big difference between 1080p and 2160p, but remember that the “1080” in “1080p” only refers to the number of vertical pixels. In terms of overall pixels, there is a pretty vast gulf between 1080p and 4K:
% of 1080p
As you can see, 4K gives you 400% more pixels to render legible text in the exact same amount of screen space. That's why the Deathrite Shaman on the right can clearly display its entire text box despite taking up the exact same amount of space as the Deathrite Shaman on the left.
Cranking OBS to 11
Before I began recording, I simply assumed that 1080p recordings were a matter of inertia. Everybody recorded in 1080p, so what was the point in trying to bump the resolution up to 4K? After all, 4K means more CPU usage, larger files, and slower downloads. Why bother when nobody else was doing it?
It turns out my assumptions were way, way wrong. It turns out that it's actually really difficult to record in 4K while playing MTGO. My machine isn't top-of-the-line, but it's nothing to scoff at: a 2013 Macbook Pro with quad 2.6GHz i7 CPUs and 16GB of memory.
I assumed that all I'd have to do was tell OBS to record at the native “Retina” resolution (3360x2100) and I could go on my merry way. What happened when I did that?
PAIN. Telling OBS to record at 4K in real time took so much CPU that my machine was rendered completely useless. I couldn't actually play MTGO, because each click took over 15 seconds to register.
I then tried telling OBS to use one of its faster CPU settings (ultrafast), but the image quality came out very poor, with lots of noise and other encoding artifacts:
Path to 4K
This process left with a whole new respect and understanding for the professionals who do these recordings. It's simply impossible to have:
High quality 4K recordings
Low CPU usage
Managably-sized video files that you can upload directly to YouTube
I realized I'd have to compromise and do my recordings in two steps:
Record with at high quality and low CPU usage, but large video sizes
Re-encode post-recording to generate high-quality videos with low file sizes
This is certainly more work, and takes a lot more time. But it comes with some benefits:
The recording takes very little CPU usage, instead of causing the typical OBS lag
The re-encoding takes 8-12 hours, but the settings used result in YouTube quickly generating all the other resolutions post-upload
My screen's resolution (3360x2100) is actually lower than 4K (3840x2160), but the re-encoding lets me upscale to 4K
The Technical Details
So how did I do it? Here are my OBS video settings:
Recording Format: mp4
Rescale Output: unchecked (native resolution)
Rate Control: CRF
Keyframe Interval: 0 (auto)
CPU Usage Preset: superfast
Variable Framerate (VFR): checked
These settings generate very high quality recordings that average about 1GB for every ten minutes of recording. Lowering the CRF value leads to higher quality files at the cost of increased CPU usage, and 12 was the highest quality my machine could handle. If you find these settings too aggressive, bump CRF to a higher number.
Once I am finished recording, I have an automated job that upscales and re-encodes with ffmpeg, using the optimal YouTube video settings:
RTFM… just kidding! There is no manual for the CORS (Cross-Origin Resource Sharing) specification. I really had you going there, didn't I?
Don't worry, it's not your fault. After all, here is what a Google search provides:
Each of these sites contains a wealth of information about CORS, and each of them is far over the head of your average developer. Given the frequent questions that I receive from confused and frightened developers trying to understand these documents, I thought it might be helpful to boil CORS down into a couple simple examples.
Q. If I have static content that depends neither upon cookies nor user-specific URLs and/or parameters and I want to share my site's content with the web, what should I do?
Q. Well, that is great and all. But what if I want to let a foreign website interact with my site, as a logged-in user, allowing them to do anything they could as if they were on my site? I swear that I understand the risks that this entails and that I really trust this other site to not make any security mistakes such as falling victim to a cross-site scripting (XSS) attack.
Access-Control-Allow-Credentials means that the user's cookies (such as their session cookies) will be sent with the request
Access-Control-Allow-Origin is the whitelisted origin sent in the Origin header by the browser and not * nor blindly reflected
And these optional headers mean the following:
Access-Control-Allow-Methods is the list of allowed HTTP methods beyond GET, HEAD, and POST
Access-Control-Expose-Headers allows example.com to read the contents of the X-Poop-Emoji header (💩, obviously)
Access-Control-Max-Age allows example.com to make these requests without preflights for the next 300 seconds
Again, please be aware that you need to be very careful with Access-Control-Allow-Credentials. Even if you think you're safe by only allowing idempotent methods such as GET, that might be enough to steal an anti-CSRF token and let attackers go to town with CSRF attacks.
If you need additional documentation about other features in CORS, I highly recommend the frustratingly hard to locate CORS for Developers document by Brad Hill.
But that was six months ago. With the Mozilla Observatory being publicly released almost two months ago, I was curious as to whether significant improvement had been made around the internet. After all, in those two months, the Observatory has scanned approximately 1.3M sites, totalling over 2.5M scans.
With that in mind, I ran a new scan of the Alexa Top 1M at the end of October, and here is what I found:
I'll admit, I was a bit taken aback by the overall improvement across the top million sites, especially as some of these security technologies are almost a decade old.
When we did our initial scan of the top million six months ago, a stunning 97.6% of websites were given a failing grade from the Observatory. Have those results changed since then, given the improvements above?
While a decrease of 1.5% in failing grades might seem like only a small improvement, the latest Observatory scan contained 962,011 successful scans. With each percentage point representing nearly ten thousand sites, a drop from 97.6% to 96.09% represents approximately fifteen thousand top websites making significant improvements in their security.
I'm excited for the possibility of seeing further improvements as additional surveys are completed. Please share the Mozilla Observatory and help to make the internet a safer and more secure place for everyone!
Allows 'unsafe-inline' in neither script-src nor style-src
Allows 'unsafe-inline' in style-src only
Amongst sites that set cookies
Disallows foreign origins from reading the domain's contents within user's context
Redirects from HTTP to HTTPS on the same domain, which allows HSTS to be set
Redirects from HTTP to HTTPS, regardless of the final domain
Today was a huge leap forward for humankind, for it marks the day that Let's Encrypt now supports internationalized domain names. That means that you can now get certs with non-ASCII characters in them, which will be huge in helping Let's Encrypt improve HTTPS uptake in countries that use languages outside of the traditional ASCII character set.
How did I do this? First, you must transform unicode (in this case, the 👉👁 emoji) into what is called punycode. Punycode is simply a method of representing unicode characters in ASCII, the only characters supported by the domain name system (DNS). There are many ways to do it, including a simple tool at punycoder.com. For 👉👁, its punycode encoding is xn--mp8hpa.
I simply setup DNS for xn--mp8hpa.pokeinthe.io, updated my nginx configuration to include xn--mp8hpa.pokeinthe.io in its server_name parameter, and requested a cert using my favorite Let's Encrypt client (lego):
root@pokeinthe:~# /opt/go/bin/lego -d pokeinthe.io -d www.pokeinthe.io -d 'xn--mp8hpa.pokeinthe.io' --email 'email@example.com' --accept-tos -k ec384 --webroot /var/www/pokeinthe.io --path '/etc/lego' run
2016/10/21 17:30:02 [INFO][pokeinthe.io, www.pokeinthe.io, xn--ls8h.pokeinthe.io] acme: Obtaining bundled SAN certificate2016/10/21 17:30:03 [INFO][pokeinthe.io] acme: Authorization already valid; skipping challenge2016/10/21 17:30:03 [INFO][www.pokeinthe.io] acme: Authorization already valid; skipping challenge2016/10/21 17:30:03 [INFO][xn--ls8h.pokeinthe.io] acme: Could not find solver for: tls-sni-012016/10/21 17:30:03 [INFO][xn--ls8h.pokeinthe.io] acme: Trying to solve HTTP-012016/10/21 17:30:04 [INFO][xn--ls8h.pokeinthe.io] The server validated our request2016/10/21 17:30:04 [INFO][pokeinthe.io, www.pokeinthe.io, xn--ls8h.pokeinthe.io] acme: Validations succeeded; requesting certificates2016/10/21 17:30:04 [INFO] acme: Requesting issuer cert from https://acme-v01.api.letsencrypt.org/acme/issuer-cert2016/10/21 17:30:04 [INFO][pokeinthe.io] Server responded with a certificate.