Skip to content

Commit 73528c0

Browse files
authored
Realtime Video SDK with new interface (#886)
* Realtime Video SDK with new interface * room session with the new interface * remove auto subscribe consumer * fix unit tests for video and room session * room member instance * unit tests for room session member * fix stack test * room session playback realtime-api instance * room session recording realtime-api instance * room session stream realtime-api instance * explicit methods for the realtime-api * fix build issue * separate workers for playback, recording and stream * video playground with the new interface * decorated promise for room session playback api * decorated promise for room session recording api * decorated promise for room session stream api * fix unit test cases * unit tests for decorated promises * update video play ground with decorated promise * fix e2e test case for the video * fix unit test * do not unsubscribe events * fix unit test * include changeset * streaming getter for room session * rename types
1 parent 02106e1 commit 73528c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+4596
-1441
lines changed

.changeset/fluffy-birds-yawn.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
'@signalwire/realtime-api': major
3+
'@signalwire/core': major
4+
---
5+
6+
- New interface for the realtime-api Video SDK.
7+
- Listen function with _video_, _room_, _playback_, _recording_, and _stream_ objects.
8+
- Listen param with `room.play`, `room.startRecording`, and `room.startStream` functions.
9+
- Decorated promise for `room.play`, `room.startRecording`, and `room.startStream` functions.
10+
11+
```js
12+
import { SignalWire } from '@signalwire/realtime-api'
13+
14+
const client = await SignalWire({ project, token })
15+
16+
const unsub = await client.video.listen({
17+
onRoomStarted: async (roomSession) => {
18+
console.log('room session started', roomSession)
19+
20+
await roomSession.listen({
21+
onPlaybackStarted: (playback) => {
22+
console.log('plyaback started', playback)
23+
}
24+
})
25+
26+
// Promise resolves when playback ends.
27+
await roomSession.play({ url: "http://.....", listen: { onEnded: () => {} } })
28+
},
29+
onRoomEnded: (roomSession) => {
30+
console.log('room session ended', roomSession)
31+
}
32+
})
33+
```

internal/e2e-realtime-api/src/playwright/video.test.ts

+24-22
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { test, expect } from '@playwright/test'
22
import { uuid } from '@signalwire/core'
3-
import { Video } from '@signalwire/realtime-api'
3+
import { SignalWire } from '@signalwire/realtime-api'
44
import { createNewTabRoomSession } from './videoUtils'
55

66
test.describe('Video', () => {
77
test('should join the room and listen for events', async ({ browser }) => {
8-
const videoClient = new Video.Client({
9-
// @ts-expect-error
8+
const client = await SignalWire({
109
host: process.env.RELAY_HOST,
1110
project: process.env.RELAY_PROJECT as string,
1211
token: process.env.RELAY_TOKEN as string,
@@ -18,19 +17,20 @@ test.describe('Video', () => {
1817

1918
const roomSessionCreated = new Map<string, any>()
2019
const findRoomSessionsByPrefix = async () => {
21-
const { roomSessions } = await videoClient.getRoomSessions()
20+
const { roomSessions } = await client.video.getRoomSessions()
2221
return roomSessions.filter((r) => r.name.startsWith(prefix))
2322
}
2423

25-
videoClient.on('room.started', async (roomSession) => {
26-
console.log('Room started', roomSession.id)
27-
if (roomSession.name.startsWith(prefix)) {
28-
roomSessionCreated.set(roomSession.id, roomSession)
29-
}
30-
})
31-
32-
videoClient.on('room.ended', async (roomSession) => {
33-
console.log('Room ended', roomSession.id)
24+
await client.video.listen({
25+
onRoomStarted: (roomSession) => {
26+
console.log('Room started', roomSession.id)
27+
if (roomSession.name.startsWith(prefix)) {
28+
roomSessionCreated.set(roomSession.id, roomSession)
29+
}
30+
},
31+
onRoomEnded: (roomSession) => {
32+
console.log('Room ended', roomSession.id)
33+
},
3434
})
3535

3636
const roomSessionsAtStart = await findRoomSessionsByPrefix()
@@ -72,24 +72,26 @@ test.describe('Video', () => {
7272
for (let index = 0; index < roomSessionsRunning.length; index++) {
7373
const rs = roomSessionsRunning[index]
7474

75-
await new Promise((resolve) => {
76-
rs.on('recording.ended', noop)
77-
rs.on('playback.ended', noop)
78-
rs.on('room.updated', noop)
79-
rs.on('room.subscribed', resolve)
75+
await new Promise(async (resolve) => {
76+
await rs.listen({
77+
onRecordingEnded: noop,
78+
onPlaybackEnded: noop,
79+
onRoomUpdated: noop,
80+
onRoomSubscribed: resolve,
81+
})
8082
})
8183

8284
await new Promise<void>(async (resolve) => {
83-
rs.on('recording.ended', () => {
84-
resolve()
85+
await rs.listen({
86+
onRecordingEnded: () => resolve(),
8587
})
8688
const { recordings } = await rs.getRecordings()
8789
await Promise.all(recordings.map((r) => r.stop()))
8890
})
8991

9092
await new Promise<void>(async (resolve) => {
91-
rs.on('playback.ended', () => {
92-
resolve()
93+
await rs.listen({
94+
onPlaybackEnded: () => resolve(),
9395
})
9496
const { playbacks } = await rs.getPlaybacks()
9597
await Promise.all(playbacks.map((p) => p.stop()))

internal/playground-realtime-api/src/with-events/index.ts

+76-26
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,108 @@
1-
import { Video } from '@signalwire/realtime-api'
1+
import { Video, SignalWire } from '@signalwire/realtime-api'
22

33
async function run() {
44
try {
5-
const video = new Video.Client({
6-
// @ts-expect-error
5+
const client = await SignalWire({
76
host: process.env.HOST || 'relay.swire.io',
87
project: process.env.PROJECT as string,
98
token: process.env.TOKEN as string,
109
debug: {
11-
logWsTraffic: true,
10+
// logWsTraffic: true,
1211
},
1312
})
1413

15-
const roomSessionHandler = (room: Video.RoomSession) => {
16-
console.log('Room started --->', room.id, room.name, room.members)
17-
room.on('room.subscribed', (room) => {
18-
console.log('Room Subscribed --->', room.id, room.members)
19-
})
14+
const unsubVideo = await client.video.listen({
15+
onRoomStarted(room) {
16+
console.log('🟢 onRoomStarted 🟢', room.id, room.name)
17+
roomSessionHandler(room)
18+
},
19+
onRoomEnded(room) {
20+
console.log('🔴 onRoomEnded 🔴', room.id, room.name)
21+
},
22+
})
2023

21-
room.on('member.updated', () => {
22-
console.log('Member updated --->')
23-
})
24+
const roomSessionHandler = async (room: Video.RoomSession) => {
25+
const unsubRoom = await room.listen({
26+
onRoomSubscribed: (room) => {
27+
console.log('onRoomSubscribed', room.id, room.name)
28+
},
29+
onRoomStarted: (room) => {
30+
console.log('onRoomStarted', room.id, room.name)
31+
},
32+
onRoomUpdated: (room) => {
33+
console.log('onRoomUpdated', room.id, room.name)
34+
},
35+
onRoomEnded: (room) => {
36+
console.log('onRoomEnded', room.id, room.name)
37+
},
38+
onMemberJoined: async (member) => {
39+
console.log('onMemberJoined --->', member.id, member.name)
2440

25-
room.on('member.joined', (member) => {
26-
console.log('Member joined --->', member.id, member.name)
27-
})
41+
const play = await room
42+
.play({
43+
url: 'https://cdn.signalwire.com/default-music/welcome.mp3',
44+
listen: {
45+
onStarted: (playback) => {
46+
console.log('onStarted', playback.id, playback.url)
47+
},
48+
onUpdated: (playback) => {
49+
console.log('onUpdated', playback.id, playback.url)
50+
},
51+
onEnded: (playback) => {
52+
console.log('onEnded', playback.id, playback.url)
53+
},
54+
},
55+
})
56+
.onStarted()
57+
console.log('play', play.id)
58+
59+
setTimeout(async () => {
60+
await play.pause()
2861

29-
room.on('member.left', (member) => {
30-
console.log('Member left --->', member.id, member.name)
62+
setTimeout(async () => {
63+
await play.stop()
64+
}, 5000)
65+
}, 10000)
66+
},
67+
onMemberUpdated: (member) => {
68+
console.log('onMemberUpdated', member.id, member.name)
69+
},
70+
onMemberTalking: (member) => {
71+
console.log('onMemberTalking', member.id, member.name)
72+
},
73+
onMemberLeft: (member) => {
74+
console.log('onMemberLeft', member.id, member.name)
75+
},
76+
onPlaybackStarted: (playback) => {
77+
console.log('onPlaybackStarted', playback.id, playback.url)
78+
},
79+
onPlaybackUpdated: (playback) => {
80+
console.log('onPlaybackUpdated', playback.id, playback.url)
81+
},
82+
onPlaybackEnded: (playback) => {
83+
console.log('onPlaybackEnded', playback.id, playback.url)
84+
},
3185
})
3286
}
33-
video.on('room.started', roomSessionHandler)
34-
35-
video.on('room.ended', (room) => {
36-
console.log('🔴 ROOOM ENDED 🔴', `${room}`, room.name)
37-
})
3887

39-
video._session.on('session.connected', () => {
88+
// @ts-expect-error
89+
client.video._client.session.on('session.connected', () => {
4090
console.log('SESSION CONNECTED!')
4191
})
4292

4393
console.log('Client Running..')
4494

45-
const { roomSessions } = await video.getRoomSessions()
95+
const { roomSessions } = await client.video.getRoomSessions()
4696

47-
roomSessions.forEach(async (room: any) => {
97+
roomSessions.forEach(async (room: Video.RoomSession) => {
4898
console.log('>> Room Session: ', room.id, room.displayName)
4999
roomSessionHandler(room)
50100

51101
const r = await room.getMembers()
52102
console.log('Members:', r)
53103
// await room.removeAllMembers()
54104

55-
const { roomSession } = await video.getRoomSessionById(room.id)
105+
const { roomSession } = await client.video.getRoomSessionById(room.id)
56106
console.log('Room Session By ID:', roomSession.displayName)
57107
})
58108
} catch (error) {

internal/stack-tests/src/video/app.ts

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
import { Video } from '@signalwire/realtime-api'
1+
import { SignalWire } from '@signalwire/realtime-api'
22
import tap from 'tap'
33

44
async function run() {
55
try {
6-
const video = new Video.Client({
7-
// @ts-expect-error
6+
const client = await SignalWire({
87
host: process.env.RELAY_HOST || 'relay.swire.io',
98
project: process.env.RELAY_PROJECT as string,
109
token: process.env.RELAY_TOKEN as string,
1110
})
1211

13-
tap.ok(video.on, 'video.on is defined')
14-
tap.ok(video.once, 'video.once is defined')
15-
tap.ok(video.off, 'video.off is defined')
16-
tap.ok(video.subscribe, 'video.subscribe is defined')
17-
tap.ok(video.removeAllListeners, 'video.removeAllListeners is defined')
12+
tap.ok(client.video, 'client.video is defined')
13+
tap.ok(client.video.listen, 'client.video.listen is defined')
14+
tap.ok(client.video.getRoomSessions, 'video.getRoomSessions is defined')
15+
tap.ok(
16+
client.video.getRoomSessionById,
17+
'video.getRoomSessionById is defined'
18+
)
19+
tap.ok(client.disconnect, 'video.disconnect is defined')
1820

1921
process.exit(0)
2022
} catch (error) {

packages/core/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export type {
8989
SDKActions,
9090
ReduxComponent,
9191
} from './redux/interfaces'
92+
export type { SDKStore } from './redux'
9293
export type { ToExternalJSONResult } from './utils'
9394
export * as actions from './redux/actions'
9495
export * as sagaHelpers from './redux/utils/sagaHelpers'

packages/core/src/types/videoLayout.ts

+6
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@ import { VideoPosition } from '..'
33
import type { CamelToSnakeCase, ToInternalVideoEvent } from './utils'
44

55
export type LayoutChanged = 'layout.changed'
6+
export type OnLayoutChanged = 'onLayoutChanged'
67

78
/**
89
* List of public event names
910
*/
1011
export type VideoLayoutEventNames = LayoutChanged
1112

13+
/**
14+
* List of public listener names
15+
*/
16+
export type VideoLayoutListenerNames = OnLayoutChanged
17+
1218
/**
1319
* List of internal events
1420
* @internal

packages/core/src/types/videoMember.ts

+42-3
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,15 @@ export type MemberTalking = 'member.talking'
6161
export type MemberPromoted = 'member.promoted'
6262
export type MemberDemoted = 'member.demoted'
6363

64-
// Generated by the SDK
64+
/**
65+
* Public listener types
66+
*/
67+
export type OnMemberJoined = 'onMemberJoined'
68+
export type OnMemberLeft = 'onMemberLeft'
69+
export type OnMemberUpdated = 'onMemberUpdated'
70+
export type OnMemberTalking = 'onMemberTalking'
71+
export type OnMemberPromoted = 'onMemberPromoted'
72+
export type OnMemberDemoted = 'onMemberDemoted'
6573

6674
/**
6775
* @privateRemarks
@@ -72,13 +80,25 @@ export type MemberDemoted = 'member.demoted'
7280
* room.
7381
*/
7482
export type MemberListUpdated = 'memberList.updated'
83+
export type OnMemberListUpdated = 'onMemberListUpdated'
7584

7685
/**
7786
* See {@link MEMBER_UPDATED_EVENTS} for the full list of events.
7887
*/
79-
export type MemberUpdatedEventNames = typeof MEMBER_UPDATED_EVENTS[number]
88+
export type MemberUpdatedEventNames = (typeof MEMBER_UPDATED_EVENTS)[number]
8089
export type MemberTalkingStarted = 'member.talking.started'
8190
export type MemberTalkingEnded = 'member.talking.ended'
91+
92+
export type OnMemberDeaf = 'onMemberDeaf'
93+
export type OnMemberVisible = 'onMemberVisible'
94+
export type OnMemberAudioMuted = 'onMemberAudioMuted'
95+
export type OnMemberVideoMuted = 'onMemberVideoMuted'
96+
export type OnMemberInputVolume = 'onMemberInputVolume'
97+
export type OnMemberOutputVolume = 'onMemberOutputVolume'
98+
export type OnMemberInputSensitivity = 'onMemberInputSensitivity'
99+
export type OnMemberTalkingStarted = 'onMemberTalkingStarted'
100+
export type OnMemberTalkingEnded = 'onMemberTalkingEnded'
101+
82102
/**
83103
* Use `member.talking.started` instead
84104
* @deprecated
@@ -97,6 +117,11 @@ export type MemberTalkingEventNames =
97117
| MemberTalkingStart
98118
| MemberTalkingStop
99119

120+
export type MemberTalkingListenerNames =
121+
| OnMemberTalking
122+
| OnMemberTalkingStarted
123+
| OnMemberTalkingEnded
124+
100125
/**
101126
* List of public events
102127
*/
@@ -108,8 +133,22 @@ export type VideoMemberEventNames =
108133
| MemberTalkingEventNames
109134
| MemberListUpdated
110135

136+
export type VideoMemberListenerNames =
137+
| OnMemberJoined
138+
| OnMemberLeft
139+
| OnMemberUpdated
140+
| OnMemberDeaf
141+
| OnMemberVisible
142+
| OnMemberAudioMuted
143+
| OnMemberVideoMuted
144+
| OnMemberInputVolume
145+
| OnMemberOutputVolume
146+
| OnMemberInputSensitivity
147+
| MemberTalkingListenerNames
148+
| OnMemberListUpdated
149+
111150
export type InternalMemberUpdatedEventNames =
112-
typeof INTERNAL_MEMBER_UPDATED_EVENTS[number]
151+
(typeof INTERNAL_MEMBER_UPDATED_EVENTS)[number]
113152

114153
/**
115154
* List of internal events

0 commit comments

Comments
 (0)