Comment on page
Room
There are three special trigger events for the room object:
room.after
, participant.after
and track.after
. Each occurs in response to a web hook call from the video provider. These events are also recorded in the room's events[]
list.Note
recording.after
and composition.after
will be implemented in future versions.To handle events triggered by the remote room provider, insert these Cortex script triggers.
org.objects.scripts.insertMany([{
type: 'trigger',
active: true,
configuration: {
event: 'room.after',
object: 'room',
},
description: 'c_room_room_event',
label: 'c_room_room_event',
name: 'c_room_room_event',
principal: null,
script: `
const { arguments: { event, old: room }, context } = script
require('logger').trace(event)
`
},{
type: 'trigger',
active: true,
configuration: {
event: 'participant.after',
object: 'room',
},
description: 'c_room_participant_event',
label: 'c_room_participant_event',
name: 'c_room_participant_event',
principal: null,
script: `
const { arguments: { event, old: room }, context } = script
require('logger').trace(event)
`
},{
type: 'trigger',
active: true,
configuration: {
event: 'track.after',
object: 'room',
},
description: 'c_room_track_event',
label: 'c_room_track_event',
name: 'c_room_track_event',
principal: null,
script: `
const { arguments: { event, old: room }, context } = script
require('logger').trace(event)
`
}]).execute()
All room events share the following properties:
type
{ String } Indexed room event type [room
,participant
,track
]name
{ String } Indexed room event name.created
,ended
,connected
, etc.order
{ Number } Indexed integer representing the order in which the remote event was fired. It's possible thatevents are called and written out of order. Theorder
property may be used to present the remote timeline.roomId
{ ObjectID } Indexed originating local room identifier.
{
type: 'room',
name: 'created',
order: 0,
roomId: '5df02d890535377c38cfdeef'
}
duration
{ Number } The number of seconds the room was active.
{
type: 'room',
name: 'ended',
order: 12,
roomId: '5df02d890535377c38cfdeef',
duration: 156
}
status
{ String } The current status of the participant generating this event - eitherconnected
ordisconnected
.accountId
{ ObjectID } The id of the account generating the event.
{
type: 'participant',
name: 'connected',
order: 1,
roomId: '5df02d890535377c38cfdeef',
status: 'connected',
accountId: '58c87b958b8f160100812b70'
}
status
{ String } The current status of the participant generating this event - eitherconnected
ordisconnected
.accountId
{ ObjectID } The id of the account generating the event.duration
{ Number } The number of seconds the participant was connected to the room.
{
type: 'participant',
name: 'disconnected',
order: 8,
roomId: '5df02d890535377c38cfdeef',
status: 'disconnected',
accountId: '58c87b958b8f160100812b70',
duration: 101
}
status
{ String } The current status of the participant generating this event - eitherconnected
ordisconnected
.accountId
{ ObjectID } The id of the account generating the event.trackKind
{ String } The kind of track -data
,audio
orvideo
.trackName
{ String } The track name. Currently unused and set to a uuid.
{
type: 'track',
name: 'added',
order: 2,
roomId: '5df02d890535377c38cfdeef',
status: 'connected',
accountId: '58c87b958b8f160100812b70',
trackKind: 'audio',
trackName: '613ef5df-cdee-4fd6-8f19-7140deb08b81'
}
status
{ String } The current status of the participant generating this event - eitherconnected
ordisconnected
.accountId
{ ObjectID } The id of the account generating the event.trackKind
{ String } The kind of track -data
,audio
orvideo
.trackName
{ String } The track name. Currently unused and set to a uuid.
{
type: 'track',
name: 'removed',
order: 21,
roomId: '5df02d890535377c38cfdeef',
status: 'connected',
accountId: '58c87b958b8f160100812b70',
trackKind: 'video',
trackName: '8bd80b33-34ab-4ac6-b2fd-23d51cfe9156'
}
status
{ String } The current status of the participant generating this event - eitherconnected
ordisconnected
.accountId
{ ObjectID } The id of the account generating the event.trackKind
{ String } The kind of track -data
,audio
orvideo
.trackName
{ String } The track name. Currently unused and set to a uuid.
{
type: 'track',
name: 'enabled',
order: 22,
roomId: '5df02d890535377c38cfdeef',
status: 'connected',
accountId: '58c87b958b8f160100812b70',
trackKind: 'video',
trackName: '8bd80b33-34ab-4ac6-b2fd-23d51cfe9156'
}
status
{ String } The current status of the participant generating this event - eitherconnected
ordisconnected
.accountId
{ ObjectID } The id of the account generating the event.trackKind
{ String } The kind of track -data
,audio
orvideo
.trackName
{ String } The track name. Currently unused and set to a uuid.
{
type: 'track',
name: 'enabled',
order: 21,
roomId: '5df02d890535377c38cfdeef',
status: 'connected',
accountId: '58c87b958b8f160100812b70',
trackKind: 'video',
trackName: '8bd80b33-34ab-4ac6-b2fd-23d51cfe9156'
}
The Room definition
defaultAcl
is owner.delete
and there is no createAcl
defined for Rooms; Rooms must be created in-script using bypassCreateAcl()
.Alternatively, the Room definition may be extended with overriding
createAcl
, defaultAcl
and - incidentally - custom properties.org.objects.objects.insertOne({
label: 'Room',
name: 'room',
createAcl: 'account.public', // any user can create rooms.
properties: [{
name: 'c_ustom',
label: 'Custom',
type: 'String'
}]
})
Access to instances is provided using explicit
acl
writing. the shorthand import/export format can be used as well as the standard type
, target
, allow
properties. Anyone with read
access to the room instance is provided a token when reading the token
property. For example:org.objects.rooms.insertOne({
acl: [
'account.public.read', // any logged in account
'account.anonymous.read', // anyone anywhere
'role.developer.read', // developer role
`account.${emailToId('[email protected]')}.read`, // specific account (by id)
{ type: 1, target: emailToId('[email protected]'), allow: 4 } // long form
]
})
.bypassCreateAcl()
.execute()
function emailToId(email) {
return org.objects.accounts.readOne({ email }).skipAcl().grant('read').execute()._id
}
Some environment-level options are required to create rooms.
org.configuration.televisit.roomsEnabled
must be true in order to create rooms in an environment.org.configuration.televisit.maxConcurrentRooms
determines how many open rooms are allowed in a given environment.
To see current values for the above read current environment as an administrator (
return org.read('configuration.televisit')
)To create a room instance, write an acl and insert a room instance:
return org.objects.rooms.insertOne({
acl: [
`role.developer.read` // example.
]
}).lean(false).execute()
The Cortex room instance is now created and the
state
is "new"
. The provider room to which clients connect is opened asynchronously. Once this process has completed, the room's state
property will be set to "open"
and fire any room.after
script triggers ({type: 'room', name: 'created', ...}
).Participant may now use their tokens to connect to the remote room.
Current participant status is updated in the Room instance to reflect the state of connected participants as they connect, disconnect, add and pause tracks, etc. Participant status is updated prior to script triggers so the latest is available in room event triggers.
Example participants list where both are connected and streaming audio and video.
const doc = org.objects.room
.readOne('5df2cb2a020fd46a6351e66b')
.paths('participants.status', 'participants.audio', 'participants.video', 'participants.account.name')
.execute()
let json = {
"_id": "5df2cb2a020fd46a6351e66b",
"object": "room",
"participants": [
{
"_id": "5df2cb3d020fd46a6351e70b",
"account": {
"_id": "58c87b958b8f160100812b70",
"name": {
"additional": [],
"first": "Jane",
"last": "Doe"
},
"object": "account"
},
"audio": [
"connected"
],
"status": "connected",
"video": [
"connected"
]
},
{
"_id": "5df2cce5020fd46a6351ef86",
"account": {
"_id": "5da9ff0fff5c5eb553a557f1",
"name": {
"additional": [],
"first": "John",
"last": "Doe"
},
"object": "account"
},
"audio": [
"connected"
],
"status": "connected",
"video": [
"connected"
]
}
]
}
- The
status
of the participant isconnected
when they are connected to the room. - The
audio
andvideo
are arrays that containconnected
and/orpaused
.- When either of these tracks are removed,
connected
will no longer appear in the array, butpaused
may linger andshould be ignored.
- When a participant status is
disconnected
:- Ignore the values in
audio
andvideo
. - The participant remains in the list.
Last modified 2yr ago