Add native self-hosted instance connection to fluxer_desktop
Trimmed monorepo checkout (fluxer_desktop + packages/voice_engine_v2 + tools/ci) with a "Connect to a Different Server" menu item and popout that lets the desktop app switch to any self-hosted Fluxer instance, plus fixes for well-known discovery on single-domain self-hosted deployments and a false-positive ERR_ABORTED on same-origin client redirects during the switch. Defaults to chat.fluxr.chat and uses an isolated userData directory from the official build.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "basic_session",
|
||||
"events": [
|
||||
{
|
||||
"type": "microphone.publishRequested",
|
||||
"options": {
|
||||
"deviceId": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
{
|
||||
"type": "microphone.publishSucceeded",
|
||||
"operationId": 2
|
||||
},
|
||||
{
|
||||
"type": "gateway.voiceStateUpdated",
|
||||
"voiceState": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-1",
|
||||
"userId": "user-1",
|
||||
"sessionId": "session-1",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false,
|
||||
"selfVideo": false,
|
||||
"selfStream": false,
|
||||
"suppress": false,
|
||||
"requestToSpeakTimestamp": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"connectionStatus": "connected",
|
||||
"activeUrl": "wss://voice.example.test",
|
||||
"microphoneStatus": "published",
|
||||
"microphoneDeviceId": "default",
|
||||
"gatewayChannelId": "channel-1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"version": 18,
|
||||
"methods": [
|
||||
"isSupported",
|
||||
"getCapabilities",
|
||||
"prewarm",
|
||||
"getHardwareEncoderCapabilities",
|
||||
"connect",
|
||||
"disconnect",
|
||||
"isConnected",
|
||||
"publishMicrophone",
|
||||
"pushPcm",
|
||||
"publishScreen",
|
||||
"updateScreenShareEncoding",
|
||||
"unpublishScreen",
|
||||
"publishScreenAudio",
|
||||
"pushScreenAudioPcm",
|
||||
"pushScreenAudioFloat",
|
||||
"unpublishScreenAudio",
|
||||
"setMicEnabled",
|
||||
"setSpeakingDetection",
|
||||
"listAudioInputDevices",
|
||||
"listAudioOutputDevices",
|
||||
"setAudioOutputDevice",
|
||||
"setParticipantVolume",
|
||||
"setRemoteTrackSubscription",
|
||||
"publishData",
|
||||
"listCameraDevices",
|
||||
"publishCamera",
|
||||
"updateCameraCapture",
|
||||
"publishNativeCameraSink",
|
||||
"publishProcessedCamera",
|
||||
"pushProcessedCameraFrame",
|
||||
"pushCameraBackgroundFrame",
|
||||
"clearCameraBackgroundFrame",
|
||||
"publishDeviceScreenShare",
|
||||
"unpublishCamera",
|
||||
"isPublishingCamera",
|
||||
"startCameraPreview",
|
||||
"stopCameraPreview",
|
||||
"getConnectionStats",
|
||||
"getVoiceEngineReadiness",
|
||||
"getAudioDeviceModuleState",
|
||||
"onEvent",
|
||||
"onVideoFrame"
|
||||
],
|
||||
"ipcChannels": {
|
||||
"isSupported": "voice-engine-v2:is-supported",
|
||||
"getCapabilities": "voice-engine-v2:get-capabilities",
|
||||
"prewarm": "voice-engine-v2:prewarm",
|
||||
"getHardwareEncoderCapabilities": "voice-engine-v2:get-hardware-encoder-capabilities",
|
||||
"connect": "voice-engine-v2:connect",
|
||||
"disconnect": "voice-engine-v2:disconnect",
|
||||
"isConnected": "voice-engine-v2:is-connected",
|
||||
"publishMicrophone": "voice-engine-v2:publish-microphone",
|
||||
"pushPcm": "voice-engine-v2:push-pcm",
|
||||
"publishScreen": "voice-engine-v2:publish-screen",
|
||||
"updateScreenShareEncoding": "voice-engine-v2:update-screen-share-encoding",
|
||||
"unpublishScreen": "voice-engine-v2:unpublish-screen",
|
||||
"publishScreenAudio": "voice-engine-v2:publish-screen-audio",
|
||||
"pushScreenAudioPcm": "voice-engine-v2:push-screen-audio-pcm",
|
||||
"pushScreenAudioFloat": "voice-engine-v2:push-screen-audio-float",
|
||||
"unpublishScreenAudio": "voice-engine-v2:unpublish-screen-audio",
|
||||
"setMicEnabled": "voice-engine-v2:set-mic-enabled",
|
||||
"setSpeakingDetection": "voice-engine-v2:set-speaking-detection",
|
||||
"listAudioInputDevices": "voice-engine-v2:list-audio-input-devices",
|
||||
"listAudioOutputDevices": "voice-engine-v2:list-audio-output-devices",
|
||||
"setAudioOutputDevice": "voice-engine-v2:set-audio-output-device",
|
||||
"setParticipantVolume": "voice-engine-v2:set-participant-volume",
|
||||
"setRemoteTrackSubscription": "voice-engine-v2:set-remote-track-subscription",
|
||||
"publishData": "voice-engine-v2:publish-data",
|
||||
"listCameraDevices": "voice-engine-v2:list-camera-devices",
|
||||
"publishCamera": "voice-engine-v2:publish-camera",
|
||||
"updateCameraCapture": "voice-engine-v2:update-camera-capture",
|
||||
"publishNativeCameraSink": "voice-engine-v2:publish-native-camera-sink",
|
||||
"publishProcessedCamera": "voice-engine-v2:publish-processed-camera",
|
||||
"pushProcessedCameraFrame": "voice-engine-v2:push-processed-camera-frame",
|
||||
"pushCameraBackgroundFrame": "voice-engine-v2:push-camera-background-frame",
|
||||
"clearCameraBackgroundFrame": "voice-engine-v2:clear-camera-background-frame",
|
||||
"publishDeviceScreenShare": "voice-engine-v2:publish-device-screen-share",
|
||||
"unpublishCamera": "voice-engine-v2:unpublish-camera",
|
||||
"isPublishingCamera": "voice-engine-v2:is-publishing-camera",
|
||||
"startCameraPreview": "voice-engine-v2:start-camera-preview",
|
||||
"stopCameraPreview": "voice-engine-v2:stop-camera-preview",
|
||||
"getConnectionStats": "voice-engine-v2:get-connection-stats",
|
||||
"getVoiceEngineReadiness": "voice-engine-v2:get-readiness",
|
||||
"getAudioDeviceModuleState": "voice-engine-v2:get-audio-device-module-state"
|
||||
},
|
||||
"eventChannels": {
|
||||
"event": "voice-engine-v2:event",
|
||||
"videoFrame": "voice-engine-v2:video-frame"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "camera_in_place_update",
|
||||
"events": [
|
||||
{
|
||||
"type": "connection.connectRequested",
|
||||
"options": {"url": "wss://voice.example.test", "token": "token-camera"}
|
||||
},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{
|
||||
"type": "camera.publishRequested",
|
||||
"options": {"deviceId": "camera-1", "width": 1280, "height": 720, "mirror": false}
|
||||
},
|
||||
{"type": "camera.publishSucceeded", "operationId": 2},
|
||||
{
|
||||
"type": "camera.updateEncodingRequested",
|
||||
"options": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"frameRate": 60,
|
||||
"mirror": true,
|
||||
"backgroundMode": "blur",
|
||||
"backgroundBlurStrength": 60
|
||||
}
|
||||
},
|
||||
{"type": "camera.updateEncodingSucceeded", "operationId": 3}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {"url": "wss://voice.example.test", "token": "token-camera"}
|
||||
},
|
||||
{
|
||||
"type": "camera.publish",
|
||||
"operationId": 2,
|
||||
"options": {"deviceId": "camera-1", "width": 1280, "height": 720, "mirror": false}
|
||||
},
|
||||
{
|
||||
"type": "camera.updateEncoding",
|
||||
"operationId": 3,
|
||||
"options": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"frameRate": 60,
|
||||
"mirror": true,
|
||||
"backgroundMode": "blur",
|
||||
"backgroundBlurStrength": 60
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 4,
|
||||
"cameraStatus": "published",
|
||||
"cameraDeviceId": "camera-1",
|
||||
"cameraWidth": 1920,
|
||||
"cameraFrameRate": 60,
|
||||
"cameraMirror": true,
|
||||
"cameraBackgroundMode": "blur",
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "capabilities_lifecycle",
|
||||
"events": [
|
||||
{
|
||||
"type": "capabilities.changed",
|
||||
"capabilities": {
|
||||
"connect": true,
|
||||
"microphone": true,
|
||||
"camera": true,
|
||||
"screen": true,
|
||||
"screenAudio": true,
|
||||
"outputDevice": true,
|
||||
"participantVolume": true,
|
||||
"remoteTrackSubscription": true,
|
||||
"dataChannel": true,
|
||||
"stats": true,
|
||||
"nativeVideoFrames": true,
|
||||
"hardwareEncoding": true,
|
||||
"zeroCopyScreenTransport": true,
|
||||
"nativeAudioTaps": true
|
||||
}
|
||||
},
|
||||
{"type": "capabilities.hardwareEncoderQueryRequested"},
|
||||
{
|
||||
"type": "capabilities.hardwareEncoderChanged",
|
||||
"operationId": 1,
|
||||
"capabilities": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "hevc"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": ["d3d11-texture"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectedCommands": [[], [{"type": "capabilities.queryHardwareEncoder", "operationId": 1}], []],
|
||||
"expected": {
|
||||
"nextOperationId": 2,
|
||||
"hardwareEncoderOperationId": null,
|
||||
"hardwareEncoderFailureCode": null,
|
||||
"hardwareEncoderBackend": "nvenc",
|
||||
"hasZeroCopyNativeInput": true,
|
||||
"hasNativeNvencH264": true,
|
||||
"hasNativeNvencH265": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"name": "codec_republish",
|
||||
"events": [
|
||||
{
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": "token-codec"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
{
|
||||
"type": "screen.publishRequested",
|
||||
"options": {
|
||||
"captureId": "capture-screen-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h264",
|
||||
"hardwareEncoding": true,
|
||||
"zeroCopyRequired": true,
|
||||
"maxFramerate": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.publishSucceeded",
|
||||
"operationId": 2
|
||||
},
|
||||
{
|
||||
"type": "screen.updateEncodingRequested",
|
||||
"options": {
|
||||
"captureId": "capture-screen-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h265",
|
||||
"hardwareEncoding": true,
|
||||
"zeroCopyRequired": true,
|
||||
"frameRate": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.publishSucceeded",
|
||||
"operationId": 3
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": "token-codec"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.publish",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"captureId": "capture-screen-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h264",
|
||||
"hardwareEncoding": true,
|
||||
"zeroCopyRequired": true,
|
||||
"maxFramerate": 60
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.publish",
|
||||
"operationId": 3,
|
||||
"options": {
|
||||
"captureId": "capture-screen-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h265",
|
||||
"hardwareEncoding": true,
|
||||
"zeroCopyRequired": true,
|
||||
"maxFramerate": 60
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 4,
|
||||
"screenStatus": "published",
|
||||
"screenCaptureId": "capture-screen-1",
|
||||
"screenCodec": "h265",
|
||||
"screenHardwareEncoding": true,
|
||||
"screenZeroCopyRequired": true,
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "audio input selection and hotplug republish microphone when connected",
|
||||
"events": [
|
||||
{"type": "connection.connectRequested", "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{"type": "microphone.publishRequested", "options": {"deviceId": "mic-a"}},
|
||||
{"type": "microphone.publishSucceeded", "operationId": 2},
|
||||
{"type": "devices.selectAudioInputRequested", "deviceId": "mic-b"},
|
||||
{"type": "command.succeeded", "operationId": 3, "commandType": "devices.selectAudioInput"},
|
||||
{"type": "microphone.publishSucceeded", "operationId": 4},
|
||||
{
|
||||
"type": "devices.changed",
|
||||
"operationId": null,
|
||||
"reason": "hotplug",
|
||||
"devices": {
|
||||
"audioInputs": [
|
||||
{"deviceId": "mic-b", "label": "Desk mic", "isDefault": false},
|
||||
{"deviceId": "mic-c", "label": "Headset mic", "isDefault": true}
|
||||
],
|
||||
"audioOutputs": [],
|
||||
"cameras": [],
|
||||
"selectedAudioInputId": "mic-c",
|
||||
"selectedAudioOutputId": null,
|
||||
"selectedCameraId": null
|
||||
}
|
||||
},
|
||||
{"type": "microphone.publishSucceeded", "operationId": 5}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{"type": "connection.connect", "operationId": 1, "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "microphone.publish", "operationId": 2, "options": {"deviceId": "mic-a"}},
|
||||
{"type": "devices.selectAudioInput", "operationId": 3, "deviceId": "mic-b"},
|
||||
{"type": "microphone.publish", "operationId": 4, "options": {"deviceId": "mic-b"}},
|
||||
{"type": "microphone.publish", "operationId": 5, "options": {"deviceId": "mic-c"}}
|
||||
],
|
||||
"checkpoints": [
|
||||
{
|
||||
"afterEvent": 5,
|
||||
"microphoneStatus": "publishing",
|
||||
"desiredDeviceId": "mic-b",
|
||||
"selectedAudioInputId": "mic-b"
|
||||
},
|
||||
{
|
||||
"afterEvent": 8,
|
||||
"microphoneStatus": "publishing",
|
||||
"desiredDeviceId": "mic-c",
|
||||
"selectedAudioInputId": "mic-c"
|
||||
}
|
||||
],
|
||||
"expectedSnapshot": {
|
||||
"nextOperationId": 6,
|
||||
"connectionStatus": "connected",
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": true,
|
||||
"localSpeakingOverride": null,
|
||||
"publishedDeviceId": "mic-c",
|
||||
"desiredDeviceId": "mic-c",
|
||||
"selectedAudioInputId": "mic-c",
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"name": "device_inventory",
|
||||
"events": [
|
||||
{"type": "devices.enumerateRequested"},
|
||||
{
|
||||
"type": "devices.changed",
|
||||
"operationId": 1,
|
||||
"reason": "initial",
|
||||
"devices": {
|
||||
"audioInputs": [
|
||||
{"deviceId": "mic-1", "label": "Built-in Microphone", "isDefault": true, "role": "default"},
|
||||
{
|
||||
"deviceId": "mic-2",
|
||||
"label": "USB Microphone",
|
||||
"isDefault": false,
|
||||
"role": "communications",
|
||||
"endpointLabel": "USB Audio",
|
||||
"isDefaultRoute": true
|
||||
}
|
||||
],
|
||||
"audioOutputs": [{"deviceId": "speaker-1", "label": "Built-in Speakers", "isDefault": true, "role": "default"}],
|
||||
"cameras": [{"deviceId": "camera-1", "label": "FaceTime Camera", "description": "Integrated camera"}],
|
||||
"selectedAudioInputId": "mic-1",
|
||||
"selectedAudioOutputId": "speaker-1",
|
||||
"selectedCameraId": "camera-1"
|
||||
}
|
||||
},
|
||||
{"type": "devices.selectAudioInputRequested", "deviceId": "mic-2"},
|
||||
{"type": "command.succeeded", "operationId": 2, "commandType": "devices.selectAudioInput"},
|
||||
{
|
||||
"type": "devices.changed",
|
||||
"operationId": null,
|
||||
"reason": "hotplug",
|
||||
"devices": {
|
||||
"audioInputs": [
|
||||
{
|
||||
"deviceId": "mic-2",
|
||||
"label": "USB Microphone",
|
||||
"isDefault": true,
|
||||
"role": "communications",
|
||||
"endpointLabel": "USB Audio",
|
||||
"isDefaultRoute": true
|
||||
}
|
||||
],
|
||||
"audioOutputs": [
|
||||
{"deviceId": "speaker-1", "label": "Built-in Speakers", "isDefault": true, "role": "default"},
|
||||
{"deviceId": "headset-1", "label": "USB Headset", "isDefault": false, "role": "endpoint"}
|
||||
],
|
||||
"cameras": [
|
||||
{"deviceId": "camera-1", "label": "FaceTime Camera", "description": "Integrated camera"},
|
||||
{"deviceId": "camera-2", "label": "Capture Card", "description": "USB capture"}
|
||||
],
|
||||
"selectedAudioInputId": "mic-2",
|
||||
"selectedAudioOutputId": "speaker-1",
|
||||
"selectedCameraId": "camera-1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
[{"type": "devices.enumerate", "operationId": 1}],
|
||||
[],
|
||||
[{"type": "devices.selectAudioInput", "operationId": 2, "deviceId": "mic-2"}],
|
||||
[],
|
||||
[]
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"deviceOperationId": null,
|
||||
"failureCode": null,
|
||||
"selectedAudioInputId": "mic-2",
|
||||
"selectedAudioInputLabel": "USB Microphone",
|
||||
"selectedAudioInputRole": "communications",
|
||||
"audioOutputCount": 2,
|
||||
"cameraCount": 2,
|
||||
"operationStatuses": {"1": "succeeded", "2": "succeeded"}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "diagnostics_lifecycle",
|
||||
"events": [
|
||||
{
|
||||
"type": "diagnostics.logRequested",
|
||||
"entry": {
|
||||
"id": "diag-1",
|
||||
"atMs": 1000,
|
||||
"level": "info",
|
||||
"code": "voice.session.started",
|
||||
"message": "Voice session started"
|
||||
}
|
||||
},
|
||||
{"type": "command.succeeded", "operationId": 1, "commandType": "diagnostics.log"},
|
||||
{
|
||||
"type": "diagnostics.logged",
|
||||
"operationId": null,
|
||||
"entry": {
|
||||
"id": "diag-2",
|
||||
"atMs": 1010,
|
||||
"level": "warn",
|
||||
"code": "voice.stats.delayed",
|
||||
"message": "Stats collection was delayed",
|
||||
"detail": {"delayMs": 250}
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
[
|
||||
{
|
||||
"type": "diagnostics.log",
|
||||
"operationId": 1,
|
||||
"entry": {
|
||||
"id": "diag-1",
|
||||
"atMs": 1000,
|
||||
"level": "info",
|
||||
"code": "voice.session.started",
|
||||
"message": "Voice session started"
|
||||
}
|
||||
}
|
||||
],
|
||||
[],
|
||||
[]
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 2,
|
||||
"entryIds": ["diag-1", "diag-2"],
|
||||
"lastCode": "voice.stats.delayed",
|
||||
"operationStatuses": {"1": "succeeded"}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "e2ee_lifecycle",
|
||||
"events": [
|
||||
{"type": "e2ee.setEnabledRequested", "enabled": true, "keyId": "key-a"},
|
||||
{"type": "e2ee.setEnabledRequested", "enabled": false},
|
||||
{"type": "e2ee.enabled", "operationId": 1, "keyId": "key-a"},
|
||||
{"type": "e2ee.disabled", "operationId": 2},
|
||||
{"type": "e2ee.enabled", "operationId": null, "keyId": "key-b"},
|
||||
{
|
||||
"type": "e2ee.failed",
|
||||
"operationId": null,
|
||||
"error": {
|
||||
"code": "implementationError",
|
||||
"message": "Remote participant key material could not be applied",
|
||||
"capability": "e2ee"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
[{"type": "e2ee.setEnabled", "operationId": 1, "enabled": true, "keyId": "key-a"}],
|
||||
[{"type": "e2ee.setEnabled", "operationId": 2, "enabled": false}],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[]
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"status": "failed",
|
||||
"keyId": "key-b",
|
||||
"operationId": null,
|
||||
"failureCode": "implementationError"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"name": "gateway_connection",
|
||||
"description": "Join writes gateway voice state, observes gateway state, then connects the media session.",
|
||||
"steps": [
|
||||
{
|
||||
"name": "request gateway join",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateWriteRequested",
|
||||
"options": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-1",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "gateway.voiceState.write",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-1",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gateway join write succeeds",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateWriteSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "gateway voice state arrives",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateUpdated",
|
||||
"voiceState": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-1",
|
||||
"userId": "user-1",
|
||||
"sessionId": "session-1",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false,
|
||||
"selfVideo": false,
|
||||
"selfStream": false,
|
||||
"suppress": false,
|
||||
"requestToSpeakTimestamp": null
|
||||
}
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "request media connection",
|
||||
"event": {
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice-one.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"url": "wss://voice-one.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "media connection succeeds",
|
||||
"event": {
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 2
|
||||
},
|
||||
"commands": []
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"connectionStatus": "connected",
|
||||
"activeUrl": "wss://voice-one.example.test",
|
||||
"desiredUrl": "wss://voice-one.example.test",
|
||||
"gatewayChannelId": "channel-1",
|
||||
"lifecycleTearingDown": false,
|
||||
"operationStatuses": {
|
||||
"1": "succeeded",
|
||||
"2": "succeeded"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"name": "inbound video frame stats projection",
|
||||
"events": [
|
||||
{
|
||||
"type": "inboundVideo.trackSubscribed",
|
||||
"track": {
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "inboundVideo.frameReceived",
|
||||
"frame": {
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"width": 640,
|
||||
"height": 360,
|
||||
"timestampUs": 1000,
|
||||
"byteLength": 345600
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "inboundVideo.frameStats",
|
||||
"stats": {
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"frameCount": 31,
|
||||
"lastFrameTimestampUs": 1033000,
|
||||
"lastFrameByteLength": 1382400
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "inboundVideo.frameStats",
|
||||
"stats": {
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"frameCount": 61,
|
||||
"lastFrameTimestampUs": 2033000,
|
||||
"lastFrameByteLength": 1382400
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "inboundVideo.frameStats",
|
||||
"stats": {
|
||||
"participantSid": "PA_bob",
|
||||
"trackSid": "TR_unknown",
|
||||
"width": 320,
|
||||
"height": 180,
|
||||
"frameCount": 5,
|
||||
"lastFrameTimestampUs": 3000000,
|
||||
"lastFrameByteLength": 86400
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"inboundVideoTracks": [
|
||||
{
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screen",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"frameCount": 61,
|
||||
"lastFrameTimestampUs": 2033000,
|
||||
"lastFrameByteLength": 1382400
|
||||
}
|
||||
],
|
||||
"droppedFrameCount": 1,
|
||||
"commands": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"name": "inbound native video frame projection",
|
||||
"events": [
|
||||
{
|
||||
"type": "inboundVideo.trackSubscribed",
|
||||
"track": {
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "inboundVideo.frameReceived",
|
||||
"frame": {
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"width": 640,
|
||||
"height": 360,
|
||||
"timestampUs": 1000,
|
||||
"byteLength": 345600
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "inboundVideo.frameReceived",
|
||||
"frame": {
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"timestampUs": 2000,
|
||||
"byteLength": 1382400
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "inboundVideo.frameReceived",
|
||||
"frame": {
|
||||
"participantSid": "PA_alice",
|
||||
"trackSid": "TR_unknown",
|
||||
"width": 320,
|
||||
"height": 180,
|
||||
"timestampUs": 3000,
|
||||
"byteLength": 86400
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"inboundVideoTracks": [
|
||||
{
|
||||
"participantSid": "PA_alice",
|
||||
"participantIdentity": "alice",
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screen",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"frameCount": 2,
|
||||
"lastFrameTimestampUs": 2000,
|
||||
"lastFrameByteLength": 1382400
|
||||
}
|
||||
],
|
||||
"droppedFrameCount": 1,
|
||||
"commands": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"name": "local media mute unmute deafen undeafen and microphone publish lifecycle",
|
||||
"events": [
|
||||
{"type": "connection.connectRequested", "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{"type": "microphone.publishRequested", "options": {"deviceId": "mic-a"}},
|
||||
{"type": "microphone.publishSucceeded", "operationId": 2},
|
||||
{"type": "connection.reconnectRequested"},
|
||||
{"type": "connection.disconnectSucceeded", "operationId": 3},
|
||||
{"type": "connection.connectSucceeded", "operationId": 4},
|
||||
{"type": "microphone.publishSucceeded", "operationId": 5},
|
||||
{"type": "localAudio.muteRequested", "muted": true},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 6},
|
||||
{"type": "localAudio.muteRequested", "muted": false},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 7},
|
||||
{"type": "localAudio.deafenRequested", "deafened": true},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 8},
|
||||
{"type": "localAudio.deafenRequested", "deafened": false},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 9},
|
||||
{"type": "microphone.unpublishRequested"},
|
||||
{"type": "microphone.unpublishSucceeded", "operationId": 10}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{"type": "connection.connect", "operationId": 1, "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "microphone.publish", "operationId": 2, "options": {"deviceId": "mic-a"}},
|
||||
{"type": "connection.disconnect", "operationId": 3, "reason": "network"},
|
||||
{"type": "connection.connect", "operationId": 4, "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "microphone.publish", "operationId": 5, "options": {"deviceId": "mic-a"}},
|
||||
{"type": "microphone.setEnabled", "operationId": 6, "enabled": false},
|
||||
{"type": "microphone.setEnabled", "operationId": 7, "enabled": true},
|
||||
{"type": "microphone.setEnabled", "operationId": 8, "enabled": false},
|
||||
{"type": "microphone.setEnabled", "operationId": 9, "enabled": true},
|
||||
{"type": "microphone.unpublish", "operationId": 10}
|
||||
],
|
||||
"checkpoints": [
|
||||
{
|
||||
"afterEvent": 5,
|
||||
"connectionStatus": "reconnecting",
|
||||
"microphoneStatus": "idle",
|
||||
"desiredDeviceId": "mic-a",
|
||||
"publishedDeviceId": null
|
||||
},
|
||||
{
|
||||
"afterEvent": 9,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": false,
|
||||
"localSpeakingOverride": false,
|
||||
"locallyMuted": true,
|
||||
"locallyDeafened": false
|
||||
},
|
||||
{
|
||||
"afterEvent": 13,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": false,
|
||||
"localSpeakingOverride": false,
|
||||
"locallyMuted": true,
|
||||
"locallyDeafened": true,
|
||||
"shouldUnmuteOnUndeafen": true
|
||||
},
|
||||
{
|
||||
"afterEvent": 15,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": true,
|
||||
"localSpeakingOverride": null,
|
||||
"locallyMuted": false,
|
||||
"locallyDeafened": false
|
||||
}
|
||||
],
|
||||
"expectedSnapshot": {
|
||||
"nextOperationId": 11,
|
||||
"connectionStatus": "connected",
|
||||
"microphoneStatus": "idle",
|
||||
"microphoneEnabled": true,
|
||||
"localSpeakingOverride": false,
|
||||
"locallyMuted": false,
|
||||
"locallyDeafened": false,
|
||||
"mutedByPermission": false,
|
||||
"publishedDeviceId": null,
|
||||
"desiredDeviceId": null,
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "microphone device failure mutes locally then device hotswap and unmute recover",
|
||||
"events": [
|
||||
{"type": "connection.connectRequested", "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{"type": "microphone.publishRequested", "options": {"deviceId": "mic-a"}},
|
||||
{
|
||||
"type": "microphone.publishFailed",
|
||||
"operationId": 2,
|
||||
"error": {"code": "deviceUnavailable", "message": "device unavailable", "capability": "microphoneCapture"}
|
||||
},
|
||||
{"type": "devices.selectAudioInputRequested", "deviceId": "mic-b"},
|
||||
{"type": "command.succeeded", "operationId": 3, "commandType": "devices.selectAudioInput"},
|
||||
{"type": "microphone.publishSucceeded", "operationId": 4},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 5},
|
||||
{"type": "localAudio.muteRequested", "muted": false},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 6}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{"type": "connection.connect", "operationId": 1, "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "microphone.publish", "operationId": 2, "options": {"deviceId": "mic-a"}},
|
||||
{"type": "devices.selectAudioInput", "operationId": 3, "deviceId": "mic-b"},
|
||||
{"type": "microphone.publish", "operationId": 4, "options": {"deviceId": "mic-b"}},
|
||||
{"type": "microphone.setEnabled", "operationId": 5, "enabled": false},
|
||||
{"type": "microphone.setEnabled", "operationId": 6, "enabled": true}
|
||||
],
|
||||
"checkpoints": [
|
||||
{
|
||||
"afterEvent": 4,
|
||||
"microphoneStatus": "failed",
|
||||
"microphoneEnabled": false,
|
||||
"locallyMuted": true,
|
||||
"preferredLocallyMuted": true,
|
||||
"lastFailureCode": "deviceUnavailable"
|
||||
},
|
||||
{
|
||||
"afterEvent": 7,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": false,
|
||||
"localSpeakingOverride": false,
|
||||
"publishedDeviceId": "mic-b",
|
||||
"desiredDeviceId": "mic-b"
|
||||
}
|
||||
],
|
||||
"expectedSnapshot": {
|
||||
"nextOperationId": 7,
|
||||
"connectionStatus": "connected",
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": true,
|
||||
"localSpeakingOverride": null,
|
||||
"locallyMuted": false,
|
||||
"preferredLocallyMuted": false,
|
||||
"publishedDeviceId": "mic-b",
|
||||
"desiredDeviceId": "mic-b",
|
||||
"selectedAudioInputId": "mic-b",
|
||||
"lastFailureCode": "deviceUnavailable"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "native_frame_sink",
|
||||
"events": [
|
||||
{
|
||||
"type": "nativeFrameSink.attachRequested",
|
||||
"options": {
|
||||
"sinkId": "sink-screen-1",
|
||||
"captureId": "capture-native-1",
|
||||
"trackSid": "TR_screen_1",
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "nativeFrameSink.detachRequested",
|
||||
"sinkId": "sink-screen-1"
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{
|
||||
"type": "nativeFrameSink.attach",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"sinkId": "sink-screen-1",
|
||||
"captureId": "capture-native-1",
|
||||
"trackSid": "TR_screen_1",
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "nativeFrameSink.detach",
|
||||
"operationId": 2,
|
||||
"sinkId": "sink-screen-1"
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"nativeFrameSinkCount": 0,
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
{
|
||||
"name": "native_zero_copy_screen",
|
||||
"events": [
|
||||
{
|
||||
"type": "nativeCapture.startRequested",
|
||||
"options": {
|
||||
"captureId": "capture-native-1",
|
||||
"source": {
|
||||
"id": "display-1",
|
||||
"kind": "screen",
|
||||
"title": "Display 1",
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"displayId": "display-1"
|
||||
},
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"frameRate": 60,
|
||||
"includeCursor": true,
|
||||
"includeAudio": false,
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "nativeCapture.started",
|
||||
"operationId": 1,
|
||||
"captureId": "capture-native-1"
|
||||
},
|
||||
{
|
||||
"type": "nativeCapture.updateRequested",
|
||||
"options": {
|
||||
"captureId": "capture-native-1",
|
||||
"source": {
|
||||
"id": "display-1",
|
||||
"kind": "screen",
|
||||
"title": "Display 1",
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"displayId": "display-1"
|
||||
},
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"frameRate": 30,
|
||||
"includeCursor": false,
|
||||
"includeAudio": false,
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "nativeCapture.started",
|
||||
"operationId": 2,
|
||||
"captureId": "capture-native-1"
|
||||
},
|
||||
{
|
||||
"type": "nativeCapture.stopRequested",
|
||||
"captureId": "capture-native-1"
|
||||
},
|
||||
{
|
||||
"type": "nativeCapture.stopped",
|
||||
"operationId": 3,
|
||||
"captureId": "capture-native-1"
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{
|
||||
"type": "nativeCapture.start",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"captureId": "capture-native-1",
|
||||
"source": {
|
||||
"id": "display-1",
|
||||
"kind": "screen",
|
||||
"title": "Display 1",
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"displayId": "display-1"
|
||||
},
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"frameRate": 60,
|
||||
"includeCursor": true,
|
||||
"includeAudio": false,
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "nativeCapture.update",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"captureId": "capture-native-1",
|
||||
"source": {
|
||||
"id": "display-1",
|
||||
"kind": "screen",
|
||||
"title": "Display 1",
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"displayId": "display-1"
|
||||
},
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"frameRate": 30,
|
||||
"includeCursor": false,
|
||||
"includeAudio": false,
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "nativeCapture.stop",
|
||||
"operationId": 3,
|
||||
"captureId": "capture-native-1"
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 4,
|
||||
"nativeCaptureCount": 0,
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "participants and tracks projection",
|
||||
"events": [
|
||||
{
|
||||
"type": "room.participantJoined",
|
||||
"participant": {"sid": "PA_alice", "identity": "alice", "name": "Alice"}
|
||||
},
|
||||
{
|
||||
"type": "room.trackPublished",
|
||||
"track": {
|
||||
"participantIdentity": "alice",
|
||||
"participantSid": "PA_alice",
|
||||
"trackSid": "TR_camera",
|
||||
"trackName": "camera",
|
||||
"kind": "video",
|
||||
"source": "camera",
|
||||
"muted": false
|
||||
}
|
||||
},
|
||||
{"type": "room.trackMuted", "trackSid": "TR_camera"},
|
||||
{
|
||||
"type": "room.trackPublished",
|
||||
"track": {
|
||||
"participantIdentity": "alice",
|
||||
"participantSid": "PA_alice",
|
||||
"trackSid": "TR_mic",
|
||||
"trackName": "microphone",
|
||||
"kind": "audio",
|
||||
"source": "microphone",
|
||||
"muted": false
|
||||
}
|
||||
},
|
||||
{"type": "room.trackUnpublished", "trackSid": "TR_mic"},
|
||||
{
|
||||
"type": "room.participantJoined",
|
||||
"participant": {"sid": "PA_bob", "identity": "bob", "name": "Bob"}
|
||||
},
|
||||
{"type": "room.participantLeft", "participantIdentity": "alice", "participantSid": "PA_alice"}
|
||||
],
|
||||
"expected": {
|
||||
"participants": [{"sid": "PA_bob", "identity": "bob", "name": "Bob"}],
|
||||
"tracks": [],
|
||||
"inboundVideoTracks": [],
|
||||
"commands": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "microphone permission denial mutes and grant restores requested unmute",
|
||||
"events": [
|
||||
{"type": "connection.connectRequested", "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{"type": "microphone.publishRequested", "options": {"deviceId": "mic-a"}},
|
||||
{"type": "microphone.publishSucceeded", "operationId": 2},
|
||||
{
|
||||
"type": "permissions.result",
|
||||
"operationId": null,
|
||||
"result": {"name": "microphone", "status": "denied", "canPrompt": false}
|
||||
},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 3},
|
||||
{"type": "localAudio.muteRequested", "muted": false},
|
||||
{
|
||||
"type": "permissions.result",
|
||||
"operationId": null,
|
||||
"result": {"name": "microphone", "status": "granted", "canPrompt": false}
|
||||
},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 4}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{"type": "connection.connect", "operationId": 1, "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "microphone.publish", "operationId": 2, "options": {"deviceId": "mic-a"}},
|
||||
{"type": "microphone.setEnabled", "operationId": 3, "enabled": false},
|
||||
{"type": "microphone.setEnabled", "operationId": 4, "enabled": true}
|
||||
],
|
||||
"checkpoints": [
|
||||
{
|
||||
"afterEvent": 5,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": false,
|
||||
"localSpeakingOverride": false,
|
||||
"locallyMuted": true,
|
||||
"mutedByPermission": true,
|
||||
"permissionStatus": "denied"
|
||||
},
|
||||
{
|
||||
"afterEvent": 7,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": false,
|
||||
"locallyMuted": true,
|
||||
"preferredLocallyMuted": false,
|
||||
"mutedByPermission": true
|
||||
}
|
||||
],
|
||||
"expectedSnapshot": {
|
||||
"nextOperationId": 5,
|
||||
"connectionStatus": "connected",
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": true,
|
||||
"localSpeakingOverride": null,
|
||||
"locallyMuted": false,
|
||||
"preferredLocallyMuted": false,
|
||||
"mutedByPermission": false,
|
||||
"permissionStatus": "granted",
|
||||
"publishedDeviceId": "mic-a",
|
||||
"desiredDeviceId": "mic-a",
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "push to talk and push to mute gate microphone enabled state",
|
||||
"events": [
|
||||
{"type": "connection.connectRequested", "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{"type": "microphone.publishRequested", "options": {"deviceId": "mic-a"}},
|
||||
{"type": "microphone.publishSucceeded", "operationId": 2},
|
||||
{"type": "audioControls.changed", "controls": {"mode": "pushToTalk", "pushToTalkActive": false}},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 3},
|
||||
{"type": "audioControls.changed", "controls": {"pushToTalkActive": true}},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 4},
|
||||
{
|
||||
"type": "audioControls.changed",
|
||||
"controls": {"mode": "pushToMute", "pushToTalkActive": false, "pushToMuteActive": true}
|
||||
},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 5},
|
||||
{"type": "audioControls.changed", "controls": {"pushToMuteActive": false}},
|
||||
{"type": "microphone.setEnabledSucceeded", "operationId": 6}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{"type": "connection.connect", "operationId": 1, "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "microphone.publish", "operationId": 2, "options": {"deviceId": "mic-a"}},
|
||||
{"type": "microphone.setEnabled", "operationId": 3, "enabled": false},
|
||||
{"type": "microphone.setEnabled", "operationId": 4, "enabled": true},
|
||||
{"type": "microphone.setEnabled", "operationId": 5, "enabled": false},
|
||||
{"type": "microphone.setEnabled", "operationId": 6, "enabled": true}
|
||||
],
|
||||
"checkpoints": [
|
||||
{
|
||||
"afterEvent": 5,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": false,
|
||||
"localSpeakingOverride": false,
|
||||
"audioMode": "pushToTalk"
|
||||
},
|
||||
{
|
||||
"afterEvent": 7,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": true,
|
||||
"localSpeakingOverride": true,
|
||||
"audioMode": "pushToTalk"
|
||||
},
|
||||
{
|
||||
"afterEvent": 9,
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": false,
|
||||
"localSpeakingOverride": false,
|
||||
"audioMode": "pushToMute"
|
||||
}
|
||||
],
|
||||
"expectedSnapshot": {
|
||||
"nextOperationId": 7,
|
||||
"connectionStatus": "connected",
|
||||
"microphoneStatus": "published",
|
||||
"microphoneEnabled": true,
|
||||
"localSpeakingOverride": null,
|
||||
"audioMode": "pushToMute",
|
||||
"publishedDeviceId": "mic-a",
|
||||
"desiredDeviceId": "mic-a",
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"name": "reconnect_channel_move",
|
||||
"description": "A channel move writes the new gateway voice state, disconnects the old media session, then reconnects to the new room.",
|
||||
"steps": [
|
||||
{
|
||||
"name": "connect first room",
|
||||
"event": {
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice-one.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"url": "wss://voice-one.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "first room connected",
|
||||
"event": {
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "old gateway channel observed",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateUpdated",
|
||||
"voiceState": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-1",
|
||||
"userId": "user-1",
|
||||
"sessionId": "session-1",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false,
|
||||
"selfVideo": false,
|
||||
"selfStream": false,
|
||||
"suppress": false,
|
||||
"requestToSpeakTimestamp": null
|
||||
}
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "write moved gateway channel",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateWriteRequested",
|
||||
"options": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-2",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "gateway.voiceState.write",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-2",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "moved gateway write succeeds",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateWriteSucceeded",
|
||||
"operationId": 2
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "new gateway channel observed",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateUpdated",
|
||||
"voiceState": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-2",
|
||||
"userId": "user-1",
|
||||
"sessionId": "session-2",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false,
|
||||
"selfVideo": false,
|
||||
"selfStream": false,
|
||||
"suppress": false,
|
||||
"requestToSpeakTimestamp": null
|
||||
}
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "request second media connection",
|
||||
"event": {
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice-two.example.test",
|
||||
"token": "token-2"
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "connection.disconnect",
|
||||
"operationId": 3,
|
||||
"reason": "replaced"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "old media connection disconnects",
|
||||
"event": {
|
||||
"type": "connection.disconnectSucceeded",
|
||||
"operationId": 3
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 4,
|
||||
"options": {
|
||||
"url": "wss://voice-two.example.test",
|
||||
"token": "token-2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "second media connection succeeds",
|
||||
"event": {
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 4
|
||||
},
|
||||
"commands": []
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 5,
|
||||
"connectionStatus": "connected",
|
||||
"activeUrl": "wss://voice-two.example.test",
|
||||
"desiredUrl": "wss://voice-two.example.test",
|
||||
"gatewayChannelId": "channel-2",
|
||||
"lifecycleTearingDown": false,
|
||||
"operationStatuses": {
|
||||
"1": "succeeded",
|
||||
"2": "succeeded",
|
||||
"3": "succeeded",
|
||||
"4": "succeeded"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "resume_preserves_media",
|
||||
"steps": [
|
||||
{
|
||||
"name": "external establishment",
|
||||
"event": {"type": "connection.externallyEstablished", "options": {"url": "wss://voice.fixture", "token": ""}},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "camera publish requested",
|
||||
"event": {"type": "camera.publishRequested", "options": {"deviceId": "camera-1"}},
|
||||
"commands": [{"type": "camera.publish", "operationId": 1, "options": {"deviceId": "camera-1"}}]
|
||||
},
|
||||
{
|
||||
"name": "camera publish succeeded",
|
||||
"event": {"type": "camera.publishSucceeded", "operationId": 1},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "resume re-establishes the same endpoint without replaying media",
|
||||
"event": {"type": "connection.externallyEstablished", "options": {"url": "wss://voice.fixture", "token": ""}},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "camera unpublish after resume plans a real command",
|
||||
"event": {"type": "camera.unpublishRequested"},
|
||||
"commands": [{"type": "camera.unpublish", "operationId": 2}]
|
||||
},
|
||||
{
|
||||
"name": "camera unpublish succeeded",
|
||||
"event": {"type": "camera.unpublishSucceeded", "operationId": 2},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "true remote disconnect resets the session",
|
||||
"event": {"type": "connection.remoteDisconnected", "reason": "network"},
|
||||
"commands": []
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"connectionStatus": "idle",
|
||||
"activeUrl": null,
|
||||
"desiredUrl": null,
|
||||
"gatewayChannelId": null,
|
||||
"lifecycleTearingDown": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "screen_audio_inclusion_toggle",
|
||||
"events": [
|
||||
{
|
||||
"type": "connection.connectRequested",
|
||||
"options": {"url": "wss://voice.example.test", "token": "token-screen-audio"}
|
||||
},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{
|
||||
"type": "screen.publishRequested",
|
||||
"options": {"captureId": "capture-1", "width": 1920, "height": 1080, "codec": "h264", "maxFramerate": 30}
|
||||
},
|
||||
{"type": "screen.publishSucceeded", "operationId": 2},
|
||||
{"type": "screenAudio.publishRequested", "options": {"sampleRate": 48000, "numChannels": 2}},
|
||||
{"type": "screenAudio.publishSucceeded", "operationId": 3},
|
||||
{
|
||||
"type": "screen.updateEncodingRequested",
|
||||
"options": {"captureId": "capture-1", "width": 1920, "height": 1080, "frameRate": 60}
|
||||
},
|
||||
{"type": "screen.updateEncodingSucceeded", "operationId": 4},
|
||||
{"type": "screenAudio.unpublishRequested"},
|
||||
{"type": "screenAudio.unpublishSucceeded", "operationId": 5},
|
||||
{"type": "screenAudio.publishRequested", "options": {"sampleRate": 48000, "numChannels": 2}},
|
||||
{"type": "screenAudio.publishSucceeded", "operationId": 6}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {"url": "wss://voice.example.test", "token": "token-screen-audio"}
|
||||
},
|
||||
{
|
||||
"type": "screen.publish",
|
||||
"operationId": 2,
|
||||
"options": {"captureId": "capture-1", "width": 1920, "height": 1080, "codec": "h264", "maxFramerate": 30}
|
||||
},
|
||||
{"type": "screenAudio.publish", "operationId": 3, "options": {"sampleRate": 48000, "numChannels": 2}},
|
||||
{
|
||||
"type": "screen.updateEncoding",
|
||||
"operationId": 4,
|
||||
"options": {"captureId": "capture-1", "width": 1920, "height": 1080, "frameRate": 60}
|
||||
},
|
||||
{"type": "screenAudio.unpublish", "operationId": 5},
|
||||
{"type": "screenAudio.publish", "operationId": 6, "options": {"sampleRate": 48000, "numChannels": 2}}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 7,
|
||||
"screenStatus": "published",
|
||||
"screenCaptureId": "capture-1",
|
||||
"screenAudioStatus": "published",
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "screen_audio_routing",
|
||||
"events": [
|
||||
{
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": "token-audio"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
{
|
||||
"type": "screenAudio.publishRequested",
|
||||
"options": {
|
||||
"sampleRate": 48000,
|
||||
"numChannels": 2,
|
||||
"route": "native",
|
||||
"captureId": "capture-screen-1",
|
||||
"tapId": "tap-screen-1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screenAudio.publishSucceeded",
|
||||
"operationId": 2
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": "token-audio"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screenAudio.publish",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"sampleRate": 48000,
|
||||
"numChannels": 2,
|
||||
"route": "native",
|
||||
"captureId": "capture-screen-1",
|
||||
"tapId": "tap-screen-1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"screenAudioStatus": "published",
|
||||
"screenAudioRoute": "native",
|
||||
"screenAudioTapId": "tap-screen-1",
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"name": "screen_share_start_update_stop",
|
||||
"events": [
|
||||
{
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": "token-screen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
{
|
||||
"type": "screen.publishRequested",
|
||||
"options": {
|
||||
"captureId": "capture-screen-1",
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"codec": "h264",
|
||||
"maxFramerate": 60,
|
||||
"maxBitrateBps": 8000000
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.publishSucceeded",
|
||||
"operationId": 2
|
||||
},
|
||||
{
|
||||
"type": "screen.updateEncodingRequested",
|
||||
"options": {
|
||||
"captureId": "capture-screen-1",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"frameRate": 30,
|
||||
"maxBitrateBps": 3000000
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.updateEncodingSucceeded",
|
||||
"operationId": 3
|
||||
},
|
||||
{
|
||||
"type": "screen.unpublishRequested"
|
||||
},
|
||||
{
|
||||
"type": "screen.unpublishSucceeded",
|
||||
"operationId": 4
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": "token-screen"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.publish",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"captureId": "capture-screen-1",
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"codec": "h264",
|
||||
"maxFramerate": 60,
|
||||
"maxBitrateBps": 8000000
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.updateEncoding",
|
||||
"operationId": 3,
|
||||
"options": {
|
||||
"captureId": "capture-screen-1",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"frameRate": 30,
|
||||
"maxBitrateBps": 3000000
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "screen.unpublish",
|
||||
"operationId": 4
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 5,
|
||||
"screenStatus": "idle",
|
||||
"screenCaptureId": null,
|
||||
"lastFailureCode": null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"name": "stale_connection",
|
||||
"description": "A stale connect completion is rejected after a newer connect operation supersedes it.",
|
||||
"steps": [
|
||||
{
|
||||
"name": "request first connection",
|
||||
"event": {
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice-one.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"url": "wss://voice-one.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "request replacement connection",
|
||||
"event": {
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice-two.example.test",
|
||||
"token": "token-2"
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"url": "wss://voice-two.example.test",
|
||||
"token": "token-2"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stale first completion arrives",
|
||||
"event": {
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "runtime rejects stale first completion",
|
||||
"event": {
|
||||
"type": "command.staleCompletionRejected",
|
||||
"operationId": 1,
|
||||
"commandType": "connection.connect",
|
||||
"resourceKey": "connection"
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "replacement completion succeeds",
|
||||
"event": {
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 2
|
||||
},
|
||||
"commands": []
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"connectionStatus": "connected",
|
||||
"activeUrl": "wss://voice-two.example.test",
|
||||
"desiredUrl": "wss://voice-two.example.test",
|
||||
"gatewayChannelId": null,
|
||||
"lifecycleTearingDown": false,
|
||||
"operationStatuses": {
|
||||
"1": "stale",
|
||||
"2": "succeeded"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"name": "stats_lifecycle",
|
||||
"events": [
|
||||
{
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{"type": "stats.collectRequested"},
|
||||
{
|
||||
"type": "stats.collected",
|
||||
"operationId": 2,
|
||||
"stats": {
|
||||
"rttMs": 24,
|
||||
"outbound": [
|
||||
{
|
||||
"trackSid": "mic-track",
|
||||
"source": "microphone",
|
||||
"kind": "audio",
|
||||
"bitrateKbps": 42,
|
||||
"packetsLost": 1,
|
||||
"packetsSent": 100
|
||||
},
|
||||
{
|
||||
"trackSid": "screen-track",
|
||||
"source": "screenshare",
|
||||
"kind": "video",
|
||||
"codec": "video/H265",
|
||||
"bitrateKbps": 3500,
|
||||
"packetsLost": 0,
|
||||
"effectiveFps": 58.5,
|
||||
"configuredFps": 60,
|
||||
"targetFps": 60,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"zeroCopy": true
|
||||
}
|
||||
],
|
||||
"inbound": [
|
||||
{
|
||||
"participantIdentity": "remote-user",
|
||||
"participantSid": "participant-1",
|
||||
"trackSid": "remote-audio",
|
||||
"kind": "audio",
|
||||
"bitrateKbps": 36,
|
||||
"packetsLost": 3,
|
||||
"packetsReceived": 97,
|
||||
"jitterMs": 7
|
||||
}
|
||||
],
|
||||
"droppedNativeVideoFrames": 2,
|
||||
"droppedVideoFrameCallbacks": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectedCommands": [
|
||||
[
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {"url": "wss://voice.example.test", "token": "token-1"}
|
||||
}
|
||||
],
|
||||
[],
|
||||
[{"type": "stats.collect", "operationId": 2}],
|
||||
[]
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"statsOperationId": null,
|
||||
"statsFailureCode": null,
|
||||
"summary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 42,
|
||||
"audioRecvBitrateKbps": 36,
|
||||
"videoSendBitrateKbps": 3500,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 3,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 7,
|
||||
"rttMs": 24
|
||||
},
|
||||
"localAudio": {"trackIdentifier": "mic-track"},
|
||||
"localScreenShare": {
|
||||
"trackIdentifier": "screen-track",
|
||||
"codec": "video/H265",
|
||||
"effectiveFramesPerSecond": 58.5,
|
||||
"configuredFramesPerSecond": 60,
|
||||
"targetFramesPerSecond": 60,
|
||||
"frameWidth": 1920,
|
||||
"frameHeight": 1080
|
||||
},
|
||||
"remoteAudio": {"trackIdentifier": "remote-audio"}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"name": "remote subscription quality and participant volume commands",
|
||||
"events": [
|
||||
{"type": "connection.connectRequested", "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{
|
||||
"type": "remoteTrackSubscription.setRequested",
|
||||
"options": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": true,
|
||||
"enabled": true,
|
||||
"quality": "high"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "remoteTrackSubscription.setRequested",
|
||||
"options": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": true,
|
||||
"enabled": true,
|
||||
"quality": "high"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "remoteTrackSubscription.setRequested",
|
||||
"options": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": true,
|
||||
"enabled": true,
|
||||
"quality": "low"
|
||||
}
|
||||
},
|
||||
{"type": "participantVolume.setRequested", "options": {"participantIdentity": "alice", "volume": 0.35}},
|
||||
{"type": "participantVolume.setRequested", "options": {"participantIdentity": "alice", "volume": 0.35}}
|
||||
],
|
||||
"expected": {
|
||||
"remoteTrackSubscriptions": {
|
||||
"alice:screen": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": true,
|
||||
"enabled": true,
|
||||
"quality": "low"
|
||||
}
|
||||
},
|
||||
"participantVolumes": {"alice": 0.35},
|
||||
"commands": [
|
||||
{"type": "connection.connect", "operationId": 1, "options": {"url": "wss://voice", "token": "token"}},
|
||||
{
|
||||
"type": "remoteTrackSubscription.set",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": true,
|
||||
"enabled": true,
|
||||
"quality": "high"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "remoteTrackSubscription.set",
|
||||
"operationId": 3,
|
||||
"options": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": true,
|
||||
"enabled": true,
|
||||
"quality": "low"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "participantVolume.set",
|
||||
"operationId": 4,
|
||||
"options": {"participantIdentity": "alice", "volume": 0.35}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"name": "teardown_renderer_window",
|
||||
"description": "Renderer teardown clears gateway state, disconnects media, then runs host lifecycle teardown.",
|
||||
"steps": [
|
||||
{
|
||||
"name": "gateway channel observed",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateUpdated",
|
||||
"voiceState": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-1",
|
||||
"userId": "user-1",
|
||||
"sessionId": "session-1",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false,
|
||||
"selfVideo": false,
|
||||
"selfStream": false,
|
||||
"suppress": false,
|
||||
"requestToSpeakTimestamp": null
|
||||
}
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "media connection requested",
|
||||
"event": {
|
||||
"type": "connection.connectRequested",
|
||||
"options": {
|
||||
"url": "wss://voice-one.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "connection.connect",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"url": "wss://voice-one.example.test",
|
||||
"token": "token-1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "media connection succeeds",
|
||||
"event": {
|
||||
"type": "connection.connectSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
"commands": []
|
||||
},
|
||||
{
|
||||
"name": "renderer teardown requested",
|
||||
"event": {
|
||||
"type": "lifecycle.teardownRequested",
|
||||
"reason": "rendererDisposed"
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "gateway.voiceState.clear",
|
||||
"operationId": 2,
|
||||
"guildId": "guild-1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gateway clear succeeds",
|
||||
"event": {
|
||||
"type": "gateway.voiceStateClearSucceeded",
|
||||
"operationId": 2
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "connection.disconnect",
|
||||
"operationId": 3,
|
||||
"reason": "shutdown"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "media disconnect succeeds",
|
||||
"event": {
|
||||
"type": "connection.disconnectSucceeded",
|
||||
"operationId": 3
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"type": "lifecycle.teardown",
|
||||
"operationId": 4,
|
||||
"reason": "rendererDisposed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "host teardown succeeds",
|
||||
"event": {
|
||||
"type": "lifecycle.teardownSucceeded",
|
||||
"operationId": 4
|
||||
},
|
||||
"commands": []
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 5,
|
||||
"connectionStatus": "idle",
|
||||
"activeUrl": null,
|
||||
"desiredUrl": null,
|
||||
"gatewayChannelId": null,
|
||||
"lifecycleTearingDown": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "watched streams drive subscription commands",
|
||||
"events": [
|
||||
{"type": "connection.connectRequested", "options": {"url": "wss://voice", "token": "token"}},
|
||||
{"type": "connection.connectSucceeded", "operationId": 1},
|
||||
{
|
||||
"type": "watchedStream.watchRequested",
|
||||
"stream": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"trackSid": null,
|
||||
"quality": "high",
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "room.trackPublished",
|
||||
"track": {
|
||||
"participantIdentity": "alice",
|
||||
"participantSid": "PA_alice",
|
||||
"trackSid": "TR_screen",
|
||||
"trackName": "screen",
|
||||
"kind": "video",
|
||||
"source": "screen",
|
||||
"muted": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "watchedStream.watchRequested",
|
||||
"stream": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"trackSid": "TR_screen",
|
||||
"quality": "low",
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
{"type": "watchedStream.unwatchRequested", "stream": {"participantIdentity": "alice", "source": "screen"}}
|
||||
],
|
||||
"expected": {
|
||||
"watchedStreams": [],
|
||||
"remoteTrackSubscriptions": {
|
||||
"alice:screen": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": false,
|
||||
"enabled": false,
|
||||
"quality": "low"
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{"type": "connection.connect", "operationId": 1, "options": {"url": "wss://voice", "token": "token"}},
|
||||
{
|
||||
"type": "remoteTrackSubscription.set",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": true,
|
||||
"enabled": true,
|
||||
"quality": "high"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "remoteTrackSubscription.set",
|
||||
"operationId": 3,
|
||||
"options": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": true,
|
||||
"enabled": true,
|
||||
"quality": "low"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "remoteTrackSubscription.set",
|
||||
"operationId": 4,
|
||||
"options": {
|
||||
"participantIdentity": "alice",
|
||||
"source": "screen",
|
||||
"subscribed": false,
|
||||
"enabled": false,
|
||||
"quality": "low"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"name": "externally_established_session",
|
||||
"events": [
|
||||
{
|
||||
"type": "microphone.publishRequested",
|
||||
"options": {
|
||||
"deviceId": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "connection.externallyEstablished",
|
||||
"options": {
|
||||
"url": "wss://voice.example.test",
|
||||
"token": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "microphone.publishSucceeded",
|
||||
"operationId": 1
|
||||
},
|
||||
{
|
||||
"type": "connection.remoteDisconnected",
|
||||
"reason": "network"
|
||||
},
|
||||
{
|
||||
"type": "microphone.publishRequested",
|
||||
"options": {
|
||||
"deviceId": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "connection.externallyEstablished",
|
||||
"options": {
|
||||
"url": "wss://voice-reconnect.example.test",
|
||||
"token": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "microphone.publishSucceeded",
|
||||
"operationId": 2
|
||||
},
|
||||
{
|
||||
"type": "gateway.voiceStateUpdated",
|
||||
"voiceState": {
|
||||
"guildId": "guild-1",
|
||||
"channelId": "channel-1",
|
||||
"userId": "user-1",
|
||||
"sessionId": "session-1",
|
||||
"selfMute": false,
|
||||
"selfDeaf": false,
|
||||
"selfVideo": false,
|
||||
"selfStream": false,
|
||||
"suppress": false,
|
||||
"requestToSpeakTimestamp": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"nextOperationId": 3,
|
||||
"connectionStatus": "connected",
|
||||
"activeUrl": "wss://voice-reconnect.example.test",
|
||||
"microphoneStatus": "published",
|
||||
"microphoneDeviceId": "default",
|
||||
"gatewayChannelId": "channel-1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
[
|
||||
{
|
||||
"name": "valid zero-copy native capture start",
|
||||
"command": {
|
||||
"type": "nativeCapture.start",
|
||||
"operationId": 1,
|
||||
"options": {
|
||||
"captureId": "capture-1",
|
||||
"source": {
|
||||
"id": "display-1",
|
||||
"kind": "screen",
|
||||
"title": "Display 1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"displayId": "display-1"
|
||||
},
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"frameRate": 60,
|
||||
"includeCursor": true,
|
||||
"includeAudio": false,
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
"expectedOk": true
|
||||
},
|
||||
{
|
||||
"name": "reject native capture start without zero-copy requirement",
|
||||
"command": {
|
||||
"type": "nativeCapture.start",
|
||||
"operationId": 2,
|
||||
"options": {
|
||||
"captureId": "capture-2",
|
||||
"source": {
|
||||
"id": "window-1",
|
||||
"kind": "window",
|
||||
"title": "Window 1",
|
||||
"windowId": "window-1"
|
||||
},
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"frameRate": 60,
|
||||
"includeCursor": true,
|
||||
"includeAudio": false,
|
||||
"zeroCopyRequired": false
|
||||
}
|
||||
},
|
||||
"expectedOk": false,
|
||||
"expectedError": "zeroCopyRequired"
|
||||
},
|
||||
{
|
||||
"name": "reject native frame sink without zero-copy requirement",
|
||||
"command": {
|
||||
"type": "nativeFrameSink.attach",
|
||||
"operationId": 3,
|
||||
"options": {
|
||||
"sinkId": "sink-1",
|
||||
"captureId": "capture-1",
|
||||
"trackSid": "TR_screen",
|
||||
"zeroCopyRequired": false
|
||||
}
|
||||
},
|
||||
"expectedOk": false,
|
||||
"expectedError": "zeroCopyRequired"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,78 @@
|
||||
[
|
||||
{
|
||||
"name": "mirror toggle updates in place",
|
||||
"input": {
|
||||
"published": {"deviceId": "camera-1", "width": 1280, "height": 720, "mirror": false},
|
||||
"desired": null,
|
||||
"update": {"mirror": true}
|
||||
},
|
||||
"expectedAction": "updateEncoding",
|
||||
"expectedReason": "effectsOrEncodingChanged",
|
||||
"expectedMirror": true
|
||||
},
|
||||
{
|
||||
"name": "background mode and blur strength update in place",
|
||||
"input": {
|
||||
"published": {"deviceId": "camera-1", "width": 1280, "height": 720, "backgroundMode": "none"},
|
||||
"desired": null,
|
||||
"update": {"backgroundMode": "blur", "backgroundBlurStrength": 70}
|
||||
},
|
||||
"expectedAction": "updateEncoding",
|
||||
"expectedReason": "effectsOrEncodingChanged",
|
||||
"expectedBackgroundMode": "blur"
|
||||
},
|
||||
{
|
||||
"name": "resolution and frame rate update in place",
|
||||
"input": {
|
||||
"published": {"deviceId": "camera-1", "width": 1280, "height": 720, "frameRate": 30},
|
||||
"desired": null,
|
||||
"update": {"width": 1920, "height": 1080, "frameRate": 60}
|
||||
},
|
||||
"expectedAction": "updateEncoding",
|
||||
"expectedReason": "effectsOrEncodingChanged",
|
||||
"expectedWidth": 1920,
|
||||
"expectedFrameRate": 60
|
||||
},
|
||||
{
|
||||
"name": "device change republishes",
|
||||
"input": {
|
||||
"published": {"deviceId": "camera-1", "width": 1280, "height": 720},
|
||||
"desired": null,
|
||||
"update": {"deviceId": "camera-2"}
|
||||
},
|
||||
"expectedAction": "republish",
|
||||
"expectedReason": "deviceChanged"
|
||||
},
|
||||
{
|
||||
"name": "codec change republishes",
|
||||
"input": {
|
||||
"published": {"deviceId": "camera-1", "width": 1280, "height": 720, "codec": "vp8"},
|
||||
"desired": null,
|
||||
"update": {"codec": "vp9"}
|
||||
},
|
||||
"expectedAction": "republish",
|
||||
"expectedReason": "codecChanged",
|
||||
"expectedCodec": "vp9"
|
||||
},
|
||||
{
|
||||
"name": "identical options is a no-op",
|
||||
"input": {
|
||||
"published": {"deviceId": "camera-1", "width": 1280, "height": 720, "mirror": true},
|
||||
"desired": null,
|
||||
"update": {"width": 1280, "height": 720, "mirror": true}
|
||||
},
|
||||
"expectedAction": "noop",
|
||||
"expectedReason": "unchanged"
|
||||
},
|
||||
{
|
||||
"name": "missing published camera rejects",
|
||||
"input": {
|
||||
"published": null,
|
||||
"desired": null,
|
||||
"update": {"mirror": true}
|
||||
},
|
||||
"expectedAction": "reject",
|
||||
"expectedReason": "missingPublishedCamera",
|
||||
"expectedErrorCode": "invalidArgument"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{"raw": "encrypted", "expected": "encrypted"},
|
||||
{"raw": "ok", "expected": "encrypted"},
|
||||
{"raw": "decryption_failed", "expected": "decryption_failed"},
|
||||
{"raw": "decryptionFailed", "expected": "decryption_failed"},
|
||||
{"raw": "error", "expected": "decryption_failed"},
|
||||
{"raw": "broken", "expected": "decryption_failed"},
|
||||
{"raw": "unencrypted", "expected": "unencrypted"},
|
||||
{"raw": "missing_key", "expected": "unencrypted"},
|
||||
{"raw": "missingKey", "expected": "unencrypted"},
|
||||
{"raw": "internal_error", "expected": "unencrypted"},
|
||||
{"raw": "unexpected", "expected": "unknown"},
|
||||
{"raw": null, "expected": "unknown"}
|
||||
]
|
||||
@@ -0,0 +1,134 @@
|
||||
[
|
||||
{
|
||||
"name": "invalid native addon result is unavailable",
|
||||
"input": null,
|
||||
"codec": "h265",
|
||||
"expectedCapabilities": {
|
||||
"available": false,
|
||||
"backend": "none",
|
||||
"compiled": false,
|
||||
"runtime": false,
|
||||
"codecs": [],
|
||||
"zeroCopy": false,
|
||||
"nativeInputs": [],
|
||||
"reason": "query-failed",
|
||||
"detail": "Native addon returned an invalid result"
|
||||
},
|
||||
"expectedNativeNvenc": false
|
||||
},
|
||||
{
|
||||
"name": "zero-copy native NVENC H265 is usable",
|
||||
"input": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "h265"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": ["dmabuf"]
|
||||
},
|
||||
"codec": "h265",
|
||||
"expectedCapabilities": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "h265"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": ["dmabuf"]
|
||||
},
|
||||
"expectedNativeNvenc": true
|
||||
},
|
||||
{
|
||||
"name": "HEVC codec alias enables H265 when zero-copy NVENC is available",
|
||||
"input": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["hevc"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": ["d3d11-texture"]
|
||||
},
|
||||
"codec": "h265",
|
||||
"expectedCapabilities": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["hevc"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": ["d3d11-texture"]
|
||||
},
|
||||
"expectedNativeNvenc": true
|
||||
},
|
||||
{
|
||||
"name": "native NVENC without zero-copy is not supported",
|
||||
"input": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "h265"],
|
||||
"zeroCopy": false,
|
||||
"nativeInputs": ["dmabuf"]
|
||||
},
|
||||
"codec": "h265",
|
||||
"expectedCapabilities": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "h265"],
|
||||
"zeroCopy": false,
|
||||
"nativeInputs": ["dmabuf"]
|
||||
},
|
||||
"expectedNativeNvenc": false
|
||||
},
|
||||
{
|
||||
"name": "native NVENC without native zero-copy input handles is not supported",
|
||||
"input": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "h265"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": []
|
||||
},
|
||||
"codec": "h264",
|
||||
"expectedCapabilities": {
|
||||
"available": true,
|
||||
"backend": "nvenc",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "h265"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": []
|
||||
},
|
||||
"expectedNativeNvenc": false
|
||||
},
|
||||
{
|
||||
"name": "non-NVENC backends are not selected by NVENC policy",
|
||||
"input": {
|
||||
"available": true,
|
||||
"backend": "videotoolbox",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "h265"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": ["cvPixelBuffer"]
|
||||
},
|
||||
"codec": "h265",
|
||||
"expectedCapabilities": {
|
||||
"available": true,
|
||||
"backend": "videotoolbox",
|
||||
"compiled": true,
|
||||
"runtime": true,
|
||||
"codecs": ["h264", "h265"],
|
||||
"zeroCopy": true,
|
||||
"nativeInputs": ["cvPixelBuffer"]
|
||||
},
|
||||
"expectedNativeNvenc": false
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"name": "camera unpublish suppressed during reconnect when video restore is pending",
|
||||
"input": {"source": "camera", "enabled": false, "reconnecting": true, "restoreVideo": true, "restoreStream": false},
|
||||
"expected": true
|
||||
},
|
||||
{
|
||||
"name": "screen share unpublish suppressed during reconnect when stream restore is pending",
|
||||
"input": {
|
||||
"source": "screen_share",
|
||||
"enabled": false,
|
||||
"reconnecting": true,
|
||||
"restoreVideo": false,
|
||||
"restoreStream": true
|
||||
},
|
||||
"expected": true
|
||||
},
|
||||
{
|
||||
"name": "publish events are not suppressed",
|
||||
"input": {
|
||||
"source": "screen_share",
|
||||
"enabled": true,
|
||||
"reconnecting": true,
|
||||
"restoreVideo": false,
|
||||
"restoreStream": true
|
||||
},
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "inactive reconnect is not suppressed",
|
||||
"input": {
|
||||
"source": "screen_share",
|
||||
"enabled": false,
|
||||
"reconnecting": false,
|
||||
"restoreVideo": false,
|
||||
"restoreStream": true
|
||||
},
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "camera without video restore is not suppressed",
|
||||
"input": {"source": "camera", "enabled": false, "reconnecting": true, "restoreVideo": false, "restoreStream": true},
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "microphone is not suppressed",
|
||||
"input": {
|
||||
"source": "microphone",
|
||||
"enabled": false,
|
||||
"reconnecting": true,
|
||||
"restoreVideo": true,
|
||||
"restoreStream": true
|
||||
},
|
||||
"expected": false
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,175 @@
|
||||
[
|
||||
{
|
||||
"name": "successful operation",
|
||||
"result": {"ok": true},
|
||||
"requestedEnabled": true,
|
||||
"expected": "none"
|
||||
},
|
||||
{
|
||||
"name": "disabled microphone not connected",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "not-connected",
|
||||
"message": "Native voice engine is not connected"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": false,
|
||||
"expected": "none"
|
||||
},
|
||||
{
|
||||
"name": "unsupported microphone capture",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "unsupported-capability",
|
||||
"capability": "microphoneCapture",
|
||||
"message": "Native voice engine addon does not support device microphone capture"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"expected": "crash"
|
||||
},
|
||||
{
|
||||
"name": "invalid args",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "invalid-args",
|
||||
"message": "Invalid voice-engine publish-microphone args"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"expected": "crash"
|
||||
},
|
||||
{
|
||||
"name": "modern not connected",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "not-connected",
|
||||
"capability": "microphoneCapture",
|
||||
"message": "Native voice engine is not connected"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"expected": "defer"
|
||||
},
|
||||
{
|
||||
"name": "legacy not connected",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "native-error",
|
||||
"capability": "microphoneCapture",
|
||||
"message": "not connected"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"expected": "defer"
|
||||
},
|
||||
{
|
||||
"name": "device unavailable",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "native-error",
|
||||
"capability": "microphoneCapture",
|
||||
"message": "device unavailable"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"expected": "mute"
|
||||
},
|
||||
{
|
||||
"name": "timeout failure defers without muting",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "timeout",
|
||||
"message": "Voice engine v2 microphone enable timed out"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"expected": "defer"
|
||||
},
|
||||
{
|
||||
"name": "cancelled failure defers without muting",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "cancelled",
|
||||
"message": "Voice engine v2 microphone enable cancelled"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"expected": "defer"
|
||||
},
|
||||
{
|
||||
"name": "livekit transport failure defers without muting",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "liveKitError",
|
||||
"message": "could not establish pc connection"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"expected": "defer"
|
||||
},
|
||||
{
|
||||
"name": "opaque failure during reconnect defers without muting",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "native-error",
|
||||
"capability": "microphoneCapture",
|
||||
"message": "engine resume in progress"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"context": {"reconnecting": true},
|
||||
"expected": "defer"
|
||||
},
|
||||
{
|
||||
"name": "opaque failure while stable still mutes",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "native-error",
|
||||
"capability": "microphoneCapture",
|
||||
"message": "engine resume in progress"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"context": {"reconnecting": false},
|
||||
"expected": "mute"
|
||||
},
|
||||
{
|
||||
"name": "invalid args during reconnect still crashes",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "invalid-args",
|
||||
"message": "Invalid voice-engine publish-microphone args"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": true,
|
||||
"context": {"reconnecting": true},
|
||||
"expected": "crash"
|
||||
},
|
||||
{
|
||||
"name": "disable failure during reconnect stays none",
|
||||
"result": {
|
||||
"ok": false,
|
||||
"error": {
|
||||
"code": "native-error",
|
||||
"capability": "microphoneCapture",
|
||||
"message": "engine resume in progress"
|
||||
}
|
||||
},
|
||||
"requestedEnabled": false,
|
||||
"context": {"reconnecting": true},
|
||||
"expected": "none"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,98 @@
|
||||
[
|
||||
{
|
||||
"name": "retry while accepted connection is still connecting before gateway echo",
|
||||
"input": {
|
||||
"connectionId": "connection-a",
|
||||
"guildId": "guild-a",
|
||||
"channelId": "channel-a",
|
||||
"voiceState": null,
|
||||
"connectionState": {
|
||||
"connectionId": "connection-a",
|
||||
"guildId": "guild-a",
|
||||
"channelId": "channel-a",
|
||||
"connecting": true,
|
||||
"connected": false,
|
||||
"reconnecting": false
|
||||
}
|
||||
},
|
||||
"expected": true
|
||||
},
|
||||
{
|
||||
"name": "retry when gateway voice state confirms channel",
|
||||
"input": {
|
||||
"connectionId": "connection-a",
|
||||
"guildId": "guild-a",
|
||||
"channelId": "channel-a",
|
||||
"voiceState": {
|
||||
"guild_id": "guild-a",
|
||||
"channel_id": "channel-a"
|
||||
},
|
||||
"connectionState": {
|
||||
"connectionId": "stale-connection",
|
||||
"guildId": "guild-a",
|
||||
"channelId": "channel-a",
|
||||
"connecting": false,
|
||||
"connected": false,
|
||||
"reconnecting": false
|
||||
}
|
||||
},
|
||||
"expected": true
|
||||
},
|
||||
{
|
||||
"name": "reject stale local connection",
|
||||
"input": {
|
||||
"connectionId": "connection-a",
|
||||
"guildId": "guild-a",
|
||||
"channelId": "channel-a",
|
||||
"voiceState": null,
|
||||
"connectionState": {
|
||||
"connectionId": "connection-b",
|
||||
"guildId": "guild-a",
|
||||
"channelId": "channel-a",
|
||||
"connecting": true,
|
||||
"connected": false,
|
||||
"reconnecting": false
|
||||
}
|
||||
},
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "reject inactive accepted connection",
|
||||
"input": {
|
||||
"connectionId": "connection-a",
|
||||
"guildId": "guild-a",
|
||||
"channelId": "channel-a",
|
||||
"voiceState": null,
|
||||
"connectionState": {
|
||||
"connectionId": "connection-a",
|
||||
"guildId": "guild-a",
|
||||
"channelId": "channel-a",
|
||||
"connecting": false,
|
||||
"connected": false,
|
||||
"reconnecting": false
|
||||
}
|
||||
},
|
||||
"expected": false
|
||||
},
|
||||
{
|
||||
"name": "treat null guild ids as equivalent private voice scope",
|
||||
"input": {
|
||||
"connectionId": "connection-a",
|
||||
"guildId": null,
|
||||
"channelId": "dm-channel-a",
|
||||
"voiceState": {
|
||||
"guild_id": null,
|
||||
"channel_id": "dm-channel-a"
|
||||
},
|
||||
"connectionState": {
|
||||
"connectionId": "connection-b",
|
||||
"guildId": null,
|
||||
"channelId": "dm-channel-a",
|
||||
"connecting": false,
|
||||
"connected": false,
|
||||
"reconnecting": false
|
||||
}
|
||||
},
|
||||
"expected": true
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,37 @@
|
||||
[
|
||||
{
|
||||
"name": "local mute wins",
|
||||
"input": {"userVolumePercent": 200, "outputVolumePercent": 100, "locallyMuted": true},
|
||||
"expected": 0
|
||||
},
|
||||
{
|
||||
"name": "unity gain",
|
||||
"input": {"userVolumePercent": 100, "outputVolumePercent": 100, "locallyMuted": false},
|
||||
"expected": 1
|
||||
},
|
||||
{
|
||||
"name": "max user volume reaches ceiling",
|
||||
"input": {"userVolumePercent": 200, "outputVolumePercent": 100, "locallyMuted": false},
|
||||
"expected": 2
|
||||
},
|
||||
{
|
||||
"name": "quiet participant below unity",
|
||||
"input": {"userVolumePercent": 50, "outputVolumePercent": 100, "locallyMuted": false},
|
||||
"expectedRange": {"minExclusive": 0, "maxExclusive": 1}
|
||||
},
|
||||
{
|
||||
"name": "zero composed volume",
|
||||
"input": {"userVolumePercent": 0, "outputVolumePercent": 100, "locallyMuted": false},
|
||||
"expected": 0
|
||||
},
|
||||
{
|
||||
"name": "non finite values fall back to unity inputs",
|
||||
"input": {"userVolumePercent": null, "outputVolumePercent": null, "locallyMuted": false},
|
||||
"expected": 1
|
||||
},
|
||||
{
|
||||
"name": "oversized values clamp to native range",
|
||||
"input": {"userVolumePercent": 999, "outputVolumePercent": 999, "locallyMuted": false},
|
||||
"expectedRange": {"minInclusive": 0, "maxInclusive": 2}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,112 @@
|
||||
[
|
||||
{
|
||||
"name": "dimensions and bitrate update in place",
|
||||
"input": {
|
||||
"published": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h264",
|
||||
"maxFramerate": 60,
|
||||
"maxBitrateBps": 8000000
|
||||
},
|
||||
"desired": null,
|
||||
"update": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"frameRate": 30,
|
||||
"maxBitrateBps": 3000000
|
||||
}
|
||||
},
|
||||
"expectedAction": "updateEncoding",
|
||||
"expectedReason": "dimensionsOrBitrateChanged",
|
||||
"expectedCodec": "h264"
|
||||
},
|
||||
{
|
||||
"name": "codec change republishes",
|
||||
"input": {
|
||||
"published": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h264"
|
||||
},
|
||||
"desired": null,
|
||||
"update": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h265"
|
||||
}
|
||||
},
|
||||
"expectedAction": "republish",
|
||||
"expectedReason": "codecChanged",
|
||||
"expectedCodec": "h265"
|
||||
},
|
||||
{
|
||||
"name": "hardware encoder change republishes",
|
||||
"input": {
|
||||
"published": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h264",
|
||||
"hardwareEncoding": false
|
||||
},
|
||||
"desired": null,
|
||||
"update": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"hardwareEncoding": true,
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
"expectedAction": "republish",
|
||||
"expectedReason": "hardwareEncoderChanged",
|
||||
"expectedHardwareEncoding": true
|
||||
},
|
||||
{
|
||||
"name": "zero-copy requirement change republishes",
|
||||
"input": {
|
||||
"published": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h264",
|
||||
"zeroCopyRequired": false
|
||||
},
|
||||
"desired": null,
|
||||
"update": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"zeroCopyRequired": true
|
||||
}
|
||||
},
|
||||
"expectedAction": "republish",
|
||||
"expectedReason": "zeroCopyRequirementChanged",
|
||||
"expectedZeroCopyRequired": true
|
||||
},
|
||||
{
|
||||
"name": "capture mismatch rejects",
|
||||
"input": {
|
||||
"published": {
|
||||
"captureId": "capture-1",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"codec": "h264"
|
||||
},
|
||||
"desired": null,
|
||||
"update": {
|
||||
"captureId": "capture-2",
|
||||
"width": 1920,
|
||||
"height": 1080
|
||||
}
|
||||
},
|
||||
"expectedAction": "reject",
|
||||
"expectedReason": "captureMismatch",
|
||||
"expectedErrorCode": "invalidArgument"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,188 @@
|
||||
[
|
||||
{
|
||||
"name": "coerces malformed sparse payload to safe defaults",
|
||||
"input": {
|
||||
"rttMs": "bad",
|
||||
"droppedVideoFrameCallbacks": -2,
|
||||
"droppedNativeVideoFrames": 3.8,
|
||||
"outbound": [
|
||||
null,
|
||||
{
|
||||
"trackSid": "",
|
||||
"source": 42,
|
||||
"kind": "data",
|
||||
"bitrateKbps": "bad",
|
||||
"packetsLost": null,
|
||||
"width": 1920.9,
|
||||
"framesDropped": -4.2,
|
||||
"zeroCopy": false
|
||||
}
|
||||
],
|
||||
"inbound": [
|
||||
null,
|
||||
{
|
||||
"participantSid": "PA_1",
|
||||
"trackSid": "TR_audio",
|
||||
"kind": "audio",
|
||||
"bitrateKbps": 42.5,
|
||||
"packetsLost": 2,
|
||||
"jitterMs": "bad",
|
||||
"audioLevel": 0.5
|
||||
}
|
||||
],
|
||||
"send": null
|
||||
},
|
||||
"expected": {
|
||||
"rttMs": null,
|
||||
"droppedVideoFrameCallbacks": 0,
|
||||
"droppedNativeVideoFrames": 3,
|
||||
"outbound": [
|
||||
{
|
||||
"trackSid": "",
|
||||
"source": "",
|
||||
"kind": "audio",
|
||||
"bitrateKbps": 0,
|
||||
"packetsLost": 0,
|
||||
"width": 1920,
|
||||
"framesDropped": 0
|
||||
}
|
||||
],
|
||||
"inbound": [
|
||||
{
|
||||
"participantSid": "PA_1",
|
||||
"trackSid": "TR_audio",
|
||||
"kind": "audio",
|
||||
"bitrateKbps": 42.5,
|
||||
"packetsLost": 2,
|
||||
"audioLevel": 0.5
|
||||
}
|
||||
],
|
||||
"send": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "preserves native video diagnostics and clamps send stats",
|
||||
"input": {
|
||||
"rttMs": 27,
|
||||
"droppedVideoFrameCallbacks": 2,
|
||||
"outbound": [
|
||||
{
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screen",
|
||||
"kind": "video",
|
||||
"codec": "video/H265",
|
||||
"bitrateKbps": 2500.25,
|
||||
"packetsLost": 1,
|
||||
"fps": 59.5,
|
||||
"audioLevel": 0.1,
|
||||
"width": 2176,
|
||||
"height": 1200,
|
||||
"sourceWidth": 2176,
|
||||
"sourceHeight": 1200,
|
||||
"targetBitrateKbps": 50000,
|
||||
"configuredFps": 60,
|
||||
"targetFps": 60,
|
||||
"effectiveFps": 58.7,
|
||||
"framesProduced": 120.8,
|
||||
"framesAccepted": 119.4,
|
||||
"framesDropped": 1.9,
|
||||
"framesCoalesced": 0,
|
||||
"framesCaptured": 118.2,
|
||||
"captureFailures": 0,
|
||||
"maxQueueAgeMs": 12.5,
|
||||
"maxPushLatencyMs": 8.25,
|
||||
"adaptiveSendTier": "full",
|
||||
"adaptiveSendReason": "disabled",
|
||||
"zeroCopy": true
|
||||
}
|
||||
],
|
||||
"inbound": [],
|
||||
"send": {
|
||||
"outgoingVideoQueueDepth": 4,
|
||||
"outgoingVideoQueueCapacity": 8,
|
||||
"outgoingVideoMaxQueueDepth": 6,
|
||||
"outgoingVideoFramesProduced": 120,
|
||||
"outgoingVideoFramesAccepted": 119,
|
||||
"outgoingVideoFramesDropped": 1,
|
||||
"outgoingVideoFramesCoalesced": 0,
|
||||
"outgoingVideoFramesCaptured": 118,
|
||||
"outgoingVideoCaptureFailures": -1,
|
||||
"outgoingVideoEffectiveFps": 58.7,
|
||||
"outgoingVideoTargetFps": 60,
|
||||
"outgoingVideoPacingTargetFps": 60,
|
||||
"outgoingVideoMaxQueueAgeMs": 12.5,
|
||||
"outgoingVideoMaxPushLatencyMs": 8.25,
|
||||
"outgoingVideoPacingMode": "source",
|
||||
"outgoingVideoBusActive": true,
|
||||
"outgoingAudioBufferTargetMs": 20,
|
||||
"outgoingAudioBufferMaxMs": 80,
|
||||
"outgoingAudioUnderruns": 0,
|
||||
"outgoingAudioRebuffers": 1,
|
||||
"outgoingAudioMaxFrameGapMs": 24,
|
||||
"adaptiveSendTier": "full",
|
||||
"adaptiveSendReason": "disabled"
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"rttMs": 27,
|
||||
"droppedVideoFrameCallbacks": 2,
|
||||
"outbound": [
|
||||
{
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screen",
|
||||
"kind": "video",
|
||||
"codec": "video/H265",
|
||||
"bitrateKbps": 2500.25,
|
||||
"packetsLost": 1,
|
||||
"fps": 59.5,
|
||||
"audioLevel": 0.1,
|
||||
"width": 2176,
|
||||
"height": 1200,
|
||||
"sourceWidth": 2176,
|
||||
"sourceHeight": 1200,
|
||||
"targetBitrateKbps": 50000,
|
||||
"configuredFps": 60,
|
||||
"targetFps": 60,
|
||||
"effectiveFps": 58.7,
|
||||
"framesProduced": 120,
|
||||
"framesAccepted": 119,
|
||||
"framesDropped": 1,
|
||||
"framesCoalesced": 0,
|
||||
"framesCaptured": 118,
|
||||
"captureFailures": 0,
|
||||
"maxQueueAgeMs": 12.5,
|
||||
"maxPushLatencyMs": 8.25,
|
||||
"adaptiveSendTier": "full",
|
||||
"adaptiveSendReason": "disabled",
|
||||
"zeroCopy": true
|
||||
}
|
||||
],
|
||||
"inbound": [],
|
||||
"send": {
|
||||
"outgoingVideoQueueDepth": 4,
|
||||
"outgoingVideoQueueCapacity": 8,
|
||||
"outgoingVideoMaxQueueDepth": 6,
|
||||
"outgoingVideoFramesProduced": 120,
|
||||
"outgoingVideoFramesAccepted": 119,
|
||||
"outgoingVideoFramesDropped": 1,
|
||||
"outgoingVideoFramesCoalesced": 0,
|
||||
"outgoingVideoFramesCaptured": 118,
|
||||
"outgoingVideoCaptureFailures": 0,
|
||||
"outgoingVideoEffectiveFps": 58.7,
|
||||
"outgoingVideoTargetFps": 60,
|
||||
"outgoingVideoPacingTargetFps": 60,
|
||||
"outgoingVideoMaxQueueAgeMs": 12.5,
|
||||
"outgoingVideoMaxPushLatencyMs": 8.25,
|
||||
"outgoingVideoPacingMode": "source",
|
||||
"outgoingVideoBusActive": true,
|
||||
"outgoingAudioBufferTargetMs": 20,
|
||||
"outgoingAudioBufferMaxMs": 80,
|
||||
"outgoingAudioUnderruns": 0,
|
||||
"outgoingAudioRebuffers": 1,
|
||||
"outgoingAudioMaxFrameGapMs": 24,
|
||||
"adaptiveSendTier": "full",
|
||||
"adaptiveSendReason": "disabled"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,382 @@
|
||||
[
|
||||
{
|
||||
"name": "splits outbound camera and screen-share video by source",
|
||||
"input": {
|
||||
"rttMs": null,
|
||||
"outbound": [
|
||||
{
|
||||
"trackSid": "cam",
|
||||
"source": "camera",
|
||||
"kind": "video",
|
||||
"bitrateKbps": 500,
|
||||
"packetsLost": 0,
|
||||
"packetsSent": 500,
|
||||
"fps": 30
|
||||
},
|
||||
{
|
||||
"trackSid": "ss",
|
||||
"source": "screen_share",
|
||||
"kind": "video",
|
||||
"bitrateKbps": 3000,
|
||||
"packetsLost": 1,
|
||||
"packetsSent": 100,
|
||||
"fps": 60
|
||||
}
|
||||
],
|
||||
"inbound": []
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 0,
|
||||
"audioRecvBitrateKbps": 0,
|
||||
"videoSendBitrateKbps": 3500,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 0,
|
||||
"videoPacketLossPercent": 1,
|
||||
"jitterMs": 0,
|
||||
"rttMs": null
|
||||
},
|
||||
"localVideo": {"trackIdentifier": "cam", "framesPerSecond": 30},
|
||||
"localScreenShare": {"trackIdentifier": "ss", "framesPerSecond": 60}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "normalizes screenshare alias without underscore",
|
||||
"input": {
|
||||
"rttMs": null,
|
||||
"outbound": [{"trackSid": "ss", "source": "screenshare", "kind": "video", "bitrateKbps": 1000, "packetsLost": 0}],
|
||||
"inbound": []
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 0,
|
||||
"audioRecvBitrateKbps": 0,
|
||||
"videoSendBitrateKbps": 1000,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 0,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 0,
|
||||
"rttMs": null
|
||||
},
|
||||
"localVideo": null,
|
||||
"localScreenShare": {"trackIdentifier": "ss"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "preserves native screen-share codec dimensions fps and diagnostics",
|
||||
"input": {
|
||||
"rttMs": 1,
|
||||
"outbound": [
|
||||
{
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screenshare",
|
||||
"kind": "video",
|
||||
"codec": "video/H265",
|
||||
"bitrateKbps": 2500,
|
||||
"packetsLost": 0,
|
||||
"fps": 14,
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"sourceWidth": 2176,
|
||||
"sourceHeight": 1200,
|
||||
"targetBitrateKbps": 50000,
|
||||
"configuredFps": 60,
|
||||
"targetFps": 60,
|
||||
"effectiveFps": 58.7,
|
||||
"framesProduced": 120,
|
||||
"framesAccepted": 119,
|
||||
"framesDropped": 1,
|
||||
"framesCoalesced": 0,
|
||||
"framesCaptured": 118,
|
||||
"captureFailures": 0,
|
||||
"maxQueueAgeMs": 12.5,
|
||||
"maxPushLatencyMs": 8.25,
|
||||
"adaptiveSendTier": "full",
|
||||
"adaptiveSendReason": "disabled"
|
||||
}
|
||||
],
|
||||
"inbound": []
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 0,
|
||||
"audioRecvBitrateKbps": 0,
|
||||
"videoSendBitrateKbps": 2500,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 0,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 0,
|
||||
"rttMs": 1
|
||||
},
|
||||
"localScreenShare": {
|
||||
"trackIdentifier": "TR_screen",
|
||||
"codec": "video/H265",
|
||||
"framesPerSecond": 58.7,
|
||||
"configuredFramesPerSecond": 60,
|
||||
"targetFramesPerSecond": 60,
|
||||
"effectiveFramesPerSecond": 58.7,
|
||||
"frameWidth": 1280,
|
||||
"frameHeight": 720,
|
||||
"sourceFrameWidth": 2176,
|
||||
"sourceFrameHeight": 1200,
|
||||
"targetBitrateKbps": 50000,
|
||||
"framesProduced": 120,
|
||||
"framesAccepted": 119,
|
||||
"framesDropped": 1,
|
||||
"framesCaptured": 118,
|
||||
"maxQueueAgeMs": 12.5,
|
||||
"maxPushLatencyMs": 8.25,
|
||||
"adaptiveSendTier": "full",
|
||||
"adaptiveSendReason": "disabled"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "coalesces duplicate native outbound rows for one screen-share publication",
|
||||
"input": {
|
||||
"rttMs": null,
|
||||
"outbound": [
|
||||
{
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screen_share",
|
||||
"kind": "video",
|
||||
"codec": "video/H265",
|
||||
"bitrateKbps": 269.9,
|
||||
"packetsLost": 0,
|
||||
"fps": 3,
|
||||
"effectiveFps": 53.9,
|
||||
"configuredFps": 60,
|
||||
"targetFps": 60,
|
||||
"width": 2176,
|
||||
"height": 1200,
|
||||
"sourceWidth": 2176,
|
||||
"sourceHeight": 1200,
|
||||
"targetBitrateKbps": 50000,
|
||||
"framesProduced": 1904,
|
||||
"framesAccepted": 1904,
|
||||
"framesDropped": 64,
|
||||
"framesCoalesced": 64,
|
||||
"framesCaptured": 1839,
|
||||
"captureFailures": 0,
|
||||
"maxQueueAgeMs": 18,
|
||||
"maxPushLatencyMs": 18,
|
||||
"adaptiveSendTier": "full",
|
||||
"adaptiveSendReason": "adaptiveDisabled"
|
||||
},
|
||||
{
|
||||
"trackSid": "TR_screen",
|
||||
"source": "screenshare",
|
||||
"kind": "video",
|
||||
"codec": "video/H265",
|
||||
"bitrateKbps": 4614.1,
|
||||
"packetsLost": 0,
|
||||
"fps": 30
|
||||
}
|
||||
],
|
||||
"inbound": []
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 0,
|
||||
"audioRecvBitrateKbps": 0,
|
||||
"videoSendBitrateKbps": 4884,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 0,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 0,
|
||||
"rttMs": null
|
||||
},
|
||||
"localScreenShare": {
|
||||
"trackIdentifier": "TR_screen",
|
||||
"codec": "video/H265",
|
||||
"bitrateKbps": 4884,
|
||||
"framesPerSecond": 53.9,
|
||||
"configuredFramesPerSecond": 60,
|
||||
"targetFramesPerSecond": 60,
|
||||
"frameWidth": 2176,
|
||||
"frameHeight": 1200,
|
||||
"targetBitrateKbps": 50000,
|
||||
"adaptiveSendTier": "full",
|
||||
"adaptiveSendReason": "adaptiveDisabled"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "splits screen-share audio from microphone audio",
|
||||
"input": {
|
||||
"rttMs": null,
|
||||
"outbound": [
|
||||
{"trackSid": "mic", "source": "microphone", "kind": "audio", "bitrateKbps": 48, "packetsLost": 0},
|
||||
{"trackSid": "ss-audio", "source": "screen_share_audio", "kind": "audio", "bitrateKbps": 96, "packetsLost": 0}
|
||||
],
|
||||
"inbound": []
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 144,
|
||||
"audioRecvBitrateKbps": 0,
|
||||
"videoSendBitrateKbps": 0,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 0,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 0,
|
||||
"rttMs": null
|
||||
},
|
||||
"localAudio": {"trackIdentifier": "mic"},
|
||||
"localScreenShareAudio": {"trackIdentifier": "ss-audio"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rolls up inbound audio video jitter rtt and callback drops",
|
||||
"input": {
|
||||
"rttMs": 25,
|
||||
"droppedVideoFrameCallbacks": 3,
|
||||
"outbound": [],
|
||||
"inbound": [
|
||||
{
|
||||
"participantSid": "PA_1",
|
||||
"trackSid": "a",
|
||||
"kind": "audio",
|
||||
"bitrateKbps": 32,
|
||||
"packetsLost": 2,
|
||||
"packetsReceived": 98,
|
||||
"jitterMs": 8
|
||||
},
|
||||
{
|
||||
"participantSid": "PA_1",
|
||||
"trackSid": "v",
|
||||
"kind": "video",
|
||||
"bitrateKbps": 900,
|
||||
"packetsLost": 0,
|
||||
"packetsReceived": 1500
|
||||
}
|
||||
]
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 0,
|
||||
"audioRecvBitrateKbps": 32,
|
||||
"videoSendBitrateKbps": 0,
|
||||
"videoRecvBitrateKbps": 900,
|
||||
"audioPacketLossPercent": 2,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 8,
|
||||
"rttMs": 25
|
||||
},
|
||||
"remoteAudio": {"trackIdentifier": "a"},
|
||||
"remoteVideo": {"trackIdentifier": "v"},
|
||||
"remoteScreenShare": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uses worst case audio packet loss across send and receive",
|
||||
"input": {
|
||||
"rttMs": null,
|
||||
"outbound": [
|
||||
{
|
||||
"trackSid": "a",
|
||||
"source": "microphone",
|
||||
"kind": "audio",
|
||||
"bitrateKbps": 30,
|
||||
"packetsLost": 5,
|
||||
"packetsSent": 100
|
||||
}
|
||||
],
|
||||
"inbound": [
|
||||
{
|
||||
"participantSid": "PA_1",
|
||||
"trackSid": "b",
|
||||
"kind": "audio",
|
||||
"bitrateKbps": 30,
|
||||
"packetsLost": 12,
|
||||
"packetsReceived": 88
|
||||
}
|
||||
]
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 30,
|
||||
"audioRecvBitrateKbps": 30,
|
||||
"videoSendBitrateKbps": 0,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 12,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 0,
|
||||
"rttMs": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "reports inbound video loss as a windowed percentage not a raw packet count",
|
||||
"input": {
|
||||
"rttMs": 1,
|
||||
"outbound": [],
|
||||
"inbound": [
|
||||
{
|
||||
"participantSid": "PA_1",
|
||||
"trackSid": "v",
|
||||
"kind": "video",
|
||||
"bitrateKbps": 147,
|
||||
"packetsLost": 13,
|
||||
"packetsReceived": 4000
|
||||
}
|
||||
]
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioPacketLossPercent": 0,
|
||||
"videoPacketLossPercent": 0.3,
|
||||
"rttMs": 1
|
||||
},
|
||||
"remoteVideo": {"trackIdentifier": "v"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "handles empty stats as zero network and null tracks",
|
||||
"input": {
|
||||
"rttMs": null,
|
||||
"outbound": [],
|
||||
"inbound": []
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 0,
|
||||
"audioRecvBitrateKbps": 0,
|
||||
"videoSendBitrateKbps": 0,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 0,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 0,
|
||||
"rttMs": null
|
||||
},
|
||||
"localAudio": null,
|
||||
"localVideo": null,
|
||||
"remoteAudio": null,
|
||||
"remoteVideo": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "prefers first non-zero bitrate track when several candidates exist",
|
||||
"input": {
|
||||
"rttMs": null,
|
||||
"outbound": [
|
||||
{"trackSid": "silent", "source": "microphone", "kind": "audio", "bitrateKbps": 0, "packetsLost": 0},
|
||||
{"trackSid": "live", "source": "microphone", "kind": "audio", "bitrateKbps": 40, "packetsLost": 0}
|
||||
],
|
||||
"inbound": []
|
||||
},
|
||||
"expectedSummary": {
|
||||
"network": {
|
||||
"audioSendBitrateKbps": 40,
|
||||
"audioRecvBitrateKbps": 0,
|
||||
"videoSendBitrateKbps": 0,
|
||||
"videoRecvBitrateKbps": 0,
|
||||
"audioPacketLossPercent": 0,
|
||||
"videoPacketLossPercent": 0,
|
||||
"jitterMs": 0,
|
||||
"rttMs": null
|
||||
},
|
||||
"localAudio": {"trackIdentifier": "live"}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,123 @@
|
||||
[
|
||||
{
|
||||
"name": "classifies all explicit local and remote publication ids",
|
||||
"input": {
|
||||
"tracks": [
|
||||
{"direction": "send", "kind": "video", "trackIdentifier": "local-camera", "bitrateKbps": 500},
|
||||
{"direction": "send", "kind": "audio", "trackIdentifier": "local-mic", "bitrateKbps": 48},
|
||||
{"direction": "send", "kind": "video", "trackIdentifier": "local-screen", "bitrateKbps": 1200},
|
||||
{"direction": "send", "kind": "audio", "trackIdentifier": "local-screen-audio", "bitrateKbps": 96},
|
||||
{"direction": "recv", "kind": "audio", "trackIdentifier": "remote-mic", "bitrateKbps": 64},
|
||||
{"direction": "recv", "kind": "video", "trackIdentifier": "remote-camera", "bitrateKbps": 900},
|
||||
{"direction": "recv", "kind": "video", "trackIdentifier": "remote-screen", "bitrateKbps": 1800},
|
||||
{"direction": "recv", "kind": "audio", "trackIdentifier": "remote-screen-audio", "bitrateKbps": 128}
|
||||
],
|
||||
"publications": {
|
||||
"localCameraTrackId": "local-camera",
|
||||
"localMicrophoneTrackId": "local-mic",
|
||||
"localScreenShareTrackId": "local-screen",
|
||||
"localScreenShareAudioTrackId": "local-screen-audio",
|
||||
"remoteMicrophoneTrackIds": ["remote-mic"],
|
||||
"remoteScreenShareTrackIds": ["remote-screen"],
|
||||
"remoteScreenShareAudioTrackIds": ["remote-screen-audio"]
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"localVideoTrackIndex": 0,
|
||||
"localAudioTrackIndex": 1,
|
||||
"localScreenShareTrackIndex": 2,
|
||||
"localScreenShareAudioTrackIndex": 3,
|
||||
"remoteVideoTrackIndex": 5,
|
||||
"remoteAudioTrackIndex": 4,
|
||||
"remoteScreenShareTrackIndex": 6,
|
||||
"remoteScreenShareAudioTrackIndex": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "falls back to rid screen-share and non-rid camera when local ids are missing",
|
||||
"input": {
|
||||
"tracks": [
|
||||
{"direction": "send", "kind": "video", "trackIdentifier": "camera-fallback", "bitrateKbps": 700},
|
||||
{"direction": "send", "kind": "video", "rid": "h", "trackIdentifier": "screen-fallback", "bitrateKbps": 1600},
|
||||
{"direction": "send", "kind": "audio", "trackIdentifier": "local-mic", "bitrateKbps": 48}
|
||||
],
|
||||
"publications": {
|
||||
"localCameraTrackId": null,
|
||||
"localMicrophoneTrackId": null,
|
||||
"localScreenShareTrackId": null,
|
||||
"localScreenShareAudioTrackId": null,
|
||||
"remoteMicrophoneTrackIds": [],
|
||||
"remoteScreenShareTrackIds": [],
|
||||
"remoteScreenShareAudioTrackIds": []
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"localVideoTrackIndex": 0,
|
||||
"localAudioTrackIndex": 2,
|
||||
"localScreenShareTrackIndex": 1,
|
||||
"localScreenShareAudioTrackIndex": null,
|
||||
"remoteVideoTrackIndex": null,
|
||||
"remoteAudioTrackIndex": null,
|
||||
"remoteScreenShareTrackIndex": null,
|
||||
"remoteScreenShareAudioTrackIndex": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "does not classify remote screen-share audio as remote microphone",
|
||||
"input": {
|
||||
"tracks": [
|
||||
{"direction": "recv", "kind": "audio", "trackIdentifier": "remote-screen-audio", "bitrateKbps": 4},
|
||||
{"direction": "recv", "kind": "video", "trackIdentifier": "remote-screen", "bitrateKbps": 1800}
|
||||
],
|
||||
"publications": {
|
||||
"localCameraTrackId": null,
|
||||
"localMicrophoneTrackId": null,
|
||||
"localScreenShareTrackId": null,
|
||||
"localScreenShareAudioTrackId": null,
|
||||
"remoteMicrophoneTrackIds": [],
|
||||
"remoteScreenShareTrackIds": ["remote-screen"],
|
||||
"remoteScreenShareAudioTrackIds": ["remote-screen-audio"]
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"localVideoTrackIndex": null,
|
||||
"localAudioTrackIndex": null,
|
||||
"localScreenShareTrackIndex": null,
|
||||
"localScreenShareAudioTrackIndex": null,
|
||||
"remoteVideoTrackIndex": null,
|
||||
"remoteAudioTrackIndex": null,
|
||||
"remoteScreenShareTrackIndex": 1,
|
||||
"remoteScreenShareAudioTrackIndex": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "chooses active remote screen-share and camera candidates over silent rows",
|
||||
"input": {
|
||||
"tracks": [
|
||||
{"direction": "recv", "kind": "video", "trackIdentifier": "remote-camera-silent", "bitrateKbps": 0},
|
||||
{"direction": "recv", "kind": "video", "trackIdentifier": "remote-camera-live", "bitrateKbps": 900},
|
||||
{"direction": "recv", "kind": "video", "trackIdentifier": "remote-screen-silent", "bitrateKbps": 0},
|
||||
{"direction": "recv", "kind": "video", "trackIdentifier": "remote-screen-live", "bitrateKbps": 1600}
|
||||
],
|
||||
"publications": {
|
||||
"localCameraTrackId": null,
|
||||
"localMicrophoneTrackId": null,
|
||||
"localScreenShareTrackId": null,
|
||||
"localScreenShareAudioTrackId": null,
|
||||
"remoteMicrophoneTrackIds": [],
|
||||
"remoteScreenShareTrackIds": ["remote-screen-silent", "remote-screen-live"],
|
||||
"remoteScreenShareAudioTrackIds": []
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"localVideoTrackIndex": null,
|
||||
"localAudioTrackIndex": null,
|
||||
"localScreenShareTrackIndex": null,
|
||||
"localScreenShareAudioTrackIndex": null,
|
||||
"remoteVideoTrackIndex": 1,
|
||||
"remoteAudioTrackIndex": null,
|
||||
"remoteScreenShareTrackIndex": 3,
|
||||
"remoteScreenShareAudioTrackIndex": null
|
||||
}
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user