An Apple TV case study: How we stayed ahead of the curve, and what we learnt along the way
Earlier this year when Apple shared our PLUS7 app as an example of excellence to a global audience in their keynote address, it was the culmination of an engaging journey for the engineering team.
When Apple announced the 4th generation Apple TV, we knew it would be a perfect fit for expanding our PLUS7 offering. The Apple TV’s simple yet elegant experience is great for designing in a way that allows users to get straight to the content they want.
Building upon our knowledge of iOS and existing Apple frameworks, the process to develop a tvOS app was fast and really enabled our engineers to push the envelope in terms of redefining the PLUS7 viewing experience on a larger screen.
With Swift still evolving fairly heavily, choosing to go with it is not without some risk and overhead. On evaluation, we decided that it was mature enough to use in a production application and that it would be the way forward for us. Although we could have reused Objective-C code from our iOS implementation, we further decided to start from scratch and our own code in the tvOS build is 100% Swift. We now believe this decision was a good one; even our test builds were remarkably stable and there are much fewer lines of code than its iOS counterpart. Additionally, we can now use our arguably better Swift code in future versions of our iOS releases.
We initially had a prototype version of the app which was built in spare time and had no input from the design team. Ultimately, it was this version that was iterated on as the build progressed. One of the main issues we encountered was 3rd party SDKs not being tvOS or bitcode compatible. With a bit of prodding, we were able to resolve most of these, with the large exception of the SDK we use for video advertising.
On iOS and Android we use Google’s IMA SDK for video advertising, which is not compatible with tvOS at this time. Obviously, launching PLUS7 for Apple TV without video advertising is not a viable strategy for our business. So we decided to implement the VAST spec ourselves, in Swift. We had a look at some (old) open source VAST implementations which unfortunately turned out not to be suitable. At first glance a VAST implementation looks fairly straightforward.
However, it turns out that it’s much more complicated than at first glance. A video contains “cuepoints”, which indicate when advertising slots are to be played. There are three types of ad sets; pre-rolls (played before a stream), mid-rolls (several per video, in the middle of the stream) and post-rolls (played after the stream). Each cuepoint maps to a “pod” of ads. A pod is made up of a number of ads. So the first preroll might contain one 15 second ad. The first mid-roll pod may contain 4 ads of various lengths (between 15 and 60 seconds), the next one 5 ads of various lengths and so on.
When the video starts, we make one query which returns each element in each pod. However, each ad is a recursive ad call to an ad server which you have to keep querying until you get an actual creative to play. The first ad server may not have the content, but will defer to another ad server, and so on. Additionally, each ad server that is traversed through will add its own tracking URLs for each event that may occur during playback, for example each quartile that is played, play, pause, stop etc events. Further, it’s possible that following a particular path down ad servers may result in an infinite loop (!), or a playback error, in which case specific rules apply.
It is vital that the implementation of the VAST specification behaves correctly, as our business revenue depends on it. Most of the time spent on development for our 1.0 release went into this effort.
Playing content along with video ads (which are separate video streams) while providing a seamless experience to the users is not that straightforward. Each video ad is fetched ahead of time, stored in a list and passed to the video controller provided by tvOS API. The content is paused and resumed after each ad sequence in a different controller. Seeking forward over one or more “cuepoints” means that we have to play the last set of ads in a pod and so on: the user might get to the post rolls too if they are patient enough.
As much as we can, we fetch required data ahead of time. As soon as we have enough information to play a preroll, we do, and then go and do the rest of the requests for specific ads so that users aren’t waiting for this to happen every time an ad has to play.
The Apple TV experience has some unique features due to the nature of the remote. Our first iteration had multiple tabs of grid views, and a master/detail view. It worked, but had the obvious drawback of having to excessively scroll vertically to simply navigate around. After feedback (and using the app ourselves), we simplified the navigation dramatically and created multiple horizontal scrolling collection views on the main screen, and a “Search” screen for quickly filtering for known content.
Furthermore, we were honoured to be featured on the screen during Tim Cook’s recent keynote:
– Richard Nelson, Max Bhuiyan, Shri Baichwal, Razvan Balazs
Originally published at careers.yahoo.com.au.