Corey Hart
Corey Hart

Reputation: 193

WebRTC video call with picture in picture

Below is a script I´ve clumsily customized as much as I could for my need, which is to have a peer to peer WebRTC call where you see yourself in a small box in a corner, overlaid on the party sending to you showing in full screen. As you can see, I got as far as having a small view of myself, followed by the view of your call partner. But, how do I achive that the small box with your own view is an overlay on the other one?

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0, 
minimum-scale=1.0">


</head>
<body>


  <section class="make-center">




    <div id="videos-container"></div>
  </section>
<script src="/dist/RTCMultiConnection.min.js"></script>
<script src="/socket.io/socket.io.js"></script>

<!-- custom layout for HTML5 audio/video elements -->
<script src="/dist/getMediaElement.js"></script>
<script>


// ......................................................
// ..................RTCMultiConnection Code.............
// ......................................................

var connection = new RTCMultiConnection();

// by default, socket.io server is assumed to be deployed on your own URL
connection.socketURL = '/';

// comment-out below line if you do not have your own socket.io server
// connection.socketURL =     
'https://rtcmulticonnection.herokuapp.com:443/';

connection.socketMessageEvent = 'video-conference-demo';

connection.session = {
    audio: true,
    video: true
};

connection.sdpConstraints.mandatory = {
    OfferToReceiveAudio: true,
    OfferToReceiveVideo: true
};

connection.videosContainer = document.getElementById('videos-container');

connection.onstream = function(event) {

    var width = parseInt(connection.videosContainer.clientWidth);
   if (event.type === 'remote') { 
   var mediaElement = getMediaElement(event.mediaElement, {
        title: event.userid,
        buttons: [],
        width: width,
        showOnMouseEnter: false
    });
    connection.videosContainer.appendChild(mediaElement);
}
if (event.type === 'local') { 
   var mediaElement = getMediaElement(event.mediaElement, {
        title: event.userid,
        buttons: [],
        width: width / 8,
        showOnMouseEnter: false
    });
    connection.videosContainer.appendChild(mediaElement);
}



    setTimeout(function() {
        mediaElement.media.play();
    }, 5000);

    mediaElement.id = event.streamid;
};

connection.onstreamended = function(event) {
    var mediaElement = document.getElementById(event.streamid);
    if (mediaElement) {
        mediaElement.parentNode.removeChild(mediaElement);
    }
};


// ......................................................
// ......................Handling Room-ID................
// ......................................................



(function() {
    var params = {},
        r = /([^&=]+)=?([^&]*)/g;

    function d(s) {
        return decodeURIComponent(s.replace(/\+/g, ' '));
    }
    var match, search = window.location.search;
    while (match = r.exec(search.substring(1)))
        params[d(match[1])] = d(match[2]);
    window.params = params;
})();

var roomid = '';

var hashString = location.hash.replace('#', '');
if (hashString.length && hashString.indexOf('comment-') == 0) {
    hashString = '';
}

var roomid = params.roomid;
if (!roomid && hashString.length) {
    roomid = hashString;

}

if (roomid && roomid.length) {
    (function reCheckRoomPresence() {
        connection.checkPresence(roomid, function(isRoomExists) {
            if (isRoomExists) {
                connection.join(roomid);
                return;
            }
  if (!isRoomExists) {
                connection.open(roomid);
                return;
            }

            setTimeout(reCheckRoomPresence, 30000);
        });
    })();


}

//    to make it one-to-one
            connection.maxParticipantsAllowed = 1;
           connection.onRoomFull = function(roomid) {
              connection.closeSocket();
              connection.attachStreams.forEach(function(stream) {
                stream.stop();
              });


            };

</script>




<script src="/dist/common.js"></script>
</body>
</html>

Thanks in advance!

Upvotes: 0

Views: 2250

Answers (1)

Koby Douek
Koby Douek

Reputation: 16675

I suspect your problem is the order in which .appendChild add your DOM elements to your container.

First, set the elements as position:absolute so they can be placed on top of each other:

mediaElement.style.position = 'absolute';

Now, you have to decide which comes on top of which. I suggest using these 3 options:

Option 1: insertBefore

You can set which DOM element comes before or after the other using .insertBefore.

First, I suggest you scope both variables as global to the script, then you can use .insertBefore to set the 2nd element on top of the first one.

For example:

var mediaElement1;
var mediaElement2;

....

mediaElement1 = getMediaElement(event.mediaElement, {
    ....
});
connection.videosContainer.appendChild(mediaElement1);

// And then use the 1st element as a reference to insertBefore:
....
connection.videosContainer.insertBefore(mediaElement2, mediaElement1);

Option 2: Element.insert

You can also just use Element.insert instead of .appendChild:

Element.Insert(mediaElement, connection.videosContainer);
....
Element.Insert(mediaElement, connection.videosContainer);

Option 3: z-index

On the bigger window, the one in the background, do this:

mediaElement.style.zIndex = "1";

On the smaller window, the one in the front, do this:

mediaElement.style.zIndex = "9999";

Arrange them!

Now that both elements are displayed, styling them both as position:absolute, gives you the option to modify their top and left style properties to position the smaller video window wherever you like on top of the larger video display:

mediaElement.style.top = 10 + 'px';
mediaElement.style.left = 20 + 'px';

Upvotes: 1

Related Questions