Skip to content

Commit b3fe90e

Browse files
Add meeting session timing tracking and signaling (#3168)
1 parent 0097fd7 commit b3fe90e

53 files changed

Lines changed: 7139 additions & 86 deletions

File tree

Some content is hidden

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

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Added PPS metrics on the Encoded Transform when used.
13+
- Added meeting session lifecycle timing tracking and signaling via `MeetingSessionTimingManager`.
1314

1415
### Removed
1516

demos/browser/package-lock.json

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demos/browser/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"build:fast": "vite build --",
88
"build": "npm run deps && npm install && tsc --noEmit && npm run build:fast",
99
"start:fast": "node dev-server.js",
10-
"start:watch": "WATCH_SDK=true node dev-server.js",
10+
"start:sdk-autorefresh": "SDK_AUTOREFRESH=true node dev-server.js",
1111
"start": "npm run deps && npm install && npm run start:fast"
1212
},
1313
"devDependencies": {

demos/browser/vite.config.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33

44
import { defineConfig, type Plugin } from 'vite';
55
import { resolve } from 'path';
6-
import { rmSync } from 'fs';
76
import { watch } from 'chokidar';
87
import { viteSingleFile } from 'vite-plugin-singlefile';
98
import ejsSvgPlugin from './plugins/vite-plugin-ejs-svg';
109

1110
const app = process.env.npm_config_app || process.env.APP || 'meetingV2';
12-
const watchSdk = process.env.WATCH_SDK === 'true';
11+
const watchSdk = process.env.SDK_AUTOREFRESH === 'true';
1312

1413
/**
1514
* This is exactly what we document in the CSP guide.
@@ -89,12 +88,11 @@ function fullReloadPlugin(): Plugin {
8988
sdkWatcher.on('change', () => {
9089
if (debounce) clearTimeout(debounce);
9190
debounce = setTimeout(() => {
92-
console.log('[full-reload] SDK build changed, clearing cache and restarting...');
93-
try { rmSync(resolve(__dirname, 'node_modules/.vite'), { recursive: true, force: true }); } catch {}
94-
server.restart();
91+
console.log('[full-reload] SDK build changed, reloading browser...');
92+
server.ws.send({ type: 'full-reload' });
9593
}, 1000);
9694
});
97-
console.log('[full-reload] Watching SDK build output for changes.');
95+
console.log('[full-reload] Watching SDK build output for changes (SDK_AUTOREFRESH).');
9896
}
9997

10098
server.watcher.on('change', () => {
@@ -118,6 +116,7 @@ export default defineConfig({
118116
},
119117
optimizeDeps: {
120118
include: ['amazon-chime-sdk-js'],
119+
force: true,
121120
},
122121
define: {
123122
global: 'globalThis',

package-lock.json

Lines changed: 6 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,5 +134,8 @@
134134
"singleQuote": true,
135135
"trailingComma": "es5",
136136
"printWidth": 100
137+
},
138+
"overrides": {
139+
"fast-xml-parser": "5.3.6"
137140
}
138141
}

protocol/SignalingProtocol.proto

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ message SdkSignalFrame {
2727
PRIMARY_MEETING_JOIN_ACK = 26;
2828
PRIMARY_MEETING_LEAVE = 27;
2929
NOTIFICATION = 34;
30+
MEETING_SESSION_TIMING = 43;
3031
}
3132
required uint64 timestamp_ms = 1;
3233
required Type type = 2;
@@ -52,6 +53,7 @@ message SdkSignalFrame {
5253
optional SdkPrimaryMeetingJoinAckFrame primary_meeting_join_ack = 27;
5354
optional SdkPrimaryMeetingLeaveFrame primary_meeting_leave = 28;
5455
optional SdkNotificationFrame notification = 35;
56+
optional SdkMeetingSessionTimingFrame meeting_session_timing = 44;
5557
}
5658

5759
message SdkErrorFrame {
@@ -283,6 +285,8 @@ message SdkMetric {
283285
VIDEO_DISCARDED_PPS = 47;
284286
VIDEO_PLIS_SENT = 48;
285287
VIDEO_RECEIVED_JITTER_MS = 49;
288+
VIDEO_LOCAL_RENDER_FPS = 52;
289+
VIDEO_REMOTE_RENDER_FPS = 56;
286290
VIDEO_INPUT_HEIGHT = 60;
287291
VIDEO_ENCODE_HEIGHT = 64;
288292
VIDEO_SENT_QP_SUM = 66;
@@ -503,3 +507,60 @@ enum SdkVideoCodecCapability {
503507
VP9_PROFILE_0 = 8;
504508
AV1_MAIN_PROFILE = 11;
505509
};
510+
511+
message SdkMeetingSessionTimingFrame {
512+
repeated SdkMeetingSessionSignalingTiming signaling = 1;
513+
repeated SdkMeetingSessionRemoteAudioTiming remote_audio = 2;
514+
repeated SdkMeetingSessionLocalAudioTiming local_audio = 3;
515+
repeated SdkMeetingSessionLocalVideoTiming local_video = 4;
516+
repeated SdkMeetingSessionRemoteVideoTiming remote_videos = 5;
517+
}
518+
519+
message SdkMeetingSessionSignalingTiming {
520+
optional int64 start_ms = 1;
521+
optional int64 join_sent_ms = 2;
522+
optional int64 join_ack_received_ms = 3;
523+
optional int64 transport_connected_ms = 4;
524+
optional int64 create_offer_ms = 5;
525+
optional int64 set_local_description_ms = 6;
526+
optional int64 set_remote_description_ms = 7;
527+
optional int64 ice_gathering_start_ms = 8;
528+
optional int64 ice_gathering_complete_ms = 9;
529+
optional int64 ice_connected_ms = 10;
530+
optional int64 subscribe_sent_ms = 11;
531+
optional int64 subscribe_ack_ms = 12;
532+
optional bool timed_out = 13;
533+
}
534+
535+
message SdkMeetingSessionRemoteAudioTiming {
536+
optional int64 added_ms = 1;
537+
optional int64 first_packet_received_ms = 2;
538+
optional int64 first_frame_rendered_ms = 3;
539+
optional bool timed_out = 4;
540+
optional bool removed = 5;
541+
}
542+
543+
message SdkMeetingSessionLocalAudioTiming {
544+
optional int64 added_ms = 1;
545+
optional int64 first_frame_captured_ms = 2;
546+
optional int64 first_packet_sent_ms = 3;
547+
optional bool timed_out = 4;
548+
optional bool removed = 5;
549+
}
550+
551+
message SdkMeetingSessionLocalVideoTiming {
552+
optional int64 added_ms = 1;
553+
optional int64 first_frame_captured_ms = 2;
554+
optional int64 first_frame_sent_ms = 3;
555+
optional bool timed_out = 4;
556+
optional bool removed = 5;
557+
}
558+
559+
message SdkMeetingSessionRemoteVideoTiming {
560+
optional uint32 group_id = 1;
561+
optional int64 added_ms = 2;
562+
optional int64 first_packet_received_ms = 3;
563+
optional int64 first_frame_rendered_ms = 4;
564+
optional bool timed_out = 5;
565+
optional bool removed = 6;
566+
}

script/audit-deps

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ end
66

77
# Just so the devs can see.
88
puts 'Auditing development dependencies. You should address any findings.'
9-
system('npm audit --omit=prod')
9+
system('npm audit --include=dev')
1010

1111
puts '---'
1212

script/barrelize.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,16 @@ walk('src')
120120
importStrings.push(importLine);
121121
exportStrings.push(exportLine);
122122

123+
if (typeToImport === 'MeetingSessionTiming') {
124+
importStrings.push(`import { MeetingSessionSignalingTiming, MeetingSessionRemoteAudioTiming, MeetingSessionLocalAudioTiming, MeetingSessionLocalVideoTiming, MeetingSessionRemoteVideoTiming, MeetingSessionTimingObserver } from '${pathToImport}/MeetingSessionTiming';`);
125+
exportStrings.push('MeetingSessionSignalingTiming');
126+
exportStrings.push('MeetingSessionRemoteAudioTiming');
127+
exportStrings.push('MeetingSessionLocalAudioTiming');
128+
exportStrings.push('MeetingSessionLocalVideoTiming');
129+
exportStrings.push('MeetingSessionRemoteVideoTiming');
130+
exportStrings.push('MeetingSessionTimingObserver');
131+
}
132+
123133
// Because these two types are very intertwined.
124134
if (typeToImport === 'VideoPreferences') {
125135
importStrings.push(`import { MutableVideoPreferences } from '${pathToImport}/VideoPreferences';`);

script/generate-media-transform-worker-code.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ const workerTsconfig = 'tsconfig.mediatransformworker.json';
2020
const workerTsconfigContent = `{
2121
"extends": "./tsconfig.base.json",
2222
"compilerOptions": {
23-
"module": "ES2015",
23+
"module": "es2015",
2424
"moduleResolution": "node",
25-
"outDir": "../build",
26-
"rootDir": "../src"
25+
"outDir": "../build/mediatransformworker",
26+
"rootDir": "../src",
27+
"tsBuildInfoFile": "./tsconfig.mediatransformworker.tsbuildinfo",
28+
"incremental": true,
29+
"composite": false
2730
},
2831
"include": [
2932
"../src/encodedtransformworker/**/*.ts"
@@ -55,7 +58,7 @@ fs.unlinkSync(`${configDir}/${workerTsconfig}`);
5558

5659
// Read all transpiled worker files and bundle them inline
5760
// Order matters: dependencies must come before classes that use them
58-
const buildDir = './build/encodedtransformworker';
61+
const buildDir = './build/mediatransformworker/encodedtransformworker';
5962
const workerFiles = [
6063
'EncodedTransform.js',
6164
'RedundantAudioEncodedTransform.js',

0 commit comments

Comments
 (0)