Expand my Community achievements bar.

Learn about Edge Delivery Services in upcoming GEM session
SOLVED

Problem Directing P2P Webcam Publisher and Subscriber Streams!

Avatar

Former Community Member

Hello all,

I am making a video chat application that is strictly one-to-one and that has 2 separate WebcamSubscriber components, one for the host publisher to view himself and the other to view the person he/she is chatting with (exactly like is done on Skype).  However, whenever I test it with 2 people, it adds 2 screens in both WebcamSubscribers.  How can I tell the top WebcamSubscriber to ONLY show the other person, and the bottom one to ONLY show me?

I have looked over the documentation and it says that in order to subscribe to the stream being published by the current user`s computer I would have to use the following:

myWebcamSubscriber.webcamPublisher = myWebcamPublisher;

I am not doing this in Actionscript, but rather I am assigning the WebcamPublisher to the WebcamSurbscriber inside of the MXML tag which creates the bottom WebcamSubscriber component:

<rtc:WebcamPublisher width="0" height="0" id="webcamPub" />

<s:VGroup width="240" height="100%">

     <rtc:WebcamSubscriber width="240" height="240" />

     <s:HGroup width="100%">

          <rtc:WebcamSubscriber width="120" height="120" webcamPublisher="{webcamPub}" />

     </s:HGroup>

</s:VGroup>

What am I doing wrong?  This seems like it should be a no-brainer, but unfortunately there are no clear examples which show how to do this.

Thanks in advance for any help!

Matt

1 Accepted Solution

Avatar

Correct answer by
Former Community Member

Hi,

You need to pass an array with just one element i.e. cSession.userManager.myUserID . You can either put it inline or call a function that does this on creationComplete.

And as you mentioned in the function, you should do similarly here too. i.e. publisherIDs=[cSession.userManager.myUserID] . The central idea of this property is pass the userIDs of only those users whom you want to see. In this case since its only you, the array consists of only one element i.e. your userID.

Hope this helps

Thanks

Regards

Hironmay Basu

View solution in original post

9 Replies

Avatar

Former Community Member

Hi Matt,

You need to use the publisherIDs property in WebcamSubscriber. By default, our webcamsubscribers are meant to show all camera streams in a room in a grid layout. If you want one to show only you, you should set publisherIDs property( an array) to have just one element i.e. your userID. Similarly , you can set in the other subscriber( the one showing the other person) to have userID that’s not of yours( you can get the list of userIDs from userManager.userCollection).

Hope this helps

Thanks

Regards

Hironmay Basu

Avatar

Former Community Member

Hironmay,

Thank you so much for this!  This seems straight forward enough.  I just had a quick question:  What is my userID and how do I differentiate it from other userIDs?  What I mean is, how are they assigned and how do I know which one of the 2 in the array (assuming I`m connected to one other peer) is mine?

Matt

Avatar

Former Community Member

Its very simple. You should do userManager.myUserID to get your userID.

Thanks

Hironmay Basu

Avatar

Former Community Member

Hironmay,

I`ve been studying the WebCamera example and a lot of this is making sense.  However, I just tested the code suggestions you made to get the bottom camera to only show the publisher (i.e. me) and now the webcameraSubscriber displays nothing after the video stream is published.  Here is my code:

<rtc:WebcamPublisher width="0" height="0" id="webcamPub" />

<rtc:WebcamSubscriber width="120" height="120" webcamPublisher="{webcamPub}" publisherIDs="cSession.userManager.myUserID"/>

I didn`t get any errors, but since publisherIDs is expecting an array I imagine I should create one and populate it with myUserID?  There must be a more straighforward way to do this that I`m missing.  Can I set the publisherIDs inline, or must it be done in a function up in the [CDATA] section?

As far as setting up only the other user`s stream to play in my other webCamSubscriber, should I be using something like the following code (found in an earlier thread):

            private function onStreamEnters(evt:StreamEvent):void
            {
               // on STREAM_RECEIVE event
                startVisio();
            }

            private function startVisio():void{
                    var userStreams:Array = _streamManager.getStreamDescriptors();
                    var i:int;
                    var found:Boolean = false;                   
                   
                    if (userStreams.length == 0) trace("Found no streams");
                    for (i=0; i<userStreams.length; i++){
                        if (userStreams[i].streamPublisherID != _userManager.myUserID){
                            if (userStreams[i].type == StreamManager.CAMERA_STREAM ) {
                                currentSubscriber = new WebcamSubscriber();
                                currentSubscriber.height = this.height;
                                currentSubscriber.width = this.width;
                                currentSubscriber.displayUserBars=false;
                                currentSubscriber.connectSession = cSession ;
                                currentSubscriber.subscribe();
                                //currentSubscriber.webcamPublisher = webCamPub ;
                                currentSubscriber.publisherIDs = [userStreams[i].streamPublisherID];
                                videoContainer.addChild(currentSubscriber);
                                vs.selectedIndex=1;
                                found = true;
                            }
                        }
                    }
                    if (!found) message.text="En attente...";
            }

I just want to make sure that all possible scenarios are handled.

Thank you so much for the help Hironmay!  I don`t want to come across as an idiot, but I just want to make sure I`m doing this correctly and am following best practices while doing so.

Matt

Avatar

Correct answer by
Former Community Member

Hi,

You need to pass an array with just one element i.e. cSession.userManager.myUserID . You can either put it inline or call a function that does this on creationComplete.

And as you mentioned in the function, you should do similarly here too. i.e. publisherIDs=[cSession.userManager.myUserID] . The central idea of this property is pass the userIDs of only those users whom you want to see. In this case since its only you, the array consists of only one element i.e. your userID.

