Rss

A Roku SDK Brain-Dump

So it’s been a month since I taught my half-day Roku SDK class at CodeMash 2014 (sorry for the lack of blogging… client project in crunch mode). I’ve long since posted my slides, with the sample code in my Dropbox public folder.

Jeff Kelly's setup for Roku class at CodeMash

But since my most-popular blogs have always been these brain-dump things — Core Audio, OpenAL, and In-App Purchase — I figured I’d roll back to that old format.

Also, if you don’t already have a Roku, get one through my Amazon affiliate link and thereby incentivize me to blog more. Thanks.

Commence unordered list…

  • The entirety of the SDK is profoundly different from the large, deep stacks of desktops and smartphones. In fact, you don’t need to actually download anything to start programming your Roku. There are no libraries to compile against, nor an emulator to test your stuff on. You write source files in plaintext, zip them up with resources (images), and upload them directly to your Roku box. It feels like it was meant for command-line warriors, though there is also an Eclipse plug-in available if that suits you (Jeff Kelley loaded this up during the class and was pretty happy with it).

  • The maximum size of a Roku channel is 2MB. Not a typo. The developer guide says typical Roku channels are under 500KB, which means they consist entirely of the program code and the launch screen images. Everything else is downloaded from the network. And that makes sense, of course, because if your video player can’t get its program guide and images from the network, you’re dead already and local files won’t help you.

  • Get used to this theme of “simple”, and “simpler”. You’re going to hear it a lot in this blog.

  • A Roku application consists of a Manifest file with certain required attributes (version number, local or remote URLs for home screen artwork), and a Source folder with code files. You can include any other needed files in whatever file structure suits you, subject to the size restriction noted above.

  • Third-party Roku apps are written in BrightScript, a simple language that is based on Visual Basic. That’s going to freak a few people out, but I see the value of it to Roku:

    • Why not a popular and standard language, like Ruby or JavaScript? Because then Roku might be obligated to keep up with the evolution of those languages, even if those developments are meant for domains (Rails, the DOM) that are irrelevant to Roku. Owning their own language is smart. That’s why Apple controls Objective-C, Microsoft has C#, and Google f’ing stole Java. (Be honest, they did, and you know it.) BrightScript can have exactly what Roku needs in it and nothing more.
    • Why not a compiled language, like Java or some C derivative? Apparently, Roku’s special friends get that, but if you’re just writing a content browser that throws to a player, do you need the hassle, or even the performance?
    • But dude, really, Visual freakin’ Basic? Do you know how many professional programmers started on VB? Not my cup of tea, either, but why not co-opt the talent that’s out there? Chances are, it was comfortable to the guys and girls implementing it on Roku too.
  • Of course, it was no picnic getting myself out of the curly-brace mindset and into BrightScript, seeing as I hadn’t coded in any flavor of BASIC since the first Reagan administration. Among the key traps for C/C++/C#/Java/Obj-C converts:

    • No semicolons, and line-endings are syntactically meaningful.
    • Case-insensitive… most of the time.
    • Single = for testing equality, not ==. You’re not looking for cutesy-poo side-effects in BrightScript like you are in C.
    • No global variables, save for a single global associative array you can use as a sort of registry. Beyond that, if it’s not in scope, it’s dead to you.
    • Subclassing isn’t really a thing, at least not in your code. You’re mostly just interested in writing useful functions that’ll be called in-line, passing around state as needed. There are a small number of primitive types, along with an object type.
    • All the objects you’ll want to create are prefixed with ro (eg, roArray, roVideoScreen, etc.). However, when you look in the docs, all the good functionality is listed in the interfaces implemented by these objects, prefixed with if. Many classes implement multiple interfaces, so hit the base class, then follow the links to the interfaces.
    • Types are specified with the as keyword. For example function nextEpisode (episodeIndex as integer) as object takes an integer argument and returns an object.
    • Strings are ASCII, not UTF-8. Yes. In 2014. (facepalm)
  • Roku code is single-threaded — at least yours is — and this deserves its own bullet point because it really gets at the structure of a Roku application, as opposed to what a lot of us are used to from smartphones. On iOS, you write a lot of asychronous code, like event handlers that’ll be called when needed, or put long-running tasks into separate threads or blocks. By comparison, the typical Roku app builds its first screen and waits for user input by attaching a roMessagePort to the screen and calling wait(). This wait() gets woken up by an asychronous event like a user input or a video player update, at which point you investigate the message that unblocked the wait() and decide what to do. Often, the wait() is wrapped in a while that loops forever until it gets a message that merits breaking out of the loop. The flavor is similar to Java’s wait() and notify()/notifyAll() for signalling between threads, though that was never all that popular when I did Java and may be even less popular now.
  • The typical drill-down style of Roku application is basically a nested set of wait()s and function calls. Our main example project in the CodeMash class worked like this.

    • Download the list of sessions as JSON, parse it, and display a screen with tracks and sessions within the selected track.
    • wait() for user input, which may change the selected track or session, or drill into a session
    • If a session is selected, present a new screen for that session, with metadata and a play button, and wait() again.
    • If the user hits “play,”, put up a video player screen and start playing. Do another wait() to catch the user hitting the back button or the video ending

    Basically, at each step, we collate the data needed to present a new screen and then block our thread until notified of an event. All our state is basically left on the stack as we drill down further into our navigation.

  • The code for our final project was 200 lines and could be taught in less than a morning. By comparison, I’m pretty sure I couldn’t get an iOS class through a four-scene storyboard with JSON parsing and a video player in four hours.

  • One thing that makes things simple and consistent: on Roku, you have no control over or responsibility for layout. There are a dozen or so canned “screens” that you use to present information — lists of episodes, contents of an episode, a search screen, etc. — and these are populated by setting known properties with strings, arrays, or associative arrays (key-value lists). This is why Roku apps all look the same: the only way to do something dramatically different is to use the roScreen and draw everything yourself (this may be what the fancy-pants Hulu channel is doing, unless it’s using the native API). So, you get a lot less control, but you also have a lot less to do.

  • Oh, I hear you about to object, but just sit tight.

  • There are two video players, the convenient fullscreen roVideoScreen, and the roVideoPlayer that renders to an roImageCanvas on an roScreen in case you need to do overlays or you’re just crazy. You send your contents to this object as an associative array that includes, as a minimum, the keys StreamURLs, StreamBitrates, and StreamQualities, with arrays as their values. These arrays describe variants at different qualities (HD, SD) and bitrates that the player can choose from (meaning that all the index 0 entries describe one stream, all of index 1 describe another stream, etc.). It’s not the easiest thing to find in the documentation (look for Content Meta-Data), and there’s the additional caveat that HTTP Live Streaming (HLS) variant playlists should provide a bitrate of 0 as a flag value to tell the Roku “you figure it out”. Good times.

  • Roku apps are uploaded to your box with a browser, and can be debugged with a telnet session. This is why the first steps of doing Roku development are putting your box into “developer mode” (with a Konami-code-like input) and then getting your IP from the settings menu. This is why you’re also screwed if you take your Roku to a foreign location without the remote, as I did at CocoaConf San Jose: without the remote, you can’t get to the settings and get the Roku on the wifi. And the Roku app for smartphones won’t save you, because it needs the Roku to be on the wifi.

  • When you’re ready to submit to Roku, you sign the app with the Roku box itself and send it up for review. You can also publish private channels that are neither reviewed nor blessed by Roku, but are listed on and downloaded from their site. Some of the best stuff on my Roku is the Nowhere Man private channels that provide access to media that doesn’t enjoy official Roku support from its providers.

