Thursday, May 26, 2016

Reverse engineering Pubvn apps for fun and... larger-screen-fun

It's Friday night and the wifeTM wanted to watch Games of Thrones on the TV (via Chromecast). Should be easy right? We have lots of apps installed for exactly this purpose: Netflix, HBO Now, Flix, etc. None of them worked though...

  • Netflix just doesn't have HBO contents like GoT.
  • HBO Now works but it requires a US proxy to watch and there is no way to tell the Chromecast to go through a proxy.
  • Flix, a promising local app, good with TV streaming but not series.
So we had to settle to use HBO Now and Google Chrome's cast tab feature to have it on the big screen. A complicated setup, and slow. The casting was broken a few times during the episode, probably because of wifi interferences. This problem needs some engineering!

Proxy Those Apps

First order of business would be proxy their apps to catch all network requests. I used Charles with their iOS app. At first I thought it would be tricky if they use https or certificate pinning but it turned out everything runs through http. After a few taps on the apps, the flow looks something like this:

  1. `filmlist` api for search
  2. `filmdetail` to get a movie's episodes
  3. Finally use `filmmedia` for the mp4 url
After a few hours or so, I had gotten the mp4 casting on my TV. Success? Not yet.

Subtitles

Hmm, subtitles are important, we really need those (especially for GoT). Chromecast supports subtitles in WebVTT format (which is good) but apparently Pubvn only has SRT. Also, the subtitles url is protected with some weird authentication hashing. Almost gave up, I tried to proxy their Android app and found out that this app uses a slightly different api. Best of all, Android subtitles don't require authentication, they have some custom made encoding instead.

New plan:
  • Switch to use Android api endpoints
  • Decompile their apk to get the SRT decoder.
  • Put that decoder on Heroku with WebVTT converter
Complicated but now we have working mp4 and WebVTT urls. For some reason, Chromecast failed to play with subtitles turned on though...

CORS

Another couple hours passed by until I found out that both urls must have CORS headers. Probably the video player needs more data from the movie stream when it renders subtitles, I don't know.

It's easy to add those headers for the subtitles, we just need to update the Heroku app. But for the movie itself... It is hard, we don't control Pubvn servers so there is no ways to add those CORS headers (I asked them, no answer so far). I guess we can run a CORS proxy and play the movie from there? Just to be safe, let route the srt through that proxy too (so Pubvn servers will see our requests all from one IP).

Hah! Now we have movie with subtitles fully working on Chromecast! I have to keep 2 servers running though: the Heroku app and the CORS proxy.

Source: elitedaily.com
Repositories if you are interested: