mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-16 23:45:50 +00:00
A transport may soon carry a LiveKit SFU `url` instead of, or as well as, a `livekit_service_url`, so a service URL alone no longer identifies it. Pass the whole transport to the tiles' debug stats and print it as JSON in log lines instead of picking out the service URL. Element Call's media view models carry the member's raw transport from the SDK's TransportMetadata to the tiles.
132 lines
4.0 KiB
TypeScript
132 lines
4.0 KiB
TypeScript
/*
|
|
Copyright 2023, 2024 New Vector Ltd.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
import { useState, type FC } from "react";
|
|
import { Button, Text } from "@vector-im/compound-web";
|
|
import {
|
|
MicOnSolidIcon,
|
|
VideoCallSolidIcon,
|
|
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
|
import classNames from "classnames";
|
|
|
|
import { Modal } from "./Modal";
|
|
import styles from "./RTCConnectionStats.module.css";
|
|
import mediaViewStyles from "../src/tile/MediaView.module.css";
|
|
import { type Transport } from "matrix-js-sdk/lib/matrixrtc";
|
|
|
|
interface Props {
|
|
audio?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats;
|
|
video?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats;
|
|
transport?: Transport;
|
|
rtcBackendIdentity?: string;
|
|
}
|
|
|
|
// This is only used in developer mode for debugging purposes, so we don't need full localization
|
|
export const RTCConnectionStats: FC<Props> = ({
|
|
audio,
|
|
video,
|
|
transport,
|
|
rtcBackendIdentity,
|
|
}) => {
|
|
const [showModal, setShowModal] = useState(false);
|
|
const [modalContents, setModalContents] = useState<
|
|
"video" | "audio" | "none"
|
|
>("none");
|
|
|
|
const showFullModal = (contents: "video" | "audio"): void => {
|
|
setShowModal(true);
|
|
setModalContents(contents);
|
|
};
|
|
|
|
const onDismissModal = (): void => {
|
|
setShowModal(false);
|
|
setModalContents("none");
|
|
};
|
|
return (
|
|
<div className={classNames(mediaViewStyles.nameTag, styles.statsPill)}>
|
|
<Modal
|
|
title="RTC Connection Stats"
|
|
open={showModal}
|
|
onDismiss={onDismissModal}
|
|
>
|
|
<div className={styles.modal}>
|
|
<pre>
|
|
{modalContents !== "none" &&
|
|
JSON.stringify(
|
|
modalContents === "video" ? video : audio,
|
|
null,
|
|
2,
|
|
)}
|
|
</pre>
|
|
</div>
|
|
</Modal>
|
|
<Text as="span" size="xs" title="rtcBackendIdentity">
|
|
rtcBackendIdentity:{rtcBackendIdentity}
|
|
</Text>
|
|
{transport && (
|
|
<div>
|
|
<Text as="span" size="xs" title="transport">
|
|
{JSON.stringify(transport)}
|
|
</Text>
|
|
</div>
|
|
)}
|
|
{audio && (
|
|
<div>
|
|
<Button
|
|
onClick={() => showFullModal("audio")}
|
|
size="md"
|
|
kind="tertiary"
|
|
Icon={MicOnSolidIcon}
|
|
>
|
|
{"jitter" in audio && typeof audio.jitter === "number" && (
|
|
<Text as="span" size="xs" title="jitter">
|
|
{(audio.jitter * 1000).toFixed(0)}ms
|
|
</Text>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
)}
|
|
{video && (
|
|
<div>
|
|
<Button
|
|
onClick={() => showFullModal("video")}
|
|
size="md"
|
|
kind="tertiary"
|
|
Icon={VideoCallSolidIcon}
|
|
>
|
|
{!!video?.framesPerSecond && (
|
|
<Text as="span" size="xs" title="frame rate">
|
|
{video.framesPerSecond.toFixed(0)}fps
|
|
</Text>
|
|
)}
|
|
{"jitter" in video && typeof video.jitter === "number" && (
|
|
<Text as="span" size="xs" title="jitter">
|
|
{(video.jitter * 1000).toFixed(0)}ms
|
|
</Text>
|
|
)}
|
|
{"frameHeight" in video &&
|
|
typeof video.frameHeight === "number" &&
|
|
"frameWidth" in video &&
|
|
typeof video.frameWidth === "number" && (
|
|
<Text as="span" size="xs" title="frame size">
|
|
{video.frameWidth}x{video.frameHeight}
|
|
</Text>
|
|
)}
|
|
{"qualityLimitationReason" in video &&
|
|
typeof video.qualityLimitationReason === "string" &&
|
|
video.qualityLimitationReason !== "none" && (
|
|
<Text as="span" size="xs" title="quality limitation reason">
|
|
{video.qualityLimitationReason}
|
|
</Text>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|