2:1 hack for HBO GO

Recently I’ve watched the Chernobyl miniseries on HBO GO. It had this somewhat unusual ratio of 2:1 and the site tried to squeeze it into 16:9 portion of the screen. As with 21:9, this resulted in windowboxing and a video smaller then it should be. Unfortunately my previous script could not fix it, but with a few tweaks it was easy enough to make a new one. Obviously, before I could enjoy the series, I had to write a new script.

The black rectangle represents a 21:9 screen, the red rectangle is the 16:9 area used by HBO GO and finally the blue rectangle is the area where a 2:1 video gets displayed. This means that if I want to use more of the screen for 2:1 video, I need to compensate for the difference between 2:1 video and the 16:9 area that HBO GO intends to use. So the question is, how much do I need to upscale the video.

(16/9) * x = 2/1

(16/9) * x = 2 | / (16/9)

x = 2 * (9/16)

x = 18/16

x = 112.5%

As before, I also need to offset the video to get rid of the upper black bar.

Let H be the height of the screen, h the height of 2:1 video squeezed into 16:9 area and b the height of a single black bar.

We know that to make the image fit the screen height, we need to multiply it by 18/16. So we are trying to inverse the downscaling operation that was already done to the video. This means that that the two heights are related by an inverse ratio.

h = (16/18) * H

The difference between those two heights is the area occupied by the black bars and since there are two of those, the height of a single black bar is half of this number.

b = (H – h) / 2

b = (H – (16/18) * H) / 2

b = H * (1 – (16/18)) * (1/2)

b = H * ((18/18) – (16/18)) * (1/2)

b = H * (2/18) * (1/2)

b = H * (1/9) * (1/2)

b = (1/18) * H | / H

b / H = 5.(5)%

This means we need to offset the image vertically by roughly 5.55%.

After changing the numbers in my old script, the new one looks like this:
javascript: (function(){ var video = document.body.querySelector('.video-js .vjs-tech'); if (video.getAttribute("style") == null) { video.setAttribute("style", "height: 112.5% !important; transform: translateY(-5.55%) !important;"); } else { video.removeAttribute("style"); } })();

As with the previous script, I recommend adding it to your browser as a bookmarklet. Just create a new bookmark, paste the code into the url/address field and click on it whenever you want to watch a 2:1 video on HBO GO and you have a screen that has ratio wider than 16:9 (in my case 21:9).

21:9 “hack” for HBO GO

Recently I decided to give HBO GO a try, because they had a movie available that I wanted to watch. As an owner of an ultrawide monitor, I was a little disappointed when I find out that the movie was in 16:9 (while even DVDs tend to be in 21:9 those days).

However the next movie I watched “Wreck-it Ralph”, aside from being pretty great, was actually in 21:9. However, a new problem emerged when watching. The aspect ratio might have been correct, but now I had to deal with windowboxing.

It appears HBO GO aims to deliver 16:9 content, so a 21:9 movie will be letterboxed (ie. black bars will be added to the video). Combined with the vertical black bars that occur when you display 16:9 content on 21:9 screen, we end up with a thick black box around the movie and not all of the screen being used for displaying it.

Thankfully I use HBO GO in a browser and the way a webpage is displayed can be easily adjusted.

The video player is styled to take all available space
width: 100%;
height: 100%;

If I were to increase the height of the video I could make it fit the width of the screen and hide horizontal black bars. So it’s time for some math.

I have a 3440×1440 monitor and a 16:9 1440p screen resolution would be 2560×1440.

I need to find out how much I need to increase the size of the video to make it fit the width of my screen.
2560 * x = 3440
x = 3440 / 2560
3440 / 2560 = 1.34375

If I increase the height to around 134% the video should fit the width of the screen, but the bottom of the video is now cropped, because the black bars have also increased in size. So now, I need to move the video up.

We can calculate the new height of the video.
1440 * 1.34375 = 1935

Check how it differs from the height of the screen (this is the amount of space the black bars take).
1935 – 1440 = 495

We need to offset the video by the height of a single black bar, so we divide it by 2.
495 / 2 = 247.5

If we were to offset the video by set amount of pixels, it would look wrong if window resolution wasn’t exactly 3440×1440 (ie. window mode or different screen resolution), so we translate it to percentage.
247.5 / 1935 = 0.1279…

Note, this is in relation to the new video height (1935) and not the original video height (1440).

So, I should be able to fix the windowboxing by adding following inline css to the video element.
height: 134.375% !important; transform: translateY(-12.79%) !important;

Adding this as inline css and using !important helps preventing some other style from overthrowing our change and sure enough, it works.

The only thing that’s left is adding some way to activate\deactivate this hack. Since we only want to apply it to some movies, adding it automatically to every page is a bad idea.

Another problem is that HBO GO appears to work like a single page application, so a user script (it generally runs once after you loaded a page) would require some extra work. Not to mention integrating the script with HBO GO ui would be a hassle.

Thankfully there is a simpler way. Some browsers allow the use of bookmarklet. Bookmarklets are basically javascript code placed in a bookmark instead of url. The “link” in a bookmarklet has to start with:
javascript:

A simple bookmarklet script for activating\deactivating the 21:9 hack, could look like this:
javascript: (function(){ var video = document.body.querySelector('.video-js .vjs-tech'); if (video.getAttribute("style") == null) { video.setAttribute("style", "height: 134.375% !important; transform: translateY(-12.79%) !important;"); } else { video.removeAttribute("style"); } })();

