I have set up a Roku channel in gridview, all the episodes play and look great but my boss wants to have our ads play in the video just like they do on our website. I have been trying to get this to work for the past two weeks, with no leads. I gutted the VAST.XML file that chris posted with his example, took all the tracking out of it, changed the media files to point to our CDN that is holding our Ads. I can not get the video to play midrolls, I have gotten prerolls to work.
I am going to post my video screen code and my local variables, I will also post the Ads.xml files I am using to pull the Ads. I do not want to hard code any of this so that I will be able to update the content of the channel with forcing our viewers to update the app. I have added AdBreak1, AdBreak2, and AdBreak3 elements in my showfeeds xml files, I did this to allow each episode to have it's own break schedule. If you guys could help me getting this playing between my Ad and back to my content it would be great, and then I will be able to create different Ad Pod xml files, which I plan randomize which ad pod is pull each time a episode is watched.
Video Screen:
'**********************************************************
'** Video Player Example Application - Video Playback
'** November 2009
'** Copyright (c) 2009 Roku Inc. All Rights Reserved.
'**********************************************************
'***********************************************************
'** Create and show the video screen. The video screen is
'** a special full screen video playback component. It
'** handles most of the keypresses automatically and our
'** job is primarily to make sure it has the correct data
'** at startup. We will receive event back on progress and
'** error conditions so it's important to monitor these to
'** understand what's going on, especially in the case of errors
'***********************************************************
Library "Roku_Ads.brs"
Function showVideoScreen(episode As Object)
adIface = Roku_Ads()
adIface.setAdUrl("globalsportsman.com/Roku/xml/Ads.xml")
adPods = adIface.getAds()
adBreakSchedule = [episode.AdBreak1, episode.AdBreak2, episode.AdBreak3]
scheduledPods = []
adBreakIndex = 0
for each ad in adPods
' schedule one ad per ad break
scheduledPods.Push({viewed : false,
renderSequence : "midroll",
duration : ad.duration,
renderTime : adBreakSchedule[adBreakIndex],
ads : [ad]
})
adBreakIndex = adBreakIndex + 1
end for
if type(episode) <> "roAssociativeArray" then
print "invalid data passed to showVideoScreen"
return -1
endif
timer=createobject("rotimespan")
timer.mark()
contentvideoScreen = CreateObject("roVideoScreen")
contentvideoScreen.SetContent(episode)
' need a reasonable notification period set if midroll/postroll ads are to be
' rendered at an appropriate time
contentvideoScreen.SetPositionNotificationPeriod(1)
contentvideoScreen.SetMessagePort(CreateObject("roMessagePort"))
contentvideoScreen.Show()
shouldPlayContent = true
adBreakIndex = 0
' videoScreen = PlayVideoContent(videoContent)
while shouldPlayContent
videoMsg = wait(0, contentVideoScreen.GetMessagePort())
if videoMsg.isPlaybackPosition()
curPos = videoMsg.GetIndex()
nextPod = scheduledPods[adBreakIndex]
if curPos > nextPod.renderTime and not nextPod.viewed
contentVideoScreen.Close() 'stop playback of content
shouldPlayContent = adIface.showAds(nextPod) 'render next ad pod
adBreakIndex = adBreakIndex + 1
if shouldPlayContent
episode.PlayStart = curPos
videoScreen = PlayVideoContent(episode)
end if
end if
end if
'*** Insert client app’s video event handler code here
end while
End Function
Function PlayVideoContent(content as Object) as Object
' roVideoScreen just closes if you try to resume or seek after
' returning from ad playback... TODO: is there a way to make
' this work without resetting the screen object?
videoScreen = CreateObject("roVideoScreen")
videoScreen.SetContent(content)
' need a reasonable notification period set if midroll/postroll ads are to be
' rendered at an appropriate time
videoScreen.SetPositionNotificationPeriod(1)
videoScreen.SetMessagePort(CreateObject("roMessagePort"))
videoScreen.Show()
return videoScreen
End Function
function ShowPreRoll(video as object)
' a true result indicates that playback finished without user intervention
' a false result indicates that the user pressed UP or BACK to terminate playback
result = true
canvas = CreateObject("roImageCanvas")
player = CreateObject("roVideoPlayer")
port = CreateObject("roMessagePort")
canvas.SetMessagePort(port)
' build a very simple buffer screen for our preroll video
canvas.SetLayer(0, { text: "Your program will begin after this message", color: "#000000" })
canvas.Show()
' be sure to use the same message port for both the canvas and the player
' so we can receive events from both
player.SetMessagePort(port)
player.SetDestinationRect(canvas.GetCanvasRect())
player.AddContent(video)
player.Play()
' start our event loop
while true
' wait for an event
msg = wait(0, canvas.GetMessagePort())
if type(msg) = "roVideoPlayerEvent"
if msg.isFullResult()
' the video played to the end without user intervention
exit while
else if msg.isRequestFailed()
'something went wrong with playback, but the user did not intervene
exit while
else if msg.isStatusMessage()
if msg.GetMessage() = "start of play"
' once the video starts, clear out the canvas so it doesn't cover the video
canvas.SetLayer(0, { color: "#00000000", CompositionMode: "Source" })
canvas.Show()
end if
end if
else if type(msg) = "roImageCanvasEvent"
if msg.isRemoteKeyPressed()
index = msg.GetIndex()
'if index = 0 or index = 2
' the user pressed UP or BACK to terminate playback
' result = false
exit while
' end if
end if
end if
end while
player.Stop()
player.ClearContent()
canvas.Close()
return result
end function
ShowFeed :
Function InitShowFeedConnectionAnglerWest() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/AnglerWest.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionBetterBuilt() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/BetterBuilt.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionCastIron() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/CastIron.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionDRT() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/DRT.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionEastonBow() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/EastonBow.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionFrontier() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/Frontier.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionKillCliff() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/KillCliff.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionJoeyMines() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/JoeyMines.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionPredatorNation() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/PredatorNation.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionSmacked() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/Smacked.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionOutdoorsmanTable() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/OutdoorsmanTable.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionTracks() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/Tracks.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionRockhillRanch() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/RockhillRanch.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
Function InitShowFeedConnectionClips() As Object
conn = CreateObject("roAssociativeArray")
conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/Clips.xml"
conn.Timer = CreateObject("roTimespan")
conn.LoadShowFeed = load_show_feed
conn.ParseShowFeed = parse_show_feed
conn.InitFeedItem = init_show_feed_item
print "created feed connection for " + conn.UrlShowFeed
return conn
End Function
'Function InitShowFeedConnectionBulletTime() As Object
' conn = CreateObject("roAssociativeArray")
' conn.UrlShowFeed = "http://globalsportsman.com/Roku/xml/BulletTime.xml"
' conn.Timer = CreateObject("roTimespan")
'conn.LoadShowFeed = load_show_feed
' conn.ParseShowFeed = parse_show_feed
' conn.InitFeedItem = init_show_feed_item
'print "created feed connection for " + conn.UrlShowFeed
' return conn
'End Function
'******************************************************
'Initialize a new feed object
'******************************************************
Function newShowFeed() As Object
o = CreateObject("roArray", 100, true)
return o
End Function
'***********************************************************
' Initialize a ShowFeedItem. This sets the default values
' for everything. The data in the actual feed is sometimes
' sparse, so these will be the default values unless they
' are overridden while parsing the actual game data
'***********************************************************
Function init_show_feed_item() As Object
o = CreateObject("roAssociativeArray")
o.ContentId = ""
o.Title = ""
o.ContentType = ""
o.ContentQuality = ""
o.Synopsis = ""
o.Genre = ""
o.Runtime = ""
o.StreamQualities = CreateObject("roArray", 5, true)
o.StreamBitrates = CreateObject("roArray", 5, true)
o.StreamUrls = CreateObject("roArray", 5, true)
o.AdBreak1 = int(5)
o.AdBreak2 = int(6)
o.AdBreak3 = int(7)
return o
End Function
'*************************************************************
'** Grab and load a show detail feed. The url we are fetching
'** is specified as part of the category provided during
'** initialization. This feed provides a list of all shows
'** with details for the given category feed.
'*********************************************************
Function load_show_feed(conn As Object) As Dynamic
if validateParam(conn, "roAssociativeArray", "load_show_feed") = false return invalid
print "url: " + conn.UrlShowFeed
http = NewHttp(conn.UrlShowFeed)
m.Timer.Mark()
rsp = http.GetToStringWithRetry()
print "Request Time: " + itostr(m.Timer.TotalMilliseconds())
feed = newShowFeed()
xml=CreateObject("roXMLElement")
if not xml.Parse(rsp) then
print "Can't parse feed"
return feed
endif
if xml.GetName() <> "feed" then
print "no feed tag found"
return feed
endif
if islist(xml.GetBody()) = false then
print "no feed body found"
return feed
endif
m.Timer.Mark()
m.ParseShowFeed(xml, feed)
print "Show Feed Parse Took : " + itostr(m.Timer.TotalMilliseconds())
return feed
End Function
'**************************************************************************
'**************************************************************************
Function parse_show_feed(xml As Object, feed As Object) As Void
showCount = 0
showList = xml.GetChildElements()
for each curShow in showList
'for now, don't process meta info about the feed size
if curShow.GetName() = "resultLength" or curShow.GetName() = "endIndex" then
goto skipitem
endif
item = init_show_feed_item()
'fetch all values from the xml for the current show
item.hdImg = validstr(curShow@hdImg)
item.sdImg = validstr(curShow@sdImg)
item.ContentId = validstr(curShow.contentId.GetText())
item.Title = validstr(curShow.title.GetText())
item.Description = validstr(curShow.description.GetText())
item.ContentType = validstr(curShow.contentType.GetText())
item.ContentQuality = validstr(curShow.contentQuality.GetText())
item.Synopsis = validstr(curShow.synopsis.GetText())
item.Genre = validstr(curShow.genres.GetText())
item.Runtime = validstr(curShow.runtime.GetText())
item.HDBifUrl = validstr(curShow.hdBifUrl.GetText())
item.SDBifUrl = validstr(curShow.sdBifUrl.GetText())
item.StreamFormat = validstr(curShow.streamFormat.GetText())
item.AdBreak1 = curShow.AdBreak1
item.AdBreak2 = curShow.AdBreak2
item.AdBreak3 = curShow.AdBreak3
if item.StreamFormat = "" then 'set default streamFormat to mp4 if doesn't exist in xml
item.StreamFormat = "mp4"
endif
'map xml attributes into screen specific variables
item.ShortDescriptionLine1 = item.Title
item.ShortDescriptionLine2 = item.Description
item.HDPosterUrl = item.hdImg
item.SDPosterUrl = item.sdImg
item.Length = strtoi(item.Runtime)
item.Categories = CreateObject("roArray", 5, true)
item.Categories.Push(item.Genre)
item.Actors = CreateObject("roArray", 5, true)
item.Actors.Push(item.Genre)
item.Description = item.Synopsis
'Set Default screen values for items not in feed
item.HDBranded = false
item.IsHD = false
item.StarRating = invalid
item.UserStarRating = invalid
item.ContentType = "episode"
'media may be at multiple bitrates, so parse an build arrays
for idx = 0 to 4
e = curShow.media[idx]
if e <> invalid then
item.StreamBitrates.Push(strtoi(validstr(e.streamBitrate.GetText())))
item.StreamQualities.Push(validstr(e.streamQuality.GetText()))
item.StreamUrls.Push(validstr(e.streamUrl.GetText()))
endif
next idx
showCount = showCount + 1
feed.Push(item)
skipitem:
next
End Function
Ads.xml File:
<?xml version="1.0" encoding="utf-8"?>
<VAST version="2.0"> <Ad id="2291331">
<InLine>
<AdSystem version="4.6.0-10">LiveRail</AdSystem>
<AdTitle><![CDATA[Buck Fishman HD2]]></AdTitle>
<Description><![CDATA[This is the first Buck Fishman Ad created]]></Description>
<Creatives>
<Creative sequence="1" id="7969">
<Linear>
<Duration>00:03:22</Duration>
<MediaFile>
<MediaFile delivery="streaming" type="video/mp4"><![CDATA[http://1587510142.rsc.cdn77.org/Ads/BuckFishmanDotComHD2.mp4]]></MediaFile>
</MediaFile>
</Linear>
</Creative>
<Creative sequence="2" id="7970">
<Linear>
<Duration>00:00:30</Duration>
<MediaFile>
<MediaFile delivery="streaming" type="video/mp4"><![CDATA[http://1587510142.rsc.cdn77.org/Ads/PB2Rachael.mp4]]></MediaFile>
</MediaFile>
</Linear>
</Creative>
<Creative sequence="3" id="7969">
<Linear>
<Duration>00:00:14</Duration>
<MediaFile>
<MediaFile delivery="streaming" type="video/mp4"><![CDATA[http://1587510142.rsc.cdn77.org/Ads/Bell1.mp4]]></MediaFile>
</MediaFile>
</Linear>
</Creative>
</Creatives>
</InLine>
</Ad>
</VAST><!-- 19 US_ARIZONA_PHOENIXAZ_TEMPE -->
Current Roku Channel for Global Sportsman Network(http://globalsportsman.com)