Setting up a Roku Channel

Goal: Learn how to stream content on Roku using their "simplevideoplayer" sample channel.

Software Prerequisites:

  • Roku SDK
  • Roku player (developer version)

Knowledge Prerequisites:

  • Basic scripting

Key Steps:

  1. Modify, package, and install the sample Roku channel.
  2. Update the sample channel for production traffic.

Step 1 - Modify the Sample Roku Channel

Modify the sample Roku channel to point to an assetRefers to media (i.e., audio/video content) associated with either your account or a library shared with your account..

Use a text editor to open appMain.brs.

Path:

[roku_sdk_root]/examples/source/simplevideoplayer/source/appMain.brs

Review the following code and make the necessary modifications to point the channel to an asset that does not require a signed playback URL.

The most relevant code excerpts are listed below.

Excerpt #1:

'showSpringboardScreen(itemVenter) 'comment out this line 	

Excerpt #2:

showSpringboardScreen(item)       'uncomment this line to see the BigBuckBunny example	

Excerpt #3:

bitrates  = [0]          ' 0 = no dots, adaptive bitrate

Excerpt #4:

'comment out this entry and uncomment the big buck bunny entry
'Swap the commented values below to play different video clips...
'urls = ["http://video.ted.com/talks/podcast/CraigVenter_2008_480.mp4"]
'qualities = ["HD"]
'StreamFormat = "mp4"
'title = "Craig Venter Synthetic Life"
'srt = "file://pkg:/source/craigventer.srt"	

Excerpt #5:

' Uncomment this entry. Replace urls with the red urls assignment using your Playback URL from our CMS.
' Change qualities to HD.  Add the srt = "" to avoid a missing assignment error in Roku's code.
' Big Buck Bunny test stream 
urls = ["https://content.uplynk.com/your_playback_url.m3u8"]
qualities = ["HD"]
streamformat = "hls"
title = "Big Buck Bunny"
srt = "" ' Added this line to work around a Roku channel bug	

Excerpt #6:

' Explicitly declare the Switching Strategy
videoclip.SwitchingStrategy = "full-adaptation"	

Excerpt #7:

' The following lines of code work around Roku's HTTPS request issues
video.SetCertificatesFile("common:/certs/ca-bundle.crt")
video.SetCertificatesDepth(3)	

Sample PlayVideo application code:

' ********************************************************************
' **  Sample PlayVideo App
' **  Copyright (c) 2009 Roku Inc. All Rights Reserved.
' ********************************************************************

Sub Main(args As Dynamic)
	'initialize theme attributes like titles, logos and overhang color
	initTheme()

	if type(args) = "roAssociativeArray" and type(args.url) = "roString" then
		displayVideo(args)
	end if
	print "Type args = "; type(args)
	print "Type args.url = "; type(args.url)

	'has to live for the duration of the whole app to prevent flashing
	'back to the roku home screen.
	screenFacade = CreateObject("roPosterScreen")
	screenFacade.show()

	itemMpeg4 = {   ContentType:"episode"
		SDPosterUrl:"file://pkg:/images/DanGilbert.jpg"
		HDPosterUrl:"file://pkg:/images/DanGilbert.jpg"
		IsHD:False
		HDBranded:False
		ShortDescriptionLine1:"Dan Gilbert asks, Why are we happy?"
		ShortDescriptionLine2:""
		Description:"Harvard psychologist Dan Gilbert says our beliefs about what will make us happy are often wrong -- a premise he supports with intriguing research, and explains in his accessible and unexpectedly funny book, Stumbling on Happiness."
		Rating:"NR"
		StarRating:"80"
		Length:1280
		Categories:["Technology","Talk"]
		Title:"Dan Gilbert asks, Why are we happy?"
		}

	itemVenter = { ContentType:"episode"
		SDPosterUrl:"file://pkg:/images/CraigVenter-2008.jpg"
		HDPosterUrl:"file://pkg:/images/CraigVenter-2008.jpg"
		IsHD:False
		HDBranded:False
		ShortDescriptionLine1:"Can we create new life out of our digital universe?"
		ShortDescriptionLine2:""
		Description:"He walks the TED2008 audience through his latest research into fourth-generation fuels -- biologically created fuels with CO2 as their feedstock. His talk covers the details of creating brand-new chromosomes using digital technology, the reasons why we would want to do this, and the bioethics of synthetic life. A fascinating Q&A with TED's Chris Anderson follows."
		Rating:"NR"
		StarRating:"80"
		Length:1972
		Categories:["Technology","Talk"]
		Title:"Craig Venter asks, Can we create new life out of our digital universe?"
		}

	item = {   ContentType:"episode"
		SDPosterUrl:"file://pkg:/images/BigBuckBunny.jpg"
		HDPosterUrl:"file://pkg:/images/BigBuckBunny.jpg"
		IsHD:true
		HDBranded:true
		ShortDescriptionLine1:"Big Buck Bunny"
		ShortDescriptionLine2:""
		Description:"Big Buck Bunny is being served using a Wowza server running on Amazon EC2 cloud services. The video is transported via HLS HTTP Live Streaming. A team of small artists from the Blender community produced this open source content..."
		Rating:"NR"
		StarRating:"80"
		Length:600
		Categories:["Technology","Cartoon"]
		Title:"Big Buck Bunny"
		}

	'showSpringboardScreen(itemVenter) 'comment out this line 
	'showSpringboardScreen(itemMpeg4)  'uncomment this line and comment out the next to see the old mpeg4 example
	showSpringboardScreen(item)	   'uncomment this line to see the BigBuckBunny example

	'exit the app gently so that the screen doesn't flash to black
	screenFacade.showMessage("")
	sleep(25)