Editing BrightScript Roku code in TextMate 2

The point (and there is one)

OK, so what’s interesting about playing in such a tiny environment, with only minimal control over your appearance and severely limited functionality? Because the functionality is not the point. A box like a Roku is not an interesting general-purpose computing device (and neither is an Apple TV or a Chromecast). What’s interesting is the content you provide, and the whole point of the Roku SDK is clearly in providing means of letting your user search or browse content, choose something, and get the heck out of the way.

Its may be hard for developers to have the right level of humility, but on this kind of device, you are not the star (or rock star, or ninja, or whatever other embarrassing things we let VCs and their toadies call us). The value of the Roku channel is whatever stream the viewer chooses to put on his or her screen. That’s why they have the Roku.

So, on Roku, you’re just one part of a bigger effort. There’s also a bunch of server-side code to authenticate users and expose streaming URLs to them, provide program guides as XML or JSON, etc. And then there’s the whole art of encoding media across various bitrates, getting the best quality you can out of each. On that point, while Roku’s preferred streaming format is HTTP Live Streaming, and streams meant for iOS work fine (I used Apple’s BipBop stream for some of the demos), Roku’s encoding guidelines have some slightly different optimizations for their devices, such as working with a window size of eight segments for livestreams rather than three.

FWIW, we finished up the class with a livestream done with Wowza running on Amazon Web Services, which is what you’ll find in the wowzalive folder in the sample code, though of course you’ll need your own EC2 instance running Wowza for it to work, since the public IP in the sample is long gone. I used Telestream Wirecast to produce the outbound stream on my end, of course.

CodeMash class channel on Roku screen

Next steps

So what’s next? You can get the hang of the basics of Roku programming in a short amount of time, but in and of itself, it’s of limited usefulness. The trick is to have some content to show in your application. In my own attempts to bang out useful channels, that’s proven to be difficult, as many online video programmers, sensibly, carefully control access to their stream URLs. Look through the source of a web-based player, even with your User-Agent set to iPad or something Flash-less (in hopes of getting an HLS .m3u8 URL), and you’ll find the URLs are often deeply entangled in the site’s authentication schemes, meaning you’ll never manage to get a playable URL out of it. As practice, I had hoped to build a private Roku channel with the contents of anime reviewer JesuOtaku’s page (hi, JO!) and give it to her, but was thwarted by Blip.TV URLs that give you a one-frame “you’re not authenticated” movie if you try to load them up in your own player and are not duly cookied-up (or however they authenticate). Update: huh, now I can play that .mp4 on my iPhone, without going through Blip. Weird. Didn’t work two months ago. Should see if Roku will play the bare URL.

I’m resigned to think that if you want to build an interesting Roku channel, you need to bring your own content… perhaps as a stash of MP4s on a server somewhere, or a Wowza instance transcoding your livestream.

Interesting challenge. Check back in a few months and see if I’ve got that figured out.

Comments (4)

  1. Chad

    Thanks for the post. I am getting into development on the roku. Nothing to serious, unless I find a good niche. But right now I am just looking into it as a method of wasting my time. I am curious as to know if there are any good books or resources for roku development. I’ve starting going through the roku developer documentation, but I find it’s not hitting the spot for me. I am finding the coding is easy to understand, but I am with you on getting used to it (“No semicolons, and line-endings are syntactically meaningful.”)

    • Ben

      I’ve only been able to find books on Brightscript, but not the version that the Roku uses. You can still learn from it. It’s weird that there are no books published for Roku development.

  2. Ryan

    This is a great post. I’m learning Roku development and it’s interesting to see that the basic principles haven’t changed in two years. Thanks for writing. Your post helped me gain clarity over the Roku workflow and basics.

  3. If anyone is looking to control their roku device and is familiar with Javascript/Node.js – I’ve written a package for it: https://www.npmjs.com/package/nodeku

Leave a Reply

Your email address will not be published. Required fields are marked *