2. What you’ll learn
Techniques for writing and testing Roku channels
Basics of Roku’s BrightScript programming language
and built-in component library
Preparing audio and video to work with Roku
3. What we’re not covering
Submitting channels to Roku for distribution as public
or private channels
Fancy stuff (sockets, 2D graphics)
These things are well worth learning on your own, just out of
scope for a half-day intro class
4. Requirements (Roku)
A 2nd or 3rd generation Roku box (1st will probably
work too?), with power cable
Original Roku remote
Not the Roku mobile app; we need to get your Roku
on the Kalahari wifi
Some way to see the screen (monitor or capture)
5. Requirements (your
computer)
Text editor
Ability to zip files, preferably from the command-line
A telnet application (e.g., /usr/bin/telnet)
A browser not named “Safari”
Safari seems not to work reliably with Roku sideloading; Chrome works better for me
7. Basic Roku development
Roku channels are written in BrightScript
Scripting language similar to Visual Basic
Developer side-loads channel onto Roku box for
testing
Advanced: Roku box signs app for submission to Roku
as public app or private channel
12. Side loading
Channels are sent to your Roku as zips via browser
upload
Only one developer channel installed at one time; new
uploads replace the old one
Script is compiled at upload time, runs immediately if
compilation succeeds
Developer app stays on My Channels screen, can be
relaunched with remote
14. Roku channel zip contents
“source” folder
manifest file
Optional: any other files and folders (“images”, “xml”,
etc.)
Must unzip as these contents, not as a folder
with these contents. Maximum size is 2 MB,
and typical Roku channels are under 500 KB.
15. Manifest file
Describes channel such that it can be displayed on
“My Channels” page
Has attributes to indicate whether the channel is a
screensaver, requires Bluetooth or MKV support, etc.
16. Manifest file
title, subtitle — ASCII strings (not UTF-8!)
major_version, minor_version, build_version — numeric
Channel page artwork URLs — mm_icon_focus_sd
(336 x 210), mm_icon_focus_sd (248 x 140),
mm_icon_side_hd (108 x 69), mm_icon_side_sd (80 x
46)
All of these entries are required
17. Sample manifest file
major_version=1!
minor_version=0!
build_version=1!
title=Hello CodeMash project!
subtitle=First project for CodeMash 2014 precompiler!
mm_icon_focus_hd=pkg:/images/codemash-roku-menu-tile-336x210.jpeg!
mm_icon_side_hd=pkg:/images/codemash-roku-menu-tile-108x69.jpeg!
mm_icon_focus_sd=pkg:/images/codemash-roku-menu-tile-248x140.jpeg!
mm_icon_side_sd=pkg:/images/codemash-roku-menu-tile-80x46.jpeg!
splash_screen_hd=pkg:/images/codemash-roku-splash-hd.jpeg!
splash_screen_sd=pkg:/images/codemash-roku-splash-sd.jpeg!
splash_min_time=2000!
Note that the splash screen attributes are optional
18. BrightScript source files
Go in the “source” folder with file extension .brs
Execution begins in Sub Main()
You don’t need to do any sort of import/include; all are
picked up and compiled together
Some text editors (and Eclipse) have add-ons to
provide BrightScript syntax highlighting
19. Sample BrightScript file
Sub Main()!
port = CreateObject("roMessagePort")!
screen = CreateObject("roParagraphScreen")!
screen.SetMessagePort(port)!
screen.SetTitle("Example")!
screen.AddParagraph("Hello CodeMash!")!
screen.Show()!
wait(0, screen.GetMessagePort())!
End Sub
20. Building the channel
zip -9 -r ../hello_codemash.zip .
This is run from inside the hello_codemash directory
24. BrightScript code
Sub Main()!
! port = CreateObject("roMessagePort")!
! screen = CreateObject("roParagraphScreen")!
! screen.SetMessagePort(port)!
! screen.SetTitle("Example")!
! screen.AddParagraph("Hello CodeMash!")!
! screen.Show()!
! wait(0, screen.GetMessagePort())!
End Sub
25. BrightScript code
Sub Main()!
! port = CreateObject("roMessagePort")!
! screen = CreateObject("roParagraphScreen")!
! screen.SetMessagePort(port)!
! screen.SetTitle("Example")!
! screen.AddParagraph("Hello CodeMash!")!
! screen.Show()!
! wait(0, screen.GetMessagePort())!
End Sub
Sub() is a function that returns void. So this
could also be written as:
function Main() as void … end function
26. BrightScript code
Sub Main()!
! port = CreateObject("roMessagePort")!
! screen = CreateObject("roParagraphScreen")!
! screen.SetMessagePort(port)!
! screen.SetTitle("Example")!
! screen.AddParagraph("Hello CodeMash!")!
! screen.Show()!
! wait(0, screen.GetMessagePort())!
End Sub
Objects are created with CreateObject
(classname as String, [optional
parameters]) as Object
27. BrightScript code
Sub Main()!
! port = CreateObject("roMessagePort")!
! screen = CreateObject("roParagraphScreen")!
! screen.SetMessagePort(port)!
! screen.SetTitle("Example")!
! screen.AddParagraph("Hello CodeMash!")!
! screen.Show()!
! wait(0, screen.GetMessagePort())!
End Sub
Methods are called with the dot operator. Method
documentation is typically found in the interfaces
implemented by an object
28. BrightScript code
Sub Main()!
! port = CreateObject("roMessagePort")!
! screen = CreateObject("roParagraphScreen")!
! screen.SetMessagePort(port)!
! screen.SetTitle("Example")!
! screen.AddParagraph("Hello CodeMash!")!
! screen.Show()!
! wait(0, screen.GetMessagePort())!
End Sub
wait(timeout as Integer, port as
Object) as Object causes program execution
to wait here until notified by another thread.
29. BrightScript types
Numeric types: Boolean, Integer, Float, Double
String (ASCII, not UTF-8)
Object: A native BrightScript component (roFoo,
roBar)
Invalid: Return value indicating absence of an object
30. BrightScript collections
roArray — typical array. CreateObject(“roArray”,
3, true) or literal syntax: myNums = [1,2,3]
Use DIM for multi-dimensional array
roAssociativeArray — name/value pairs.
CreateObject (“roAssociativeArray”) or
literal myPairs = {foo:1, bar:2}
Collections are typically mutable
31. BrightScript flow control
if then / else if / else / end if
Compare with =, not ==
for / to / step / end for / exit for
for each in / end for / exit for
while / end while / exit while
goto
32. Other BrightScript traits
No global variables. All variables have local scope.
There is a single global associative array, accessed with
GetGlobalAA()
Single-threaded model. For asynchronous operations like
user input or video playback, wait() on a message port
and act on event when unblocked.
Most apps eventually end up in a while wrapping a
wait().
34. BrightScript screens
How you show stuff on the screen!
Typically, customize screen’s various properties (see the
interface documentation), attach it to a message port,
then present with show()
roScreen() displays immediately
wait() on the screen’s message port for events
(video ends, user presses back button, etc.)
48. Video players
roVideoScreen is a one-stop shop for video playback
Handles streaming, display, user interaction
roVideoPlayer is used for fancy stuff.
Player handles streaming. Drawing is done with an
roImageCanvas.
Developer must provide own UI with image canvas
49. Come to think about it, why
haven’t we done any video?
50. A/V Support
Video: H.264, main or high profile, 4:3 or 16:9 aspect
ratio, 384 Kbps - 3.2 Mbps for streaming (faster
possible for USB)
Audio: AAC Low Complexity (CBR) or AC3
passthrough. 128-256 Kbps, 2 channel stereo, 16-bit
samples at 44.1 or 48.0 Khz sample rate
Streaming: HTTP Live Streaming (HLS) or MS Smooth
Streaming
51. Content Metadata
Convention for Associative Arrays that describe A/V content
Used by screens: ContentType, Title, TitleSeason,
Description, ReleaseDate, Rating, StarRating,
UserStarRating, etc.
Used by players: StreamFormat, StreamBitrates,
StreamUrls, StreamQualities, StreamContentIDs
Keys with plural names are arrays, same index in each
describes one quality/bitrate option for the player to use.
65. Content Guides
Sent from server to Roku as XML or JSON
Roku parses either into a tree of arrays / associative
arrays
Use these to populate grid, poster, springboard
screens
Each drill-down takes you to a new screen and
wait()s
67. Live Streaming
Old (90’s-00’s) streams: RealMedia, Flash, Windows
Media, QuickTime Streaming. Constant socket
connection, managed by server.
Problems: Special port commonly blocked. Didn’t
scale well. Expensive servers.
68. Live Streaming (New!)
“Adaptive” streaming: server sends short (10 sec)
segments of video via HTTP on port 80
Client sees a playlist of segments at various bitrates
and switches between them based on changing
network conditions
HTTP Live Streaming (Apple, Android, Roku), Smooth
Streaming (Windows, XBox, Roku), MPEG-DASH
(Chromecast), etc.
70. Live HLS
Create the playlist and segments on-the-fly with:
Apple command-line tools and a UDP video stream
(in theory, anyways)
Server-side transcoders / transmuxers (Wowza)
74. Client side is the easy side
The client app is just part of the picture
A/V encoding
Server (content guide, transcode/transmux)
Other clients (web, mobile apps)
Having something worth streaming in the first place!
75. Next steps on Roku
Recap: Roku Streaming Player Developer Guide
Next, read “Design Guidelines” to better understand Roku
UX conventions
Let friends test your app by publishing it as a private channel
“Channel Packaging and Publishing” in SDK docs
Many Roku developers are private-only, not in Channel
Store (e.g., Nowhere Man)