Note that this works with the version of HBO GO available in my country and might not necessarily work elsewhere (or might require slight changes). Also, in Firefox I can simply copy the bookmarklet code into a bookmark, but it might require some encoding in another browser.

I’d post a link to make adding the bookmarklet easier, but apparently WordPress doesn’t allow javascript in links, so you might need to do it the old fashioned way. Create a new empty bookmark and just copy the javascript code to the url field.

Signals, editor and factory pattern

I tried to remake my clone of Popcap’s Bookworm in Godot game engine. My JavaScript code was a mess and I didn’t want to write a whole game engine from scratch in JS, so I moved to Godot. Also the graphical editor appealed to me. My very much WIP Bookworm version is available here (currently it doesn’t even support Japanese and has an English dictionary instead).

Anyway, while working on the thing I learned something new. When my game was running I was getting a lot of errors, though they didn’t seem to break anything. I was using a factory scene for my different tile types and duplicating the tiles when needed. The tiles had signals connected to them in the editor and those signals turned out to be the source of the problem. Long story short, connecting the signals in code in the _ready function, while disconnecting them in the editor made all those weird errors go away.

Don’t use wildcard in UDF and Views

In SQL Server the * wildcard is useful feature when quickly putting together a query.

SELECT *
FROM MyTable

However there are certain situations where you should avoid using it. Namely you should not use it when you’re returning data from a user defined function or a view (and possibly procedures as well). The reason behind it, is that SQL Server stores what a view or function returns (even if you don’t explicitly define it). When you ALTER or CREATE a function, the format of the returned data is defined. Let’s say your UDF executes this query:

SELECT *
FROM Orders

And your Orders table contains following columns:

  • Id
  • CustomerId
  • OrderTotal
  • IsPaid

This function will obviously return all the rows in the Orders table and everything is fine. However a problem will arise when you decide to alter the structure of the Orders table. Let’s say we will insert an IsCnancelled column right before IsPaid. So the table will look like this:

  • Id
  • CustomerId
  • OrderTotal
  • IsCancelled
  • IsPaid

The data returned by the UDF will be missing the IsCancelled column, but that’s not all. The contents of the IsCancelled column, will be presented as the IsPaid column. Such an error could wreck havoc. If you ALTER the UDF (no changes are actually required), the structure of the returned data will be updated, but it’s better to avoid using the * wildcard altogether, than trying to manage this mess.

On the other hand, using wildcard in subqueries or CTE inside an UDF should be safe.

All this is probably obvious stuff to most people working with SQL Server and my example is very basic, but I had to fix problems caused by such use of the wildcard in the past and they can get ugly.

Rikaikyun 0.15

rikai1
After nearly a year without a major update I managed to motivate myself to push a number of improvements to Rikaikyun. The key one is speed. I found my app to be acting sluggish with files that were 500+KB in size. A single volume of a WEB novel is usually this big and while I can split the volume into chapters, managing this many files becomes annoying. That’s why I rewrote the way the text is presented. Previously all text was dumped into the web view, but that caused those speed issues. On the other hand, I noticed that the dictionary doesn’t affect the speed of the app much, even though it takes some 70MB of memory. So I figured that keeping only the visible text in the web view should make the app work faster and it actually worked (few MB files can be still a bit too clunky to use). This was a bit tricky to implement, but I’ll spare you the details. Let me just say that I kept the scrolling mechanism to keep things simple.

Another thing I did was improve the security of loading random html files. The previous release of Rikaikyun wasn’t 100% resistant to loading external JS or inline JS. The new version however, should strip any JS from loaded document, or at least prevent it from executing.

rikai2

Since many newer Android devices lack physical back button, I added an on-screen back button to various menus, to make the app easier to use on those devices.

As for the changes that are visible more easily, I added chapter positions to progress bar and navigation submenu. The navigation submenu allows you to jump chapters and also jump to specific position in the document.

As usual, the APK can be grabbed from here.

Rikaikyun Beta released

I reached the stage at which Rikaikyun appears to be fully usable (though I haven’t made a lot of tests), so I decided to release it to public (not that it was hidden from public before). You can grab the APK and source code from here. Note the APK will probably not work on anything less than Android 4.

screenshot

You can also test the app in Chrome using the device emulation mode (you have to run Chrome with the –allow-file-access-from-files flag on). For running the app in chrome there is also a special Chrome hack option that allows emulating pressing back button by going back in browsers history.

Disappearing objects

While working on Rikaikyun I came across this strange problem, after pushing one of my revisions I tried running my app on my target device (Onyx Boox T68 Lynx) and found out it no longer works (even though I had no problems running on Chrome and another Android device). Debugging Phonegap apps on a Lynx is a pain, because Phonegap Development App cannot be used there, so you have to probe blindly in hopes of finding what could be causing the problem.

My first finding was that one of my classes suddenly became undefined. I spare you the details of what I tried or not, but the source of the problem was mismatched letter case in the name of one of the JS files. Now, I’m smart enough not to reference JS files using wrong case, but as it happen, at one point in the project, the file had a different name (only the case was different). Given that I use Windows and store my project on GIT, I’m sure you can guess what went wrong… Anyway GIT didn’t notice the fact that I change the case of the file and when I finally did a merge it renamed my file to what I named it originally.

I guess when you use the file:/// protocol in Android browser you have to pay attention to the case in file names, because requests to those files does appear to be case sensitive.