简体   繁体   English

Roku RAF集成协助

[英]Roku RAF Integration Assistance

I am currently using Eclipse IDE with the Roku Developer Plugin to create a channel. 我目前正在使用带有Roku Developer Plugin的Eclipse IDE来创建一个频道。 I have experience in programming and code but brightscript has been a little more difficult for me to find my comfort with. 我有编程和代码方面的经验,但对于我来说,使用brightscript更难以找到我的安慰。

I have successfully created a channel that streams sufficiently. 我已成功创建了一个足够流的频道。 What I'm trying to do now is test the inclusion of RAF. 我现在要做的是测试包含RAF。 I have tried looking through the code of an existing RAF template along with my current working streaming program. 我已经尝试查看现有RAF模板的代码以及我当前正在使用的流媒体程序。

Unfortunately the calls and variable names are different enough, and my ignorance is high enough I'm struggling to connect some dots. 不幸的是,调用和变量名称是不同的,我的无知足够高,我正在努力连接一些点。 As I included the RAF library and code, or the code I thought I needed, the video no longer plays when I press the play button. 由于我包含了RAF库和代码,或者我认为需要的代码,当我按下播放按钮时,视频不再播放。 The channel loads and the preview/details load just when I press play it does nothing. 当我按下播放时,频道加载和预览/细节加载它什么也没做。

Here is the code for that section of code on the page. 这是页面上该部分代码的代码。

    Sub onItemSelected()
' first button is Play
if m.top.itemSelected = 0
    m.videoPlayer = CreateObject("roSGNode", "Video")
    m.videoPlayer.id="videoPlayer"
    m.videoPlayer.translation="[0, 0]"
    m.videoPlayer.width="1280"
    m.videoPlayer.height="720"
    m.videoPlayer.content   = m.top.content

    'show video player
    m.top.AppendChild(m.videoPlayer)

    m.videoPlayer.visible = true
    m.videoPlayer.setFocus(true)
    m.videoPlayer.control = "play"
    m.videoPlayer.observeField("state", "OnVideoPlayerStateChange")
    m.videoPlayer.observeField("visible", "onVideoVisibleChange")

    'THIS IS THE CODE I ADDED FROM THE RAF EXAMPLE
    'EVERYTHING IN BELOW THIS UNTIL THE END OF THE
    'SUB IF REMOVED THE VIDEO PLAYS.
    '--------------------------------------------------------------------------------
    adIface = Roku_Ads() 'RAF initialize
    print "Roku_Ads library version: " + adIface.getLibVersion()

    adIface.setDebugOutput(true) 'for debug pupropse

    'Indicates whether the default Roku backfill ad service URL 
    'should be used in case the client-configured URL fails (2 retries)
    'to return any renderable ads.
    adIface.setAdPrefs(true, 2)

    ' Normally, would set publisher's ad URL here.  Uncomment following line to do so.
    ' adIface.setAdUrl(m.videoContent.adUrl) 
    ' Otherwise uses default Roku ad server (with single preroll placeholder ad)

    'Returns available ad pod(s) scheduled for rendering or invalid, if none are available.
    adPods = adIface.getAds()

    playContent = true
    'render pre-roll ads
    if adPods <> invalid and adPods.count() > 0 then
        playContent = adIface.showAds(adPods)
    endif
    while(true)
        msg = wait(0, m.port)
        msgType = type(msg)

        if msgType = "roSGScreenEvent"
            if msg.isScreenClosed() then return
        else if msgType = "roSGNodeEvent"
           if (msg.GetNode() = "DetailsScreen")

                if msg.GetField() = "position" then
                    'render mid-roll ads
                    curPos = m.video.position
                    videoEvent = createPlayPosMsg(curPos)
                    adPods = adIface.getAds(videoEvent)
                    if adPods <> invalid and adPods.count() > 0
                        m.video.control = "stop"
                        playContent = adIface.showAds(adPods)
                    if playContent then
                            m.video.seek = curPos
                            m.video.control = "play"
                        endif
                    endif
                else if msg.GetField() = "state" then
                    curState = m.video.state
                    if curState = "finished" then
                        'render post-roll ads
                        videoEvent = createPlayPosMsg(curPos, true)
                        adPods = adIface.getAds(videoEvent)
                        m.video.control = "stop"
                        if adPods <> invalid and adPods.count() > 0
                            adIface.showAds(adPods)
                        end if
                        exit while
                    endif
                else if msg.GetField() = "navBack" then
                    'back button handling
                    if msg.GetData() = true then
                        m.video.control = "stop"
                        exit while
                    endif
                end if
            end if
        end if
    end while