End Sub

'*************************************************************
'** Set the configurable theme attributes for the application
'**
'** Configure the custom overhang and Logo attributes
'*************************************************************

Sub initTheme()

	app = CreateObject("roAppManager")
	theme = CreateObject("roAssociativeArray")

	theme.OverhangPrimaryLogoOffsetSD_X = "72"
	theme.OverhangPrimaryLogoOffsetSD_Y = "15"
	theme.OverhangSliceSD = "pkg:/images/Overhang_BackgroundSlice_SD43.png"
	theme.OverhangPrimaryLogoSD  = "pkg:/images/Logo_Overhang_SD43.png"

	theme.OverhangPrimaryLogoOffsetHD_X = "123"
	theme.OverhangPrimaryLogoOffsetHD_Y = "20"
	theme.OverhangSliceHD = "pkg:/images/Overhang_BackgroundSlice_HD.png"
	theme.OverhangPrimaryLogoHD  = "pkg:/images/Logo_Overhang_HD.png"

	'this is an optional theme attribute. the default subtitle color is yellow.
	theme.SubtitleColor = "#dc00dc"

	app.SetTheme(theme)

End Sub


'*************************************************************
'** showSpringboardScreen()
'*************************************************************

Function showSpringboardScreen(item as object) As Boolean
	port = CreateObject("roMessagePort")
	screen = CreateObject("roSpringboardScreen")

	print "showSpringboardScreen"

	screen.SetMessagePort(port)
	screen.AllowUpdates(false)
	if item <> invalid and type(item) = "roAssociativeArray"
		screen.SetContent(item)
	endif

	screen.SetDescriptionStyle("generic") 'audio, movie, video, generic
										' generic+episode=4x3,
	screen.ClearButtons()
	screen.AddButton(1,"Play")
	screen.AddButton(2,"Go Back")
	screen.SetStaticRatingEnabled(false)
	screen.AllowUpdates(true)
	screen.Show()

	downKey=3
	selectKey=6
	while true
		msg = wait(0, screen.GetMessagePort())
		if type(msg) = "roSpringboardScreenEvent"
			if msg.isScreenClosed()
				print "Screen closed"
				exit while
			else if msg.isButtonPressed()
					print "Button pressed: "; msg.GetIndex(); " " msg.GetData()
					if msg.GetIndex() = 1
						 displayVideo("")
					else if msg.GetIndex() = 2
						 return true
					endif
			else
				print "Unknown event: "; msg.GetType(); " msg: "; msg.GetMessage()
			endif
		else
			print "wrong type.... type=";msg.GetType(); " msg: "; msg.GetMessage()
		endif
	end while


	return true
End Function


'*************************************************************
'** displayVideo()
'*************************************************************

