Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Haijal
Visitor

I need help setting up my Roku VAST Ad framework

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)
0 Kudos
13 REPLIES 13
TheEndless
Channel Surfer

Re: I need help setting up my Roku VAST Ad framework

There's no code in your video player event loop to handle mid-rolls. You should be listening for the isPlaybackPosition() event, stopping the video when you get to the ad position, starting the ad, then resuming the video after the ad. Instead of using RokuChris's code, you may be better off using the new Roku Ad Framework: http://sdkdocs.roku.com/display/sdkdoc/ ... +Framework

The documentation for it includes an example with mid-rolls.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
Haijal
Visitor

Re: I need help setting up my Roku VAST Ad framework

I have the event listener code in there and have the notification set to 1, which should be good enough to catch it at the AdBreaks. I forgot to post the environment variables in my first post so I will now. I have also been looking at the Framework PDF, I actually have a bit of code from the pdf in my video screen.

Current Function:
094: shouldPlayContent = true
095: adBreakIndex = 0
096: ' videoScreen = PlayVideoContent(videoContent)
097: while shouldPlayContent
098: videoMsg = wait(0, contentVideoScreen.GetMessagePort())
099: if videoMsg.isPlaybackPosition()
100: curPos = videoMsg.GetIndex()
101: nextPod = scheduledPods[adBreakIndex]
102:* if curPos > nextPod.renderTime and not nextPod.viewed
103: contentVideoScreen.Close() 'stop playback of content
104: shouldPlayContent = adIface.showAds(nextPod) 'render next ad pod
105: adBreakIndex = adBreakIndex + 1
106: if shouldPlayContent
Type Mismatch. (runtime error &h18) in pkg:/source/appVideoScreen.brs(102)
102: if curPos > nextPod.renderTime and not nextPod.viewed
Backtrace:
#4 Function showvideoscreen(episode As Object) As Dynamic
file/line: pkg:/source/appVideoScreen.brs(102)
#3 Function showdetailscreen(episode As Object) As Integer
file/line: pkg:/source/appDetailScreen.brs(97)
#2 Function displayshowdetailsscreen(category As Object, showindex As Integer) As Integer
file/line: pkg:/source/SimpleGrid.brs(288)
#1 Function showgridscreen(screen As Object, gridstyle As String) As String
file/line: pkg:/source/SimpleGrid.brs(210)
#0 Function main() As Void
file/line: pkg:/source/SimpleGrid.brs(20)
Local Variables:
episode roAssociativeArray refcnt=3 count:30
global rotINTERFACE:ifGlobal
m roAssociativeArray refcnt=6 count:2
adiface roAssociativeArray refcnt=2 count:27
adpods roArray refcnt=3 count:1
adbreakschedule roArray refcnt=1 count:3
scheduledpods roArray refcnt=1 count:1
adbreakindex Integer val:0 (&h0)
ad roAssociativeArray refcnt=3 count:5
timer bsc:roTimespan refcnt=1
contentvideoscreen bsc:roVideoScreen refcnt=1
break1 bsc:roXMLList refcnt=4
break2 bsc:roXMLList refcnt=3
break3 bsc:roXMLList refcnt=3
shouldplaycontent Boolean val:true
videomsg bsc:roVideoScreenEvent refcnt=1
curpos Integer val:0 (&h0)
nextpod roAssociativeArray refcnt=2 count:5
videoscreen <uninitialized>
BrightScript Debugger>
Current Roku Channel for Global Sportsman Network(http://globalsportsman.com)
0 Kudos
TheEndless
Channel Surfer

Re: I need help setting up my Roku VAST Ad framework

Sorry, I inadvertently scrolled down and was looking at the wrong event loop in your code. I didn't see the Roku_Ads() code at the top.

You problem is most likely this line:
adIface.setAdUrl("globalsportsman.com/Roku/xml/Ads.xml")

That's not a valid URL. You're missing the "http://", which means the VAST XML is never getting loaded and parsed, resulting in an empty scheduledPods array, which in turn is resulting in nextPod being invalid causing the type mismatch error.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
Haijal
Visitor

Re: I need help setting up my Roku VAST Ad framework

o0o man, I can not believe I did that! Looked right over it.
Current Roku Channel for Global Sportsman Network(http://globalsportsman.com)
0 Kudos
Haijal
Visitor

Re: I need help setting up my Roku VAST Ad framework

I have replaced, the bad url, but I am still getting:

Type Mismatch. (runtime error &h18) in pkg:/source/appVideoScreen.brs(62)
062: if curPos > nextPod.renderTime and not nextPod.viewed


I have also tried to use
if curPos > Int(nextPod.renderTime)
and
if curPos > nextPod.renderTime.toint()
still getting the mismatch error. This doesn't make sense to me because they should both me int.
Current Roku Channel for Global Sportsman Network(http://globalsportsman.com)
0 Kudos
RokuKC
Roku Employee
Roku Employee

Re: I need help setting up my Roku VAST Ad framework

"Haijal" wrote:
I have replaced, the bad url, but I am still getting:

Type Mismatch. (runtime error &h18) in pkg:/source/appVideoScreen.brs(62)
062: if curPos > nextPod.renderTime and not nextPod.viewed


I have always tried to use
if curPos > Int(nextPod.renderTime)
and
if curPos > nextPod.renderTime.toint()
still getting the mismatch error. This doesn't make sense to me because they should both me int.


Can you print nextPod in the debugger to check the contents, namely whether nextPod.renderTime is defined and if so as what type?
0 Kudos
Haijal
Visitor

Re: I need help setting up my Roku VAST Ad framework

"RokuKC" wrote:

Can you print nextPod in the debugger to check the contents, namely whether nextPod.renderTime is defined and if so as what type?


Here is the print to the debugger for NextPod after being initialized
Next Pod:ads: <Component: roArray>
rendertime: <Component: roXMLList>
duration: 30
rendersequence: midroll
viewed: false
Current Roku Channel for Global Sportsman Network(http://globalsportsman.com)
0 Kudos
Haijal
Visitor

Re: I need help setting up my Roku VAST Ad framework

Ok, I feel like I have made some progress. I am able to get the video to reach my adBreakSchedule[] points and the video flickers, as if it is stopping and then going to load the Ad, but instead it is throwing a error, however it is resuming where the video closed. BTW, I was using these prints:


print videoMsg.GetIndex()
print "Next Pod: " ; nextPod
print nextPod.renderTime


Here is the debugger for it now:

 15
14
Next Pod:ads: <Component: roArray>
rendertime: 15
duration: 30
rendersequence: midroll
viewed: false

15
15
Next Pod:ads: <Component: roArray>
rendertime: 15
duration: 30
rendersequence: midroll
viewed: false

15
16
Next Pod:ads: <Component: roArray>
rendertime: 15
duration: 30
rendersequence: midroll
viewed: false

15
BRIGHTSCRIPT: ERROR: Runtime: FOR EACH value is Invalid: Roku_Ads.brs(1618)
Roku_Ads_getNoResponseFromUrl: requesting URL: http://www.google-analytics.com/collect?ea=video-start&v=1&tid=UA-678051-24&ev=1&ec=Render&el=unknown&cid=4d0e381c-4c65-5201-8a21-ff70b31bae88&ds=4200X&t=event&an=dev&z=9
Roku_Ads_showVideoAd: isRequestFailed(): index = 0; message = failed to create media player
Roku_Ads_getNoResponseFromUrl: requesting URL: http://www.google-analytics.com/collect?ea=failed%20to%20create%20media%20player&v=1&tid=UA-678051-24&ev=1&ec=ErrorRender&el=unknown&cid=4d0e381c-4c65-5201-8a21-ff70b31bae88&ds=4200X&t=event&an=dev&z=10


And the new Video Screen.brs

'**********************************************************
'** 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("http://www.globalsportsman.com/Roku/xml/Ads.xml")
adPods = adIface.getAds()

'adBreakSchedule = [episode.AdBreak1.toInt(), episode.AdBreak2.toInt(), episode.AdBreak3.toInt()]
adBreakSchedule = [15,30,55]
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/pos troll 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]
print videoMsg.GetIndex()
print "Next Pod:";nextPod
print nextPod.renderTime
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
Current Roku Channel for Global Sportsman Network(http://globalsportsman.com)
0 Kudos
RokuKC
Roku Employee
Roku Employee

Re: I need help setting up my Roku VAST Ad framework

The Ads.xml file posted is not well-formed XML... it has mismatched and unclosed tags, for example.

You will likely get better results using an actual VAST server or using VAST-compliant code to generate test data.
0 Kudos