Add end-to-end audio observability

This reports via OpenTelemetry when particular participants are speaking, as an easy way to observe the delivery of audio in calls.
This commit is contained in:
Robin Townsend
2023-03-22 14:23:26 -04:00
parent 48493a96e1
commit 313ebe258e
4 changed files with 76 additions and 29 deletions

View File

@@ -18,6 +18,8 @@ import { useState, useEffect } from "react";
import { CallFeed, CallFeedEvent } from "matrix-js-sdk/src/webrtc/callFeed";
import { SDPStreamMetadataPurpose } from "matrix-js-sdk/src/webrtc/callEventTypes";
import { OTelGroupCallMembership } from "../otel/OTelGroupCallMembership";
interface CallFeedState {
callFeed: CallFeed | undefined;
isLocal: boolean;
@@ -46,40 +48,46 @@ function getCallFeedState(callFeed: CallFeed | undefined): CallFeedState {
};
}
export function useCallFeed(callFeed: CallFeed | undefined): CallFeedState {
export function useCallFeed(
callFeed: CallFeed | undefined,
otelGroupCallMembership?: OTelGroupCallMembership
): CallFeedState {
const [state, setState] = useState<CallFeedState>(() =>
getCallFeedState(callFeed)
);
useEffect(() => {
function onSpeaking(speaking: boolean) {
setState((prevState) => ({ ...prevState, speaking }));
}
function onMuteStateChanged(audioMuted: boolean, videoMuted: boolean) {
setState((prevState) => ({ ...prevState, audioMuted, videoMuted }));
}
function onLocalVolumeChanged(localVolume: number) {
setState((prevState) => ({ ...prevState, localVolume }));
}
function onUpdateCallFeed() {
setState(getCallFeedState(callFeed));
}
onUpdateCallFeed();
if (callFeed) {
const onSpeaking = (speaking: boolean) => {
otelGroupCallMembership?.onSpeaking(
callFeed.getMember()!,
callFeed.deviceId!,
speaking
);
setState((prevState) => ({ ...prevState, speaking }));
};
const onMuteStateChanged = (audioMuted: boolean, videoMuted: boolean) => {
setState((prevState) => ({ ...prevState, audioMuted, videoMuted }));
};
const onLocalVolumeChanged = (localVolume: number) => {
setState((prevState) => ({ ...prevState, localVolume }));
};
callFeed.on(CallFeedEvent.Speaking, onSpeaking);
callFeed.on(CallFeedEvent.MuteStateChanged, onMuteStateChanged);
callFeed.on(CallFeedEvent.LocalVolumeChanged, onLocalVolumeChanged);
callFeed.on(CallFeedEvent.NewStream, onUpdateCallFeed);
callFeed.on(CallFeedEvent.Disposed, onUpdateCallFeed);
}
onUpdateCallFeed();
return () => {
if (callFeed) {
return () => {
callFeed.removeListener(CallFeedEvent.Speaking, onSpeaking);
callFeed.removeListener(
CallFeedEvent.MuteStateChanged,
@@ -90,9 +98,9 @@ export function useCallFeed(callFeed: CallFeed | undefined): CallFeedState {
onLocalVolumeChanged
);
callFeed.removeListener(CallFeedEvent.NewStream, onUpdateCallFeed);
}
};
}, [callFeed]);
};
}
}, [callFeed, otelGroupCallMembership]);
return state;
}