Hope this helps

Thanks

Regards

Hironmay Basu

Avatar

Former Community Member

Hironmay,

Your help has been great!  I implemented your code, and it does work, but something is still wrong.

I added this to a creationComplete function:

                webcamSubMe.publisherIDs=[cSession.userManager.myUserID];

When the first person enters, the bottom webcamSubscriber (webcamSubMe) displays the user.  However, when the second person enters, it then displays both users.  It's as though, when the second person enters, the original code is just ignored and it displays both of them as though it was a standard webcamSubscriber.  However, when I include the code inline in the webcamSubscriber it works as it`s supposed to!

<rtc:WebcamSubscriber width="120" height="120" webcamPublisher="{webcamPub}"

webcamSubMe.publisherIDs="{[cSession.userManager.myUserID]}" displayUserBars="false"/>

I`d really like to put all my actionScript in the [CDATA] block, rather than having it mixed in with the MXML.  Any idea why it works inline, but not outside?  There has got to be something I am missing here!

Here is my code:

    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import flash.media.Microphone;
           
            public var selectedMicIndex:Number = new Number();
           
           
            [Bindable]
            public var micNamesAC:ArrayCollection = new ArrayCollection(Microphone.names);
           
            private function onCreationComplete():void
            {
                cSession.roomManager.autoPromote = true ;
                cSession.roomManager.guestsHaveToKnock = false ;
                webcamSubMe.publisherIDs=[cSession.userManager.myUserID];

                //cSession.userManager.addEventListener(UserEvent.USER_REMOVE,onUserRemove);
            }

            private function onAudioClick(p_evt:MouseEvent):void
                {
                    if ( p_evt.currentTarget.label == "Start My Audio" ) {
                        audioPub.publish();
                        p_evt.currentTarget.label = "Stop My Audio" ;
                    }else if (p_evt.currentTarget.label == "Stop My Audio" ){
                        audioPub.stop();
                        p_evt.currentTarget.label = "Start My Audio" ;
                    }
                }
           
            /*****
             * Handler for the stop and start buttons.
             *******/
            private function onVideoClick(p_evt:MouseEvent):void
            {
                if ( p_evt.currentTarget.label == "Start My Video" ) {
                    webcamPub.publish();
                    p_evt.currentTarget.label = "Stop My Video" ;
                }else if (p_evt.currentTarget.label == "Stop My Video" ){
                    webcamPub.stop();
                    p_evt.currentTarget.label = "Start My Video" ;
                }
            }

            private function onGainChange(event:Event):void
            {
                audioPub.gain = gainSlider.value;
            }
        ]]>
    </fx:Script>
    <rtc:ConnectSessionContainer id="cSession" width="100%" height="100%" roomURL="https://collaboration.adobelivecycle.com/phaseblue/myfirstroom">
        <rtc:authenticator>
            <rtc:AdobeHSAuthenticator id="auth" userName="name" password="pass" protocol="rtmfp" />
        </rtc:authenticator>
        <s:BorderContainer height="600" width="800" backgroundColor="#eeeeee" borderWeight="3" horizontalCenter="0" verticalCenter="0">
                <s:HGroup left="10" top="10" right="10" bottom="10">
                    <rtc:WebcamPublisher width="0" height="0" id="webcamPub" resolutionFactor="5" quality="80"/>
                    <s:VGroup width="260" height="100%" gap="0" paddingRight="10">
                        <s:VGroup width="240" height="280">
                            <rtc:WebcamSubscriber width="240" height="240" displayUserBars="false"/>
                            <s:VGroup width="100%">
                                <s:HSlider id="gainSlider" minimum="0" maximum="100" value="{audioPub.gain}" liveDragging="true" change="onGainChange(event)" />
                                <mx:ProgressBar id="activityProgress" minimum="0" maximum="100" mode="manual" label=""/>
                            </s:VGroup>
                        </s:VGroup>
                        <s:VGroup width="100%" height="290">
                            <s:HGroup width="100%">
                                <rtc:WebcamSubscriber width="120" height="120" id="webcamSubMe" webcamPublisher="{webcamPub}" displayUserBars="false"/>
                                <rtc:AudioPublisher id="audioPub" width="0" height="0" useEchoSuppression="true" gain="60"/>
                                <rtc:AudioSubscriber id="audioSub" width="0" height="0"/>
                                <s:VGroup width="120">
                                    <s:ToggleButton id="videoStartBtn" label="Start My Video" click="onVideoClick(event)"/>
                                    <s:ToggleButton id="audioStartBtn" label="Start My Audio" click="onAudioClick(event)"/>       
                                </s:VGroup>
                            </s:HGroup>
                        </s:VGroup>
                    </s:VGroup>

                </s:HGroup>
        </s:BorderContainer>
    </rtc:ConnectSessionContainer>

Thanks again,

Matt

Avatar

Former Community Member

Hi Matt,

I will run your code and get back to you on Monday. Since ppl r using

this use case, I presume your code might b missing something.

Thanks

Hironmay Basu

Sent from my iPhone

Avatar

Former Community Member

Hironmay,

I figured it out and it works!  I forgot to place an event listener for the onCreationComplete() function in my MXML!

Sorry for wasting your time on this one!

Matt

The following has evaluated to null or missing: ==> liqladmin("SELECT id, value FROM metrics WHERE id = 'net_accepted_solutions' and user.id = '${acceptedAnswer.author.id}'").data.items [in template "analytics-container" at line 83, column 41] ---- Tip: It's the step after the last dot that caused this error, not those before it. ---- Tip: If the failing expression is known to be legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: #assign answerAuthorNetSolutions = li... [in template "analytics-container" at line 83, column 5] ----