dealing with large numbers of videos

In a grid screen, I’m retriving like 20 rows of 80-90 videos each. The parse time is about 1 second per row, but the http time is about 5 seconds per row. I thought about dynamically loading when the user moves close to the end of a row, or loading the next row when the user moves down (this would be pretty annoying to interrupt the user each time). I also wonder if I use asyncgettostring in a wait loop with say 100ms wait time, I could set up the data transfer and do a fake multitasking, where the user could do their thing and the data could continue loading. Assuming that even works however, how would one handle it if the user selects and plays a video - you wouldn’t want to force them to reload all 2000 videos again - currently, I load the videos when the screen loads and store them into an array which I reload after the video finishes playing, this is very fast. I’m not sure how to keep track of what has been loaded and what has not, so the process can continue.

Probably I’ll just put the data transfer up front when the channel loads, but if anyone has any suggestions, it would be very helpful.

  • Joel

BrightScript isn’t the speediest interpreted language, but 1 second to parse a row of 80-90 items seems way too slow. What do you mean exactly when you say “parse”?

I mean take the xml file, go

“if xml.parse(xmlxfer) then
for each video in xml.videos…”

and convert it to a set of posters. I was using timer.mark() and timer.totalseconds() to time each action, but it might round up to a second. Roku parses the XML fast enough as far as I’m concerned. Its actually getting the files that is an issue.

While I’m talking, here’s a question:

If I use asyncgettostring() and a message port with a short wait time in my loop like msg=wait(25,port) can I do something like update the screen graphics while I’m waiting for my xml to come through, or is there a chance I’ll miss the incoming data?

  • Joel

If the most significant delay is during the web request, then doing an AsyncGetToString would allow you to continue processing messages/events. If the delay is more during the actual Parse(), then that won’t help, since there’s no way to asynchronously parse an XML string.

As for handling video selections during the AsyncGet, you can call AsyncCancel to kill the web request, and process the selection event. You’ll just need to keep track of any rows that haven’t completed loading, so you can continue with the load when the user returns to that screen.

Also, it probably goes without saying, but just to be safe, you want to make sure the port you’re listening to is the same for both the screen and the roUrlTransfer object.

Having it load 2000 videos, images, and data for a single selection screen sounds like too much to me. It could be a better idea having it load maybe 10 items per category with a “More” icon to load the rest in that category on a new screen. That would keep the traffic to a more reasonable level and not require you to load or cache so many poster images. Maybe include a dynamic search screen so users can get to that single film they want to see a lot quicker. How do you get past the >100 xml entries memory issue if you’re loading 2000 films? If you’re trying to stress test the box, your way is the way to do it, but I’d expect it to be slow, and clunky when it’s being slammed with too much data to keep track of in it’s tiny little brain. :slightly_smiling_face:

As far as reloading data, I think you can tell it what item was selected with the row/column, and you don’t need to close the gridscreen to play a video (either this current firmware or the testing firmware has that fix), so you shouldn’t have to redraw the screen anymore after the first draw.

“destruk” wrote:
How do you get past the >100 xml entries memory issue if you’re loading 2000 films?
What >100 xml entry memory issue? I’ve never experienced any limitation of that sort… at least not as low as 100.
And, for what it’s worth, the Netflix channel loads 25+ rows of anywhere from 5 to 50 titles each on its main screen.

“jbrave” wrote:
I was using timer.mark() and timer.totalseconds() to time each action, but it might round up to a second.

timer.totalmilliseconds() is probably what you want.

Does anyone here read threads or pay attention to what is posted anymore? geesh.
viewtopic.php?f=34&t=35105&p=226658&hilit=60+xml+100#p226658

ROKUKevin posted
"It sounds like your xml files are too large… 100’s of items will consume too much memory on the Roku.

It would be better to implement some sort of paging or add more hierarchies to your navigation structure.

–Kevin"

As to the size -
"There is no hard cap, but you will run into slow page loads with (retrieving…) messages…

–Kevin"

So I would think, that perhaps the reason it’s slow is because you are having it load a lot and putting a strain on the memory limitations of the roku device? maybe?
–edited to be nicer, sorry-- Limiting your xml transfers to 60 or so programs keeps it quick for me, so that’s what I do.

“destruk” wrote:
Does anyone here read threads or pay attention to what is posted anymore? geesh.
viewtopic.php?f=34&t=35105&p=226658&hilit=60+xml+100#p226658
With all due respect, I think you’re reading that too literally. The number of items in the XML is not the issue, but rather the size of the XML string being parsed. It also says “100’s of items”, not “100 items” and is specific to the memory consumed by the XML parser, not the data displayed on the current screen. That aside, jbrave is loading 20 different XML files with 80-90 items each, not a single XML file with 2000 items, so he is already implementing paged data as RokuKevin suggests in that thread.