'----------------------------------------------------------------------
'THIS IS THE END OF THE RAF CODE I INSERTED INTO THE VIDEO TEMPLATE.
end if

End Sub

On Eclipse it gives me an error that I have tried researching and figuring out but as I mentioned I'm stuck. 在Eclipse上,它给了我一个错误,我尝试过研究和搞清楚,但正如我所提到的那样,我被卡住了。

    Current Function:
    086:          m.videoPlayer.control = "play"
    087:          m.videoPlayer.observeField("state", "OnVideoPlayerStateChange")
    088:          m.videoPlayer.observeField("visible", "onVideoVisibleChange")
    089:          
    090:          'THIS IS THE CODE I ADDED FROM THE RAF EXAMPLE
    091:          'EVERYTHING IN BELOW THIS UNTIL THE END OF THE
    092:          'SUB IF REMOVED THE VIDEO PLAYS.
    093:          '--------------------------------------------------------------------------------
    094:*         adIface = Roku_Ads() 'RAF initialize
    095:          print "Roku_Ads library version: " + adIface.getLibVersion()
    096:  
    097:          adIface.setDebugOutput(true) 'for debug pupropse
    098:          
    Function Call Operator ( ) attempted on non-function. (runtime error &he0) in pkg:/components/screens/DetailsScreen/DetailsScreen.brs(94)
    094:         adIface = Roku_Ads() 'RAF initialize
    Backtrace:
    #0  Function onitemselected() As Void
       file/line: pkg:/components/screens/DetailsScreen/DetailsScreen.brs(94)
    Local Variables:
    global           Interface:ifGlobal
    m                roAssociativeArray refcnt=2 count:7
    adiface          <uninitialized>
    adpods           <uninitialized>
    playcontent      <uninitialized>
    msg              <uninitialized>
    msgtype          <uninitialized>
    curpos           <uninitialized>
    videoevent       <uninitialized>
    curstate         <uninitialized>
    roku_ads         <uninitialized>
    createplayposmsg <uninitialized>
    Threads:
    ID    Location                                Source Code
     0    pkg:/source/main.brs(34)                msg = wait(0, port)
     1*   ...ailsScreen/DetailsScreen.brs(94)     adIface = Roku_Ads() 'RAF initialize
      *selected

    Brightscript Debugger> 

I'm hoping to narrow down how to modify my channel to make this work. 我希望缩小如何修改我的频道以使其工作。 I did leave out this code: 我确实遗漏了这段代码:

    'RAF content params
        adIface.setContentId(m.videoContent.contentId)
        adIface.SetContentGenre(m.videoContent.contentGenre)

        'Nielsen content params
        adIface.enableNielsenDAR(true)
        adIface.setContentLength(m.videoContent.conntentLength)
        adIface.setNielsenProgramId(m.videoContent.nielsenProgramId)
        adIface.setNielsenGenre(m.videoContent.nielsenGenre)
        adIface.setNielsenAppId(m.videoContent.nielsenAppId)

Didnt want to work with Nielson stuff yet but not sure if I need to include it to make RAF work. 不想与Nielson合作,但不确定我是否需要将其包括在内以使RAF工作。

Thank you for your time, truly. 真的,谢谢你的时间。

Make sure you have library imported at the top of your file: 确保您在文件顶部导入了库:

Library "Roku_Ads.brs"

And entry in manifest file: 并在清单文件中输入:

bs_libs_required=roku_ads_lib

