WebRTC the easy way

Sergey Zakirov

Provectus, 2015

Experience of using OpenTok WebRTC Platform

What is WebRTC

  • Video chats
  • Voice calls
  • File sharing
  • Browser-to-browser
  • No external plugins, all native

Possible problems

  • Handling browser differences 
  • Maintaining extra-server for PeerConnection
  • Signalling 
  • Handling events (new peer, messages etc.)
  • Moderation

Our tasks

  • P2P audio/video streaming
  • Random assignment of peers
  • Pretty complex flow with a lot of events, connection handling etc.
  • Test to ensure that equipment is capable of using WebRTC
  • Statistics gathering
  • Server: Java, .NET, Node.js, PHP, Python, Ruby, REST API
  • Client: JS, Native: iOS, Android

Creating a session

require 'opentok'

def create
  opentok = OpenTok::OpenTok.new(api_key, secret_key)

  # Create plain session  
  session = opentok.create_session

  # Create session that uses OpenTok Media Server:
  session = opentok.create_session(media_mode: :routed)

  # Create session with archiving
  session = opentok.create_session(archiving_mode: :always)

  session_id = session.session_id
end

Generating Tokens

# ...

token = opentok.generate_token(session_id)
# Or
token = session.generate_token

# With options
token = session.generate_token(
    role: :moderator,
    expire_time: Time.now.to_i + 3600, # Expires in an hour
    data: 'name=User'
)

# Send session_id and token to client

Client-side

<script src='//static.opentok.com/v2/js/opentok.min.js'></script>
if (OT.checkSystemRequirements() == 1) {
  // WebRTC is supported
} else {
  // WebRTC is not supported
}

Joining a session

var session = OT.initSession(apiKey, sessionId);
session.connect(token, function(error) {
  if (error) {
    console.log("Error connecting: ", error.code, error.message);
  } else {
    console.log("Connected to the session.");
  }
});

Publishing a stream

if (session.capabilities.publish == 1) {
    // The client can publish
} else {
    // The client cannot publish
}

// Events for access dialog

publisher.on({
  accessAllowed: function (event) {
    // The user has granted access to the camera and mic.
  },
  accessDenied: function accessDeniedHandler(event) {
    // The user has denied access to the camera and mic.
  },
  accessDialogOpened: function (event) {
    // The Allow/Deny dialog box is opened.
  },
  accessDialogClosed, function (event) {
    // The Allow/Deny dialog box is closed.
  }
});


// Publish stream to the session

publisher = OT.initPublisher('local-video', properties, function(error) {
  if (error) {
    // The client cannot publish
  } else {
    console.log('Publisher initialized.');
  }
});

Publishing a stream

if (session.capabilities.publish == 1) {
    // The client can publish
} else {
    // The client cannot publish
}

// Events for access dialog

publisher.on({
  accessAllowed: function (event) {
    // The user has granted access to the camera and mic.
  },
  accessDenied: function accessDeniedHandler(event) {
    // The user has denied access to the camera and mic.
  },
  accessDialogOpened: function (event) {
    // The Allow/Deny dialog box is opened.
  },
  accessDialogClosed, function (event) {
    // The Allow/Deny dialog box is closed.
  }
});

Publishing a stream

// Publish stream to the session

publisher = OT.initPublisher('local-video', properties, function(error) {
  if (error) {
    // The client cannot publish
  } else {
    console.log('Publisher initialized.');
  }
});

session.publish(publisher, function(error) {
  if (error) {
    console.log(error);
  } else {
    console.log('Publishing a stream.');
  }
});

Subscribing to a stream

session.on('streamCreated', function (event) {
  session.subscribe(
    event.stream,
    'remoteVideo', # Video container ID
    properties,
    function (error) {
      // ...
    }
  );
});

OpenTok Events

session.on({
  sessionConnected: # ...
  sessionDisconnected: # ...
  streamCreated: # ...
  streamDestroyed: # ...  
  # And many more
});

Signals

// Send signal
session.signal(
  {
    to: connection, # Connection object can be obtained from stream
                    # If 'to' is not specified, signal will be dispatched to all clients in session  
    type: 'chatMessage'
    data: 'Hello!'
  },
  function (error) {
    // handle possible errors
  }
);

// Receive 
session.on('signal:chatMessage', function (event) {
  console.log('Chat message received from connection ' + event.from.id);
  console.log('Message: ' + event.data);
});

Moderation

session.forceDisconnect(connection);

session.forceUnpublish(stream);

OpenTok

By diokhan

OpenTok

  • 633