For anyone who has a back-end that it’s easily implemented in, JSON parsing is pretty quick, and results in a native BirghtScript associative array.

The link I presented is part of librokudev, which for anyone new might include a few functions you’ll find helpful.

You know, it’s very cool that you wrote librokudev, but it really needs documentation. I would be willing to pay for good documentation of Librokudev. Maybe $35? Something like that, maybe more if necessary.

  • Joel

“jbrave” wrote:
You know, it’s very cool that you wrote librokudev, but it really needs documentation. I would be willing to pay for good documentation of Librokudev. Maybe $35? Something like that, maybe more if necessary.

Sheesh, I would feel bad taking money to do the work on that. But the request itself may be enough to spur me into action (since I really would like to know people are using it, and the docs are probably a big hurdle). Maybe I can get some work done on that soon.

“destruk” wrote:
Having it load 2000 videos, images, and data for a single selection screen sounds like too much to me.

Actually, as it turns out, the delay was on the API side not on the Roku side, using xml text files everything loads much faster. The parsing is still on the order of 900 milleseconds, but that isn’t too bad. Maybe there’s a faster way, as KBenson suggested, one second to parse is a long time, if so, please let me know. Here’s my code:

function parsexml(xmlxfer as string) as object
timer=createobject("rotimespan")
timer.mark()
xml=createobject("RoXMLElement")
posterlist=createobject("roArray",1,true)
if xml.parse(xmlxfer) then

if xml.channel.item.count() <1 then

?"no vids in this channel"
return [{Title:"",ShortDescriptionLine1:"No Content",SDPosterURL:"pkg:/images/blank.png",HDPosterURL:"pkg:/images/blank.png",url:"",action:""}]
end if

for each vid in xml.channel.item
	group=vid.GetNamedElements("media:group")
	content=group.getnamedElements("media:content")
	tempitem=(GetVideoDataFromXML(vid))
	posterlist.push(tempitem)
next
end if
?"XML Parse Time"; timer.totalseconds()
return posterlist

end function

function GetVideoDataFromXML(video) as object
	
	vidposters=createobject("roarray",1,true)
	posterobj=createobject("roassociativearray")
	
	media=createobject("roassociativearray")
	mediaArray=createobject("roArray",1,true)
	
	group=video.GetNamedElements("media:group")
	content=group.getnamedElements("media:content")
	
	posterobj.Title=video.GetNamedElements("title").gettext()
	posterobj.description=video.GetNamedElements("description").gettext()
	posterobj.pubdate=video.GetNamedElements("pubdate").GetText()
	posterobj.video=content 'mediaArray
	posterobj.SDPosterURL=video.GetNamedElements("media:thumbnail")@url
	posterobj.HDPosterURL=posterobj.SDPosterURL
	posterobj.Action="details"
	posterobj.ContentType="episode" 
	posterobj.ShortDescriptionLine1=posterobj.Title
	posterobj.ShortDescriptionLine2=posterobj.Description
	'if posterobj.description=""
	'	posterobj.description=posterobj.ShortDescriptionLine1
	'end if
return posterobj
end function

“jbrave” wrote:
Actually, as it turns out, the delay was on the API side not on the Roku side, using xml text files everything loads much faster. The parsing is still on the order of 900 milleseconds, but that isn’t too bad. Maybe there’s a faster way, as KBenson suggested, one second to parse is a long time, if so, please let me know. Here’s my code:
Your code looks fine to me. If the delay is on the API side, then using AsyncGetToString()s is definitely a good option for increasing responsiveness, so my suggestion above may be worth looking into. A delay or one second is bearable, so I wouldn’t be concerned about the parsing time. If you’re loading all 20+ rows before responding to events, however, I’d recommend doing it on a row-by-row basis, and interrupt as necessary based on user interaction.

I have a channel that’s coming out soon that uses this method… I store the details for loading the row (ex. url, content type, etc.) on the row object, then have a low timeout on my Wait loop.. on “invalid” messages, I start loading rows, and interrupt on valid messages. Because I launch new screens in that same Wait loop, it blocks until the user returns to the screen, and continues loading rows from there. (I have no idea if that actually makes sense typed out :P)

“TheEndless” wrote:

“jbrave” wrote:

I have a channel that’s coming out soon that uses this method… I store the details for loading the row (ex. url, content type, etc.) on the row object, then have a low timeout on my Wait loop.. on “invalid” messages, I start loading rows, and interrupt on valid messages. Because I launch new screens in that same Wait loop, it blocks until the user returns to the screen, and continues loading rows from there. (I have no idea if that actually makes sense typed out :P)

Do you have an example you’d be willing to share?

Having this very issue. When the user comes back it’s reloading the lists which takes 20 seconds total. :?

Thanks

I’m sorry I don’t. That was a long time ago.

  • Joel