Function displayVideo(args As Dynamic)
	print "Displaying video: "
	p = CreateObject("roMessagePort")
	video = CreateObject("roVideoScreen")
	video.setMessagePort(p)

	bitrates  = [0]		  ' 0 = no dots, adaptive bitrate
	'bitrates  = [348]	' <500 Kbps = 1 dot
	'bitrates  = [664]	' <800 Kbps = 2 dots
	'bitrates  = [996]	' <1.1Mbps  = 3 dots
	'bitrates  = [2048]	' >=1.1Mbps = 4 dots


	'comment out this entry and uncomment the big buck bunny entry
	'Swap the commented values below to play different video clips...
	'urls = ["http://video.ted.com/talks/podcast/CraigVenter_2008_480.mp4"]
	'qualities = ["HD"]
	'StreamFormat = "mp4"
	'title = "Craig Venter Synthetic Life"
	'srt = "file://pkg:/source/craigventer.srt"

	'urls = ["http://video.ted.com/talks/podcast/DanGilbert_2004_480.mp4"]
	'qualities = ["HD"]
	'StreamFormat = "mp4"
	'title = "Dan Gilbert asks, Why are we happy?"

	' Apple's HLS test stream
	'urls = ["http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"]
	'qualities = ["SD"]
	'streamformat = "hls"
	'title = "Apple BipBop Test Stream"


	' Uncomment this entry. Replace urls with the red urls assignment using your Playback URL from our CMS.
	' Change qualities to HD.  Add the srt = "" to avoid a missing assignment error in Roku's code.
	' Big Buck Bunny test stream 
	urls = ["https://content.uplynk.com/your_playback_url.m3u8"]
	qualities = ["HD"]
	streamformat = "hls"
	title = "Big Buck Bunny"
	srt = "" ' Added this line to work around a Roku channel bug

	if type(args) = "roAssociativeArray"
		if type(args.url) = "roString" and args.url <> "" then
			urls[0] = args.url
		end if
		if type(args.StreamFormat) = "roString" and args.StreamFormat <> "" then
			StreamFormat = args.StreamFormat
		end if
		if type(args.title) = "roString" and args.title <> "" then
			title = args.title
		else
			title = ""
		end if
		if type(args.srt) = "roString" and args.srt <> "" then
			srt = args.StreamFormat
		else
			srt = ""
		end if
	end if

	videoclip = CreateObject("roAssociativeArray")
	videoclip.StreamBitrates = bitrates
	videoclip.StreamUrls = urls
	videoclip.StreamQualities = qualities
	videoclip.StreamFormat = StreamFormat
	videoclip.Title = title
	' Explicitly declare the Switching Strategy
	videoclip.SwitchingStrategy = "full-adaptation"
	print "srt = ";srt
	if srt <> invalid and srt <> "" then
		videoclip.SubtitleUrl = srt
	end if

	video.SetContent(videoclip)
	' The following lines of code work around Roku's HTTPS request issues
	video.SetCertificatesFile("common:/certs/ca-bundle.crt")
	video.SetCertificatesDepth(3)
	video.show()

	lastSavedPos   = 0
	statusInterval = 10 'position must change by more than this number of seconds before saving

	while true
		msg = wait(0, video.GetMessagePort())
		if type(msg) = "roVideoScreenEvent"
			if msg.isScreenClosed() then 'ScreenClosed event
				print "Closing video screen"
				exit while
			else if msg.isPlaybackPosition() then
				nowpos = msg.GetIndex()
				if nowpos > 10000

				end if
				if nowpos > 0
					if abs(nowpos - lastSavedPos) > statusInterval
						lastSavedPos = nowpos
					end if
				end if
			else if msg.isRequestFailed()
				print "play failed: "; msg.GetMessage()
			else
				print "Unknown event: "; msg.GetType(); " msg: "; msg.GetMessage()
			endif
		end if
	end while
End Function	

Step 2 - Package the Modified Roku Channel

Package the modified version of the sample Roku channel.

Compress the contents of the simplevideoplayer directory as a zip file.

Do not include the parent folder (i.e., simplevideoplayer) in the zip file.

The manifest file should be located in the base path of the zip file.

Step 3 - Install the Modified Roku Channel

Install the modified Roku channel by pointing the Roku player to the zip file.

Find out the device's IP address.

For example, the IP address for Roku 2 may be found by selecting About from the Roku Player Settings Channel.

Open a web browser to the above IP address. Roku's development channel installation page will load.

If the installation page does not load, please enable developer mode.
Learn more (Roku Developer Documentation).

Point the installation to the zip file created in step 2.

Step 4 - Create a Production Channel

The next step is to prepare the channel for production traffic by:

  1. Applying security to the sample channel.

    Learn more (security tutorials).

  2. Modify the channel to serve up playback URLs for your content.