Also note you cannot invoke RAF from a render thread - which will be the next issue, looking at your code. 另请注意,您无法从渲染线程调用RAF - 这将是下一个问题,查看您的代码。 It should either be done from the main thread or from a task thread (see https://github.com/rokudev/RAF4RSG-sample ). 它应该从主线程或任务线程完成(请参阅https://github.com/rokudev/RAF4RSG-sample )。

Thank you everyone for your assistance. 谢谢大家的帮助。 Nas Banov, I looked over the RAF example you linked to GitHub and I think I understand what I need to do just having difficulty seeing the road. Nas Banov,我查看了你与GitHub相关联的RAF示例,我想我明白我需要做的只是看到路上有困难。

I have actually added the seperate .brs file to handle the RAF implementation as you suggested. 我实际上已经添加了单独的.brs文件来处理你建议的RAF实现。 The video is loaded into a grid from an external XML document as follows: 视频从外部XML文档加载到网格中,如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <rss xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
      <channel>
        <title></title>
        <link />
        <description></description>
        <language></language>
        <pubDate></pubDate>
        <image>
          <title></title>
          <url></url>
          <width>-1</width>
          <height>-1</height>
        </image>

        <item>
          <title></title>
          <link></link>
          <description></description>
          <pubDate></pubDate>
          <guid isPermaLink="false"></guid>
          <media:content channels="2" bitrate="1328.0" duration="53"
            fileSize="8731706" framerate="23.976" height="720" 
            type="video/mp4" width="1280" isDefault="true" url="">
            <media:description></media:description>
            <media:keywords></media:keywords>
            <media:thumbnail url="" />
            <media:title></media:title>
          </media:content>
        </item>

      </channel>
    </rss>

I was thinking of adding the Nielson Necessary fields to this XML if I find a way to push the xml entries into the RAF integration for reporting. 如果我找到一种方法将xml条目推送到RAF集成以进行报告,我正在考虑将Nielson必要字段添加到此XML中。

This is the Details portion of the menu selection. 这是菜单选择的详细信息部分。 After pressing a button on the Grid layout the Details screen loads. 按下网格布局上的按钮后,将加载详细信息屏幕。 Here i reference the PlayerTasks.brs which has the RAF integration code in it. 在这里,我引用了具有RAF集成代码的PlayerTasks.brs。

' ********** Copyright 2016 Roku Corp.  All Rights Reserved. ********** 
 ' inits details screen
 ' sets all observers 
 ' configures buttons for Details screen
Function Init()
    ? "[DetailsScreen] init"

    m.top.observeField("visible", "onVisibleChange")
    m.top.observeField("focusedChild", "OnFocusedChildChange")

    m.buttons           =   m.top.findNode("Buttons")
    m.poster            =   m.top.findNode("Poster")
    m.description       =   m.top.findNode("Description")
    m.background        =   m.top.findNode("Background")


    ' create buttons
    result = []
    for each button in ["Play", "Second button"]
        result.push({title : button})
    end for
    m.buttons.content = ContentList2SimpleNode(result)
    m.top.content=m.buttons.content
End Function

' set proper focus to buttons if Details opened and stops Video if Details closed
Sub onVisibleChange()
    ? "[DetailsScreen] onVisibleChange"
    if m.top.visible = true then
        m.buttons.jumpToItem = 0
        m.buttons.setFocus(true)
    else if m.videoPlayer <> invalid
        m.videoPlayer.visible = false
        m.videoPlayer.control = "stop"
        m.poster.uri=""
        m.background.uri=""
    end if
End Sub

' set proper focus to Buttons in case if return from Video PLayer
Sub OnFocusedChildChange()
    if m.top.isInFocusChain() and not m.buttons.hasFocus() and not m.videoPlayer.hasFocus() then
        m.buttons.setFocus(true)
    end if
End Sub

' set proper focus on buttons and stops video if return from Playback to details
Sub onVideoVisibleChange()
    if m.videoPlayer.visible = false and m.top.visible = true
        m.buttons.setFocus(true)
        m.videoPlayer.control = "stop"
        'clear video player content, for proper start of next video player 
        m.videoPlayer.content = invalid
        'remove video player
        m.top.removeChild(m.videoPlayer)
    end if
End Sub

' event handler of Video player msg
Sub OnVideoPlayerStateChange()
    if m.videoPlayer.state = "error"
        ' error handling
        m.videoPlayer.visible = false
    else if m.videoPlayer.state = "playing"
        ' playback handling
        playContent()
    else if m.videoPlayer.state = "finished"
        m.videoPlayer.visible = false
    end if
End Sub



sub playContent()
    content = m.buttons.content
    if content <> invalid then
        m.video.content = content
        m.video.visible = false

        m.PlayerTask = CreateObject("roSGNode", "PlayerTask")
        m.PlayerTask.observeField("state", "taskStateChanged")
        m.PlayerTask.video = m.video
        m.PlayerTask.control = "RUN"
    end if
end sub

sub taskStateChanged(event as Object)
    print "Player: taskStateChanged(), id = "; event.getNode(); ", "; event.getField(); " = "; event.getData()
    state = event.GetData()
    if state = "done" or state = "stop"
        exitPlayer()
    end if
end sub


' on Button press handler
Sub onItemSelected()
    ' first button is Play
    if m.top.itemSelected = 0
        m.videoPlayer = CreateObject("roSGNode", "Video")
        m.videoPlayer.id="videoPlayer"
        m.videoPlayer.translation="[0, 0]"
        m.videoPlayer.width="1280"
        m.videoPlayer.height="720"
        m.videoPlayer.content   = m.top.content

        'show video player
        m.top.AppendChild(m.videoPlayer)

        m.videoPlayer.visible = true
        m.videoPlayer.setFocus(true)
        m.videoPlayer.control = "play"
        m.videoPlayer.observeField("state", "OnVideoPlayerStateChange")
        m.videoPlayer.observeField("visible", "onVideoVisibleChange")

    end if
End Sub

' Content change handler
Sub OnContentChange()
    m.description.content   = m.top.content
    m.description.Description.width = "770"
    m.poster.uri            = m.top.content.hdBackgroundImageUrl
    m.background.uri            = m.top.content.hdBackgroundImageUrl
End Sub

'///////////////////////////////////////////'
' Helper function convert AA to Node
Function ContentList2SimpleNode(contentList as Object, nodeType = "ContentNode" as String) as Object
    result = createObject("roSGNode",nodeType)
    if result <> invalid
        for each itemAA in contentList
            item = createObject("roSGNode", nodeType)
            item.setFields(itemAA)
            result.appendChild(item)
        end for
    end if
    return result
End Function

Function OnkeyEvent(key, press) as Boolean
    ? ">>> Details >> OnkeyEvent"
    result = false
    if press AND key = "back" AND m.videoPlayer <> invalid AND m.videoPlayer.visible 
        m.videoPlayer.visible = false
        result = true    
    end if
    return result
End Function

I added the "PlayContent" subroutine which points to the .brs file with the RAF integration. 我添加了“PlayContent”子程序,该子程序指向带有RAF集成的.brs文件。 Added the TaskStateChanged event as I noticed it was missing. 添加了TaskStateChanged事件,因为我注意到它丢失了。 I am getting stuck at the section that has [m.PlayerTask.video = m.video] 我被困在[m.PlayerTask.video = m.video]的部分

Invalid value for left-side of expression. 表达式左侧的值无效。 (runtime error &he4) (运行时错误&he4)

Can't seem to figure out where I can pass the values of the parsed XML document into the playertasks section to get it working. 似乎无法弄清楚我可以将解析的XML文档的值传递到playertasks部分以使其工作。 I'm understanding what I need to do just can't find easy enough documentation to get it. 我理解我需要做的事情就是找不到足够简单的文档来获取它。

'*********************************************************************
'** (c) 2016-2017 Roku, Inc.  All content herein is protected by U.S.
'** copyright and other applicable intellectual property laws and may
'** not be copied without the express permission of Roku, Inc., which
'** reserves all rights.  Reuse of any of this content for any purpose
'** without the permission of Roku, Inc. is strictly prohibited.
'********************************************************************* 

Library "Roku_Ads.brs"

sub init()
    m.top.functionName = "playContentWithAds" 
    m.top.id = "PlayerTask"
end sub

sub playContentWithAds()

    video = m.top.video
    ' `view` is the node under which RAF should display its UI (passed as 3rd argument of showAds())
    view = video.getParent() 

    RAF = Roku_Ads()
    'RAF.clearAdBufferScreenLayers()        ' in case it was set earlier
    'RAF.enableAdBufferMessaging(true, true) ' could have been cleared by custom screen
    'RAF.setAdBufferScreenContent({})

    content = video.content
    RAF.setAdUrl(content.ad_url)
    ' for generic measurements api
    RAF.setContentGenre(content.categories)  'if unset, ContentNode has it as []
    ' Nielsen DAR specific measurements
    if content.nielsen_app_id <> invalid:
        RAF.enableNielsenDAR(true)
        RAF.setNielsenAppId(content.nielsen_app_id)
        RAF.setNielsenGenre(content.nielsen_genre) 
        RAF.setNielsenProgramId(content.nielsen_program_id)
        RAF.setContentLength(content.length)
    end if

    ' log tracking events
'     logObj = {
'         log : Function(evtType = invalid as Dynamic, ctx = invalid as Dynamic)
'                   if GetInterface(evtType, "ifString") <> invalid
'                       print "*** tracking event " + evtType + " fired."
'                       if ctx.companion = true then
'                           print "***** companion = true"
'                       end if
'                       if ctx.errMsg <> invalid then print "*****   Error message: " + ctx.errMsg
'                       if ctx.adIndex <> invalid then print "*****  Ad Index: " + ctx.adIndex.ToStr()
'                       if ctx.ad <> invalid and ctx.ad.adTitle <> invalid then print "*****  Ad Title: " + ctx.ad.adTitle
'                   else if ctx <> invalid and ctx.time <> invalid
'                       print "*** checking tracking events for ad progress: " + ctx.time.ToStr()
'                   end if
'               End Function
'     }
'     logFunc = Function(obj = Invalid as Dynamic, evtType = invalid as Dynamic, ctx = invalid as Dynamic)
'                   obj.log(evtType, ctx)
'               End Function
'     RAF.setTrackingCallback(logFunc, logObj)

    adPods = RAF.getAds() 'array of ad pods
    keepPlaying = true 'gets set to `false` when showAds() was exited via Back button

    ' show the pre-roll ads, if any
    if adPods <> invalid and adPods.count() > 0
       keepPlaying = RAF.showAds(adPods, invalid, view)
    end if

    port = CreateObject("roMessagePort")
    if keepPlaying then
        video.observeField("position", port)
        video.observeField("state", port)
        video.visible = true
        video.control = "play"
        video.setFocus(true) 'so we can handle a Back key interruption
    end if

    curPos = 0
    adPods = invalid
    isPlayingPostroll = false
    while keepPlaying
        msg = wait(0, port)
        if type(msg) = "roSGNodeEvent"
            if msg.GetField() = "position" then
                ' keep track of where we reached in content
                curPos = msg.GetData() 
                ' check for mid-roll ads
                adPods = RAF.getAds(msg)
                if adPods <> invalid and adPods.count() > 0
                    print "PlayerTask: mid-roll ads, stopping video"
                    'ask the video to stop - the rest is handled in the state=stopped event below
                    video.control = "stop"  
                end if
            else if msg.GetField() = "state" then
                curState = msg.GetData()
                print "PlayerTask: state = "; curState
                if curState = "stopped" then
                    if adPods = invalid or adPods.count() = 0 then 
                        exit while
                    end if

                    print "PlayerTask: playing midroll/postroll ads"
                    keepPlaying = RAF.showAds(adPods, invalid, view)
                    adPods = invalid
                    if isPlayingPostroll then 
                        exit while
                    end if
                    if keepPlaying then
                        print "PlayerTask: mid-roll finished, seek to "; stri(curPos)
                        video.visible = true
                        video.seek = curPos
                        video.control = "play"
                        video.setFocus(true) 'important: take the focus back (RAF took it above)
                    end if

                else if curState = "finished" then
                    print "PlayerTask: main content finished"
                    ' render post-roll ads
                    adPods = RAF.getAds(msg)
                    if adPods = invalid or adPods.count() = 0 then 
                        exit while
                    end if
                    print "PlayerTask: has postroll ads"
                    isPlayingPostroll = true
                    ' stop the video, the post-roll would show when the state changes to  "stopped" (above)
                    video.control = "stop"
                end if
            end if
        end if
    end while

    print "PlayerTask: exiting playContentWithAds()"
end sub

Thank you everyone for helping me figure this out. 谢谢大家帮我解决这个问题。 Things have changed so much since when I focused on software development. 自从我专注于软件开发以来,情况发生了很大的变化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM