Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CF & Video SDKs: Allow user to update media with renegotiation #1137

Merged
merged 112 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 102 commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
451667e
testing
jpsantosbh Jul 17, 2024
0bbb68a
Merge branch 'main' into joao/renegotiation
jpsantosbh Jul 22, 2024
56ac7b5
cleanup
jpsantosbh Jul 22, 2024
b73d367
Merge branch 'main' into joao/renegotiation
jpsantosbh Sep 9, 2024
d312dc7
test hacking renegotiation passing
jpsantosbh Sep 11, 2024
f1cfd61
added renegotiateMedia
jpsantosbh Oct 2, 2024
9109a44
Merge branch 'main' into joao/renegotiation
jpsantosbh Oct 8, 2024
96b0c42
fix getMediaConstraints
jpsantosbh Oct 14, 2024
8607fa6
Merge branch 'joao/fix_media_constraints' into joao/renegotiation
jpsantosbh Oct 14, 2024
02b2d5c
start with offering true
jpsantosbh Oct 14, 2024
1249777
check MCU
jpsantosbh Oct 14, 2024
e350878
Merge branch 'main' into joao/renegotiation
jpsantosbh Oct 14, 2024
b7fcd79
changeset
jpsantosbh Oct 14, 2024
5708919
fixes
jpsantosbh Oct 15, 2024
46b833c
Update internal/e2e-js/tests/callfabric/renegotiation.spec.ts
jpsantosbh Oct 21, 2024
cbdacc0
Update packages/webrtc/src/RTCPeer.ts
jpsantosbh Oct 21, 2024
3a0be5f
Update packages/webrtc/src/RTCPeer.ts
jpsantosbh Oct 21, 2024
dec5f50
Update internal/e2e-js/tests/callfabric/renegotiation.spec.ts
jpsantosbh Oct 21, 2024
e5485e7
added to the public contract
jpsantosbh Oct 21, 2024
6231930
refactor
jpsantosbh Oct 21, 2024
2ca56ad
add to playground
jpsantosbh Oct 21, 2024
fc3803a
Merge branch 'main' into joao/renegotiation
jpsantosbh Oct 21, 2024
e821a1c
merge fix
jpsantosbh Oct 21, 2024
fb875a6
Update packages/webrtc/src/RTCPeer.ts
jpsantosbh Oct 22, 2024
a5ab32e
Update internal/playground-js/src/fabric/index.js
jpsantosbh Oct 22, 2024
3b9e3ea
use updateConstraints
jpsantosbh Oct 22, 2024
a89457a
Update packages/webrtc/src/BaseConnection.ts
jpsantosbh Oct 23, 2024
b401750
renaming
jpsantosbh Oct 23, 2024
e15d215
Update internal/e2e-js/tests/callfabric/renegotiation.spec.ts
jpsantosbh Oct 24, 2024
dd97f47
Merge branch 'main' into joao/renegotiation
jpsantosbh Oct 24, 2024
dd8fd6a
review
jpsantosbh Oct 24, 2024
613ce32
fix interface
jpsantosbh Oct 24, 2024
0833288
testing
jpsantosbh Jul 17, 2024
da30fef
added to the public contract
jpsantosbh Oct 21, 2024
4426dd7
fix interface
jpsantosbh Oct 24, 2024
dc1e18c
rengotiate with different direction
iAmmar7 Oct 25, 2024
e8eee01
fix build
iAmmar7 Oct 25, 2024
125ee6f
refactor the enableVideo logi
iAmmar7 Oct 25, 2024
b948222
refactor video media
iAmmar7 Oct 25, 2024
0d89795
correct api usage in e2e test
iAmmar7 Oct 25, 2024
4ee636d
update e2e tests
iAmmar7 Oct 25, 2024
73df834
update playwright config
iAmmar7 Oct 25, 2024
5e0c6a0
disable video method
iAmmar7 Oct 25, 2024
02c4455
refactor the media methods
iAmmar7 Oct 28, 2024
2cac04f
refactor types
iAmmar7 Oct 28, 2024
34ad127
include more e2e tests
iAmmar7 Oct 28, 2024
3f225d7
remove commits
iAmmar7 Oct 28, 2024
3ceec19
include disable video in e2e tests
iAmmar7 Oct 28, 2024
ba7b19d
update the default value for disableVideo method
iAmmar7 Oct 28, 2024
be13512
run tests
iAmmar7 Oct 28, 2024
9aac270
comment test issue
iAmmar7 Oct 28, 2024
99f32b0
set the offer when adding the transceiver
iAmmar7 Oct 29, 2024
af8c48e
refactor test
iAmmar7 Oct 29, 2024
f98ac95
include audio renegotiation as well
iAmmar7 Oct 29, 2024
4b97f40
update e2e test
iAmmar7 Oct 29, 2024
b640911
add negotiate audio tests
iAmmar7 Oct 29, 2024
ffd0799
remove branch from the CI
iAmmar7 Oct 29, 2024
8f43a77
update the changeset
iAmmar7 Oct 29, 2024
9f92488
update the changeset
iAmmar7 Oct 29, 2024
9d6c621
include test in the callfabric project
iAmmar7 Oct 29, 2024
8097d75
remove the enable video button
iAmmar7 Oct 29, 2024
0ea3fa0
remove helper changes
iAmmar7 Oct 29, 2024
1a5a4f4
remove helper changes
iAmmar7 Oct 29, 2024
02f95c9
introduce promise to wait for renegotiation
iAmmar7 Oct 31, 2024
38ad7e5
include sdp unit tests
iAmmar7 Oct 31, 2024
349672b
refacor video negotiation test
iAmmar7 Oct 31, 2024
d676c10
update negotiate audio test
iAmmar7 Oct 31, 2024
098bd5b
remove only from e2e test
iAmmar7 Oct 31, 2024
d965071
dedicated renegotiation project for playwright
iAmmar7 Oct 31, 2024
2eeaf3e
check for negotiation update
iAmmar7 Oct 31, 2024
fcb6425
refactor the toggleMedia code
iAmmar7 Oct 31, 2024
bca43b8
fix unit tests
iAmmar7 Nov 1, 2024
eecf205
merge with main
iAmmar7 Dec 16, 2024
4659e0a
refactor the constraints and stream update
iAmmar7 Dec 18, 2024
e2cc84a
add more comments
iAmmar7 Dec 18, 2024
c191f10
introduce the updateMedia method with media renegotitation
iAmmar7 Dec 19, 2024
52f5542
add set audio/video direction method
iAmmar7 Dec 19, 2024
3be2a36
fix build
iAmmar7 Dec 19, 2024
73866bf
fix the renegotiate video test
iAmmar7 Dec 20, 2024
583e998
add audio negotiation tests
iAmmar7 Dec 20, 2024
7a5e9c9
update test flag
iAmmar7 Dec 20, 2024
78252c2
refactor e2e tests
iAmmar7 Dec 20, 2024
8b1e359
stop the remote stream track
iAmmar7 Dec 21, 2024
209bd08
refactor the upsert transceiver method
iAmmar7 Dec 23, 2024
30fb37d
better cleanup logic for the playwright fixture
iAmmar7 Dec 23, 2024
df70207
resolve the client disconnect promise if not present
iAmmar7 Dec 23, 2024
43e9d7f
check the room session id before leaving
iAmmar7 Dec 23, 2024
c94446c
refactor the e2e test utilities
iAmmar7 Dec 23, 2024
046164f
Merge branch 'main' into aa/renegotiation
iAmmar7 Dec 23, 2024
2a6053d
check for roomSessionId before leaving
iAmmar7 Dec 23, 2024
e7c7f4e
fix the test fixture problem
iAmmar7 Dec 26, 2024
c910e4c
add e2e for Video SDK
iAmmar7 Dec 26, 2024
a891262
remove changeset
iAmmar7 Dec 26, 2024
2a1b952
add changeset
iAmmar7 Dec 26, 2024
a8e3d35
add test comment
iAmmar7 Dec 26, 2024
395520a
refactor getStats method
iAmmar7 Dec 27, 2024
b23b872
merge with main
iAmmar7 Dec 27, 2024
0f1b595
merge with main
iAmmar7 Dec 30, 2024
09b334b
fix build
iAmmar7 Dec 30, 2024
bb9dc10
remove the ts-ignore
iAmmar7 Dec 30, 2024
416db46
merge with main
iAmmar7 Jan 2, 2025
2306eb2
Rename buildVideoWithVideoSdk.spec.ts to buildVideoWithVideoSDK.spec.ts
iAmmar7 Jan 2, 2025
7cdcab0
remove the enable flag from the API
iAmmar7 Jan 21, 2025
1535833
Merge branch 'main' into aa/renegotiation
iAmmar7 Jan 21, 2025
22ab1e7
update api usage in video test
iAmmar7 Jan 21, 2025
08a60a5
PR feedback
iAmmar7 Jan 21, 2025
fb2091a
fix test name
iAmmar7 Jan 21, 2025
1c1d7c5
remove unnecessary if else check
iAmmar7 Jan 22, 2025
a90e6a4
Merge branch 'main' into aa/renegotiation
iAmmar7 Jan 30, 2025
1bc70c8
PR feedback: comments update
iAmmar7 Jan 30, 2025
f1a68e3
PR feedback: comment update
iAmmar7 Jan 30, 2025
fc57981
PR feedback: comment update
iAmmar7 Jan 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .changeset/tough-doors-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
'@signalwire/webrtc': minor
'@signalwire/core': minor
'@signalwire/js': minor
---

Fabric and Video SDK: Introduce an update media APIs with renegotiation

```text

await updateMedia({
audio: {
enable: true,
direction: 'send' | 'sendrecv',
constraints?: MediaTrackConstraints
},
video: {
enable: false
direction: 'none' | 'receive'
giavac marked this conversation as resolved.
Show resolved Hide resolved
}
})

Either "audio" or "video" is required with "enable" and "direction" properties.
The "constraints" can only be passed if the "enable" is "true".

await setVideoDirection('send' | 'sendrecv' | 'none' | 'receive')

await setAudioDirection('send' | 'sendrecv' | 'none' | 'receive')

```
1 change: 1 addition & 0 deletions .github/workflows/browser-js-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
audience,
reattach,
callfabric,
renegotiation,
videoElement,
v2WebRTC,
]
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/browser-js-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
# audience,
# reattach,
callfabric,
renegotiation,
videoElement,
v2WebRTC,
]
Expand Down
15 changes: 13 additions & 2 deletions internal/e2e-js/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,14 @@ const callfabricTests = [
'videoRoom.spec.ts',
'videoRoomLayout.spec.ts',
]
const renegotiationTests = [
'roomSessionUpdateMedia.spec.ts',
'renegotiateAudio.spec.ts',
'renegotiateVideo.spec.ts',
]
const videoElementTests = [
'buildVideoWithVideoSdk.spec.ts',
'buildVideoWithFabricSdk.spec.ts',
'buildVideoWithVideoSDK.spec.ts',
'buildVideoWithFabricSDK.spec.ts',
]
const v2WebRTC = ['v2WebrtcFromRest.spec.ts', 'webrtcCalling.spec.ts']

Expand Down Expand Up @@ -89,6 +94,7 @@ const config: PlaywrightTestConfig = {
...audienceTests,
...reattachTests,
...callfabricTests,
...renegotiationTests,
...videoElementTests,
...v2WebRTC,
],
Expand Down Expand Up @@ -128,6 +134,11 @@ const config: PlaywrightTestConfig = {
use: useDesktopChrome,
testMatch: callfabricTests,
},
{
name: 'renegotiation',
use: useDesktopChrome,
testMatch: renegotiationTests,
},
{
name: 'videoElement',
use: useDesktopChrome,
Expand Down
249 changes: 249 additions & 0 deletions internal/e2e-js/tests/callfabric/renegotiateAudio.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
import { uuid } from '@signalwire/core'
import { test, expect } from '../../fixtures'
import {
SERVER_URL,
createCFClient,
dialAddress,
expectMCUVisible,
expectStatWithPolling,
getStats,
waitForStabilizedStats,
} from '../../utils'
import { CallFabricRoomSession } from '@signalwire/js'

test.describe('CallFabric Audio Renegotiation', () => {
test('it should enable audio with "sendrecv" and then disable with "inactive"', async ({
createCustomPage,
resource,
}) => {
const page = await createCustomPage({ name: '[page]' })
await page.goto(SERVER_URL)

const roomName = `e2e-video-room_${uuid()}`
giavac marked this conversation as resolved.
Show resolved Hide resolved
await resource.createVideoRoomResource(roomName)

await createCFClient(page)

// Dial an address with video only channel
await dialAddress(page, {
address: `/public/${roomName}?channel=video`,
dialOptions: {
audio: false,
negotiateAudio: false,
},
})

// Expect MCU is visible
giavac marked this conversation as resolved.
Show resolved Hide resolved
await expectMCUVisible(page)

const stats1 = await getStats(page)
expect(stats1.outboundRTP.video?.packetsSent).toBeGreaterThan(0)
expect(stats1.inboundRTP.video?.packetsReceived).toBeGreaterThan(0)
expect(stats1.outboundRTP.audio?.packetsSent).toBe(0)
expect(stats1.inboundRTP.audio?.packetsReceived).toBe(0)

await page.evaluate(async () => {
// @ts-expect-error
const cfRoomSession: CallFabricRoomSession = window._roomObj
await cfRoomSession.setAudioDirection('sendrecv')
})

await expectStatWithPolling(page, {
propertyPath: 'outboundRTP.video.packetsSent',
matcher: 'toBeGreaterThan',
expected: 0,
})
await expectStatWithPolling(page, {
propertyPath: 'inboundRTP.video.packetsReceived',
matcher: 'toBeGreaterThan',
expected: 0,
})
await expectStatWithPolling(page, {
propertyPath: 'outboundRTP.audio.packetsSent',
matcher: 'toBeGreaterThan',
expected: 0,
})
await expectStatWithPolling(page, {
propertyPath: 'inboundRTP.audio.packetsReceived',
matcher: 'toBeGreaterThan',
expected: 0,
})

await test.step('it should disable the audio with "inactive"', async () => {
await page.evaluate(async () => {
// @ts-expect-error
const cfRoomSession: CallFabricRoomSession = window._roomObj
await cfRoomSession.updateMedia({
audio: { enable: false, direction: 'none' },
})
})

await expectStatWithPolling(page, {
propertyPath: 'outboundRTP.video.packetsSent',
matcher: 'toBeGreaterThan',
expected: 0,
})
await expectStatWithPolling(page, {
propertyPath: 'inboundRTP.video.packetsReceived',
matcher: 'toBeGreaterThan',
expected: 0,
})
await waitForStabilizedStats(page, {
propertyPath: 'outboundRTP.audio.packetsSent',
})
await waitForStabilizedStats(page, {
propertyPath: 'inboundRTP.audio.packetsReceived',
})
})
})

test('it should enable audio with "sendonly" and then disable with "recvonly"', async ({
createCustomPage,
resource,
}) => {
const page = await createCustomPage({ name: '[page]' })
await page.goto(SERVER_URL)

const roomName = `e2e-video-room_${uuid()}`
await resource.createVideoRoomResource(roomName)

await createCFClient(page)

// Dial an address with video only channel
await dialAddress(page, {
address: `/public/${roomName}?channel=video`,
dialOptions: {
audio: false,
negotiateAudio: false,
giavac marked this conversation as resolved.
Show resolved Hide resolved
},
})

// Expect MCU is visible
await expectMCUVisible(page)

const stats1 = await getStats(page)
expect(stats1.outboundRTP.video?.packetsSent).toBeGreaterThan(0)
expect(stats1.inboundRTP.video?.packetsReceived).toBeGreaterThan(0)
expect(stats1.outboundRTP.audio?.packetsSent).toBe(0)
expect(stats1.inboundRTP.audio?.packetsReceived).toBe(0)

await page.evaluate(async () => {
// @ts-expect-error
const cfRoomSession: CallFabricRoomSession = window._roomObj
await cfRoomSession.setAudioDirection('send')
})

const stats2 = await getStats(page)
expect(stats2.outboundRTP).toHaveProperty('video')
expect(stats2.inboundRTP).toHaveProperty('video')
await expectStatWithPolling(page, {
propertyPath: 'outboundRTP.audio.packetsSent',
matcher: 'toBeGreaterThan',
expected: 0,
})
expect(stats2.inboundRTP.audio?.packetsReceived).toBe(0)

await test.step('it should disable the audio with "recvonly"', async () => {
await page.evaluate(async () => {
// @ts-expect-error
const cfRoomSession: CallFabricRoomSession = window._roomObj
await cfRoomSession.updateMedia({
audio: { enable: false, direction: 'receive' },
giavac marked this conversation as resolved.
Show resolved Hide resolved
})
})

const stats3 = await getStats(page)
expect(stats3.outboundRTP).toHaveProperty('video')
expect(stats3.inboundRTP).toHaveProperty('video')
await waitForStabilizedStats(page, {
propertyPath: 'outboundRTP.audio.packetsSent',
})
await expectStatWithPolling(page, {
propertyPath: 'inboundRTP.audio.packetsReceived',
matcher: 'toBeGreaterThan',
expected: 0,
})
})
})

test('it should enable video with "recvonly" and then disable with "inactive"', async ({
createCustomPage,
resource,
}) => {
const page = await createCustomPage({ name: '[page]' })
await page.goto(SERVER_URL)

const roomName = `e2e-video-room_${uuid()}`
await resource.createVideoRoomResource(roomName)

await createCFClient(page)

// Dial an address with video only channel
await dialAddress(page, {
address: `/public/${roomName}?channel=video`,
dialOptions: {
audio: false,
negotiateAudio: false,
giavac marked this conversation as resolved.
Show resolved Hide resolved
},
})

// Expect MCU is visible
await expectMCUVisible(page)

const stats1 = await getStats(page)
expect(stats1.outboundRTP.video?.packetsSent).toBeGreaterThan(0)
expect(stats1.inboundRTP.video?.packetsReceived).toBeGreaterThan(0)
expect(stats1.outboundRTP.audio?.packetsSent).toBe(0)
expect(stats1.inboundRTP.audio?.packetsReceived).toBe(0)

await page.evaluate(async () => {
// @ts-expect-error
const cfRoomSession: CallFabricRoomSession = window._roomObj
await cfRoomSession.setAudioDirection('receive')
})

const stats2 = await getStats(page)
await expectStatWithPolling(page, {
propertyPath: 'outboundRTP.video.packetsSent',
matcher: 'toBeGreaterThan',
expected: 0,
})
await expectStatWithPolling(page, {
propertyPath: 'inboundRTP.video.packetsReceived',
matcher: 'toBeGreaterThan',
expected: 0,
})
expect(stats2.outboundRTP.audio?.packetsSent).toBe(0)
await expectStatWithPolling(page, {
propertyPath: 'inboundRTP.audio.packetsReceived',
matcher: 'toBeGreaterThan',
expected: 0,
})

await test.step('it should disable the audio with "inactive"', async () => {
await page.evaluate(async () => {
// @ts-expect-error
const cfRoomSession: CallFabricRoomSession = window._roomObj
await cfRoomSession.updateMedia({
audio: { enable: false, direction: 'none' },
giavac marked this conversation as resolved.
Show resolved Hide resolved
})
})

const stats3 = await getStats(page)
await expectStatWithPolling(page, {
propertyPath: 'outboundRTP.video.packetsSent',
matcher: 'toBeGreaterThan',
expected: 0,
})
await expectStatWithPolling(page, {
propertyPath: 'inboundRTP.video.packetsReceived',
matcher: 'toBeGreaterThan',
expected: 0,
})
expect(stats3.outboundRTP.audio?.packetsSent).toBe(0)
await waitForStabilizedStats(page, {
propertyPath: 'inboundRTP.audio.packetsReceived',
})
})
})
})
Loading
Loading