Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

SOLVED

Problem Directing P2P Webcam Publisher and Subscriber Streams!

phaseblue
Level 3
Level 3

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
Hironmay
Correct answer by
Level 10
Level 10

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
Hironmay
Level 10
Level 10

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

phaseblue
Level 3
Level 3

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

Hironmay
Level 10
Level 10

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

Thanks

Hironmay Basu

phaseblue
Level 3
Level 3

Thanks Hironmay!

I`ll give this a shot!

Matt

phaseblue
Level 3
Level 3

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

Hironmay
Correct answer by
Level 10
Level 10

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

phaseblue
Level 3
Level 3

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

Hironmay
Level 10
Level 10

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

phaseblue
Level 3
Level 3

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