feat: basic livekit setup
This commit is contained in:
@ -4,6 +4,8 @@
|
||||
"dependencies": {
|
||||
"@cashu/cashu-ts": "^1.0.0-rc.3",
|
||||
"@here/maps-api-for-javascript": "^1.50.0",
|
||||
"@livekit/components-react": "^2.5.4",
|
||||
"@livekit/protocol": "^1.22.0",
|
||||
"@noble/curves": "^1.4.0",
|
||||
"@noble/hashes": "^1.4.0",
|
||||
"@scure/base": "^1.1.6",
|
||||
@ -29,6 +31,7 @@
|
||||
"highlight.js": "^11.8.0",
|
||||
"latlon-geohash": "^2.0.0",
|
||||
"light-bolt11-decoder": "^2.1.0",
|
||||
"livekit-client": "^2.5.2",
|
||||
"lottie-react": "^2.4.0",
|
||||
"marked": "^9.1.0",
|
||||
"marked-footnote": "^1.0.0",
|
||||
|
@ -1,18 +1,35 @@
|
||||
import { NostrEvent, NostrLink } from "@snort/system";
|
||||
import { useState } from "react";
|
||||
import { NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||
import { lazy, Suspense, useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import Icon from "@/Components/Icons/Icon";
|
||||
import { findTag } from "@/Utils";
|
||||
import { extractStreamInfo } from "@/Utils/stream";
|
||||
|
||||
import NoteAppHandler from "../Event/Note/NoteAppHandler";
|
||||
import ProfileImage from "../User/ProfileImage";
|
||||
const LiveKitRoom = lazy(() => import("./livekit"));
|
||||
|
||||
export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
||||
const title = findTag(ev, "title");
|
||||
const status = findTag(ev, "status");
|
||||
const starts = Number(findTag(ev, "starts"));
|
||||
const host = ev.tags.find(a => a[0] === "p" && a[3] === "host")?.[1] ?? ev.pubkey;
|
||||
|
||||
export function LiveEvent({ ev }: { ev: TaggedNostrEvent }) {
|
||||
const service = ev.tags.find(a => a[0] === "streaming")?.at(1);
|
||||
function inner() {
|
||||
if (service?.endsWith(".m3u8")) {
|
||||
return <LiveStreamEvent ev={ev} />
|
||||
} else if (service?.startsWith("wss+livekit://")) {
|
||||
return <Suspense>
|
||||
<LiveKitRoom ev={ev} canJoin={true} />
|
||||
</Suspense>
|
||||
}
|
||||
return <NoteAppHandler ev={ev} />
|
||||
}
|
||||
|
||||
return inner();
|
||||
}
|
||||
|
||||
function LiveStreamEvent({ ev }: { ev: TaggedNostrEvent }) {
|
||||
const { title, status, starts, host } = extractStreamInfo(ev);
|
||||
const [play, setPlay] = useState(false);
|
||||
|
||||
function statusLine() {
|
||||
@ -38,7 +55,7 @@ export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
||||
return (
|
||||
<b className="uppercase">
|
||||
{new Intl.DateTimeFormat(undefined, { dateStyle: "full", timeStyle: "short" }).format(
|
||||
new Date(starts * 1000),
|
||||
new Date(Number(starts) * 1000),
|
||||
)}
|
||||
</b>
|
||||
);
|
||||
@ -73,8 +90,6 @@ export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
||||
const link = `https://zap.stream/embed/${NostrLink.fromEvent(ev).encode()}`;
|
||||
return (
|
||||
<iframe
|
||||
// eslint-disable-next-line react/no-unknown-property
|
||||
credentialless=""
|
||||
src={link}
|
||||
width="100%"
|
||||
style={{
|
||||
@ -86,7 +101,7 @@ export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
||||
return (
|
||||
<div className="sm:flex g12 br p24 bg-primary items-center">
|
||||
<div>
|
||||
<ProfileImage pubkey={host} showUsername={false} size={56} />
|
||||
<ProfileImage pubkey={host!} showUsername={false} size={56} />
|
||||
</div>
|
||||
<div className="flex flex-col g8 grow">
|
||||
<div className="font-semibold text-3xl">{title}</div>
|
||||
|
117
packages/app/src/Components/LiveStream/livekit.tsx
Normal file
117
packages/app/src/Components/LiveStream/livekit.tsx
Normal file
@ -0,0 +1,117 @@
|
||||
import { LiveKitRoom as LiveKitRoomContext, RoomAudioRenderer, useParticipants } from "@livekit/components-react";
|
||||
import { dedupe, unixNow } from "@snort/shared";
|
||||
import { EventKind, NostrLink, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
||||
import { useRequestBuilder, useUserProfile } from "@snort/system-react";
|
||||
import { LocalParticipant, RemoteParticipant } from "livekit-client";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||
import { extractStreamInfo } from "@/Utils/stream";
|
||||
|
||||
import AsyncButton from "../Button/AsyncButton";
|
||||
import { ProxyImg } from "../ProxyImg";
|
||||
import Avatar from "../User/Avatar";
|
||||
import { AvatarGroup } from "../User/AvatarGroup";
|
||||
import DisplayName from "../User/DisplayName";
|
||||
|
||||
export default function LiveKitRoom({ ev, canJoin }: { ev: TaggedNostrEvent, canJoin?: boolean }) {
|
||||
const { stream, service, id } = extractStreamInfo(ev);
|
||||
const { publisher } = useEventPublisher();
|
||||
const [join, setJoin] = useState(false);
|
||||
const [token, setToken] = useState<string>();
|
||||
|
||||
async function getToken() {
|
||||
if (!service || !publisher)
|
||||
return;
|
||||
const url = `${service}/api/v1/nests/${id}`;
|
||||
const auth = await publisher.generic(eb => {
|
||||
eb.kind(EventKind.HttpAuthentication);
|
||||
eb.tag(["url", url]);
|
||||
eb.tag(["u", url])
|
||||
eb.tag(["method", "GET"]);
|
||||
return eb;
|
||||
});
|
||||
const rsp = await fetch(url, {
|
||||
headers: {
|
||||
authorization: `Nostr ${window.btoa(JSON.stringify(auth))}`,
|
||||
}
|
||||
});
|
||||
|
||||
const text = await rsp.text();
|
||||
if (rsp.ok) {
|
||||
return JSON.parse(text) as { token: string };
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (join && !token) {
|
||||
getToken().then(t => setToken(t?.token)).catch(console.error);
|
||||
}
|
||||
}, [join]);
|
||||
|
||||
if (!join) {
|
||||
return <div className="p flex flex-col gap-2">
|
||||
<RoomHeader ev={ev} />
|
||||
{(canJoin ?? false) && <AsyncButton onClick={() => setJoin(true)}>
|
||||
<FormattedMessage defaultMessage="Join Room" />
|
||||
</AsyncButton>}
|
||||
</div>
|
||||
}
|
||||
return <LiveKitRoomContext token={token} serverUrl={stream?.replace("wss+livekit://", "wss://")} connect={true}>
|
||||
<RoomAudioRenderer volume={1} />
|
||||
<ParticipantList ev={ev} />
|
||||
</LiveKitRoomContext>
|
||||
}
|
||||
|
||||
function RoomHeader({ ev }: { ev: TaggedNostrEvent }) {
|
||||
const { image, title } = extractStreamInfo(ev);
|
||||
return <div className="relative rounded-xl h-[140px] w-full overflow-hidden">
|
||||
{image ? <ProxyImg src={image} className="w-full" /> :
|
||||
<div className="absolute bg-gray-dark w-full h-full" />}
|
||||
<div className="absolute left-4 top-4 w-full flex justify-between pr-4">
|
||||
<div className="text-2xl">
|
||||
{title}
|
||||
</div>
|
||||
<div>
|
||||
<NostrParticipants ev={ev} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
function ParticipantList({ ev }: { ev: TaggedNostrEvent }) {
|
||||
const participants = useParticipants()
|
||||
return <div className="p">
|
||||
<RoomHeader ev={ev} />
|
||||
<h3>
|
||||
<FormattedMessage defaultMessage="Participants" />
|
||||
</h3>
|
||||
<div className="grid grid-cols-4">
|
||||
{participants.map(a => <LiveKitUser p={a} key={a.identity} />)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
function NostrParticipants({ ev }: { ev: TaggedNostrEvent }) {
|
||||
const link = NostrLink.fromEvent(ev);
|
||||
const sub = useMemo(() => {
|
||||
const sub = new RequestBuilder(`livekit-participants:${link.tagKey}`);
|
||||
sub.withFilter().replyToLink([link]).kinds([10_312 as EventKind]).since(unixNow() - 600);
|
||||
return sub;
|
||||
}, [link.tagKey]);
|
||||
|
||||
const presense = useRequestBuilder(sub);
|
||||
return <AvatarGroup ids={dedupe(presense.map(a => a.pubkey))} size={32} />
|
||||
}
|
||||
|
||||
function LiveKitUser({ p }: { p: RemoteParticipant | LocalParticipant }) {
|
||||
const pubkey = p.identity.startsWith("guest-") ? "anon" : p.identity
|
||||
const profile = useUserProfile(pubkey);
|
||||
return <div className="flex flex-col gap-2 items-center text-center">
|
||||
<Avatar pubkey={pubkey} className={p.isSpeaking ? "outline" : ""} user={profile} size={48} />
|
||||
<DisplayName pubkey={pubkey} user={pubkey === "anon" ? { name: "Anon" } : profile} />
|
||||
</div>
|
||||
}
|
@ -3,10 +3,10 @@ import React from "react";
|
||||
|
||||
import ProfileImage from "@/Components/User/ProfileImage";
|
||||
|
||||
export function AvatarGroup({ ids, onClick }: { ids: HexKey[]; onClick?: () => void }) {
|
||||
export function AvatarGroup({ ids, onClick, size }: { ids: HexKey[]; onClick?: () => void, size?: number }) {
|
||||
return ids.map((a, index) => (
|
||||
<div className={`inline-block ${index > 0 ? "-ml-4" : ""}`} key={a} style={{ zIndex: ids.length - index }}>
|
||||
<ProfileImage link="" onClick={onClick} showFollowDistance={false} pubkey={a} size={24} showUsername={false} />
|
||||
<ProfileImage link="" onClick={onClick} showFollowDistance={false} pubkey={a} size={size ?? 24} showUsername={false} />
|
||||
</div>
|
||||
));
|
||||
}
|
||||
|
72
packages/app/src/Utils/stream.ts
Normal file
72
packages/app/src/Utils/stream.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { TaggedNostrEvent } from "@snort/system";
|
||||
|
||||
export function getHost(ev?: TaggedNostrEvent) {
|
||||
return ev?.tags.find(a => a[0] === "p" && a[3] === "host")?.[1] ?? ev?.pubkey ?? "";
|
||||
}
|
||||
|
||||
export type StreamState = "live" | "ended" | "planned";
|
||||
|
||||
export interface StreamInfo {
|
||||
id?: string;
|
||||
title?: string;
|
||||
summary?: string;
|
||||
image?: string;
|
||||
thumbnail?: string;
|
||||
status?: StreamState;
|
||||
stream?: string;
|
||||
recording?: string;
|
||||
contentWarning?: string;
|
||||
tags: Array<string>;
|
||||
goal?: string;
|
||||
participants?: string;
|
||||
starts?: string;
|
||||
ends?: string;
|
||||
service?: string;
|
||||
host?: string;
|
||||
gameId?: string;
|
||||
}
|
||||
|
||||
const gameTagFormat = /^[a-z-]+:[a-z0-9-]+$/i;
|
||||
export function extractStreamInfo(ev?: TaggedNostrEvent) {
|
||||
const ret = {
|
||||
host: getHost(ev),
|
||||
} as StreamInfo;
|
||||
const matchTag = (tag: Array<string>, k: string, into: (v: string) => void) => {
|
||||
if (tag[0] === k) {
|
||||
into(tag[1]);
|
||||
}
|
||||
};
|
||||
|
||||
for (const t of ev?.tags ?? []) {
|
||||
matchTag(t, "d", v => (ret.id = v));
|
||||
matchTag(t, "title", v => (ret.title = v));
|
||||
matchTag(t, "summary", v => (ret.summary = v));
|
||||
matchTag(t, "image", v => (ret.image = v));
|
||||
matchTag(t, "thumbnail", v => (ret.thumbnail = v));
|
||||
matchTag(t, "status", v => (ret.status = v as StreamState));
|
||||
if (t[0] === "streaming") {
|
||||
matchTag(t, "streaming", v => (ret.stream = v));
|
||||
}
|
||||
matchTag(t, "recording", v => (ret.recording = v));
|
||||
matchTag(t, "url", v => (ret.recording = v));
|
||||
matchTag(t, "content-warning", v => (ret.contentWarning = v));
|
||||
matchTag(t, "current_participants", v => (ret.participants = v));
|
||||
matchTag(t, "goal", v => (ret.goal = v));
|
||||
matchTag(t, "starts", v => (ret.starts = v));
|
||||
matchTag(t, "ends", v => (ret.ends = v));
|
||||
matchTag(t, "service", v => (ret.service = v));
|
||||
}
|
||||
const { regularTags } = sortStreamTags(ev?.tags ?? []);
|
||||
ret.tags = regularTags;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
export function sortStreamTags(tags: Array<string | Array<string>>) {
|
||||
const plainTags = tags.filter(a => (Array.isArray(a) ? a[0] === "t" : true)).map(a => (Array.isArray(a) ? a[1] : a));
|
||||
|
||||
const regularTags = plainTags.filter(a => !a.match(gameTagFormat)) ?? [];
|
||||
const prefixedTags = plainTags.filter(a => !regularTags.includes(a));
|
||||
return { regularTags, prefixedTags };
|
||||
}
|
207
yarn.lock
207
yarn.lock
@ -2640,6 +2640,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@bufbuild/protobuf@npm:^1.10.0, @bufbuild/protobuf@npm:^1.7.2":
|
||||
version: 1.10.0
|
||||
resolution: "@bufbuild/protobuf@npm:1.10.0"
|
||||
checksum: 10/1f120f72bbb40dd3d0f8c73f1474b001cfb9be09c38b7b0292e35fec98c5184a3db380a6feff7626fb3fff108c8a8aa7fc8cfea14904dc0a1174a01c8e637cc6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cashu/cashu-ts@npm:^1.0.0-rc.3":
|
||||
version: 1.0.0-rc.3
|
||||
resolution: "@cashu/cashu-ts@npm:1.0.0-rc.3"
|
||||
@ -3447,6 +3454,32 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/core@npm:^1.6.0":
|
||||
version: 1.6.8
|
||||
resolution: "@floating-ui/core@npm:1.6.8"
|
||||
dependencies:
|
||||
"@floating-ui/utils": "npm:^0.2.8"
|
||||
checksum: 10/87d52989c3d2cc80373bc153b7a40814db3206ce7d0b2a2bdfb63e2ff39ffb8b999b1b0ccf28e548000ebf863bf16e2bed45eab4c4d287a5dbe974ef22368d82
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/dom@npm:1.6.11":
|
||||
version: 1.6.11
|
||||
resolution: "@floating-ui/dom@npm:1.6.11"
|
||||
dependencies:
|
||||
"@floating-ui/core": "npm:^1.6.0"
|
||||
"@floating-ui/utils": "npm:^0.2.8"
|
||||
checksum: 10/8579392ad10151474869e7640af169b0d7fc2df48d4da27b6dcb1a57202329147ed986b2972787d4b8cd550c87897271b2d9c4633c2ec7d0b3ad37ce1da636f1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/utils@npm:^0.2.8":
|
||||
version: 0.2.8
|
||||
resolution: "@floating-ui/utils@npm:0.2.8"
|
||||
checksum: 10/3e3ea3b2de06badc4baebdf358b3dbd77ccd9474a257a6ef237277895943db2acbae756477ec64de65a2a1436d94aea3107129a1feeef6370675bf2b161c1abc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@formatjs/cli@npm:^6.1.3":
|
||||
version: 6.2.4
|
||||
resolution: "@formatjs/cli@npm:6.2.4"
|
||||
@ -4035,6 +4068,56 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@livekit/components-core@npm:0.11.5":
|
||||
version: 0.11.5
|
||||
resolution: "@livekit/components-core@npm:0.11.5"
|
||||
dependencies:
|
||||
"@floating-ui/dom": "npm:1.6.11"
|
||||
loglevel: "npm:1.9.1"
|
||||
rxjs: "npm:7.8.1"
|
||||
peerDependencies:
|
||||
"@livekit/protocol": ^1.20.1
|
||||
livekit-client: ^2.4.0
|
||||
tslib: ^2.6.2
|
||||
checksum: 10/e3ac4f501fb2a733a2e66d0dedf690c1ef9d868ec28896508b4600034dbe7a07b012562ec4e78f94a31884fc0bd5ca1205aa63b24abf84bb87a464c2304ea127
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@livekit/components-react@npm:^2.5.4":
|
||||
version: 2.5.4
|
||||
resolution: "@livekit/components-react@npm:2.5.4"
|
||||
dependencies:
|
||||
"@livekit/components-core": "npm:0.11.5"
|
||||
clsx: "npm:2.1.1"
|
||||
usehooks-ts: "npm:3.1.0"
|
||||
peerDependencies:
|
||||
"@livekit/protocol": ^1.20.1
|
||||
livekit-client: ^2.4.0
|
||||
react: ">=18"
|
||||
react-dom: ">=18"
|
||||
tslib: ^2.6.2
|
||||
checksum: 10/0e76bc4d39fdc363ce5a28c09ee1ad146f35d5c5032dd14eb5255805106f7b895f87c1658691e52c9d52b29061b4e065d8503e8e7a656d70d0876e6140953f2a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@livekit/protocol@npm:1.20.1":
|
||||
version: 1.20.1
|
||||
resolution: "@livekit/protocol@npm:1.20.1"
|
||||
dependencies:
|
||||
"@bufbuild/protobuf": "npm:^1.7.2"
|
||||
checksum: 10/bbc24985bb12d39eed487e8a9daca088e768b084b0860171cc72b29cd92c2ca91fce7ef899fcd8b49522ba79a8db480bdd6343c6e5ddaa8f6df9345fc4e1c515
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@livekit/protocol@npm:^1.22.0":
|
||||
version: 1.22.0
|
||||
resolution: "@livekit/protocol@npm:1.22.0"
|
||||
dependencies:
|
||||
"@bufbuild/protobuf": "npm:^1.10.0"
|
||||
checksum: 10/2ce29e2371a58921bdb3318a9f33ef09a6ca589b5abe03dc7e68f52450ca3f127191c8eec85c271b62dedeca4623ba799ccb7f52c3c2076137cfdc459588da72
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1":
|
||||
version: 5.1.1-v1
|
||||
resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1"
|
||||
@ -4639,6 +4722,8 @@ __metadata:
|
||||
"@cashu/cashu-ts": "npm:^1.0.0-rc.3"
|
||||
"@formatjs/cli": "npm:^6.1.3"
|
||||
"@here/maps-api-for-javascript": "npm:^1.50.0"
|
||||
"@livekit/components-react": "npm:^2.5.4"
|
||||
"@livekit/protocol": "npm:^1.22.0"
|
||||
"@noble/curves": "npm:^1.4.0"
|
||||
"@noble/hashes": "npm:^1.4.0"
|
||||
"@scure/base": "npm:^1.1.6"
|
||||
@ -4691,6 +4776,7 @@ __metadata:
|
||||
highlight.js: "npm:^11.8.0"
|
||||
latlon-geohash: "npm:^2.0.0"
|
||||
light-bolt11-decoder: "npm:^2.1.0"
|
||||
livekit-client: "npm:^2.5.2"
|
||||
lottie-react: "npm:^2.4.0"
|
||||
marked: "npm:^9.1.0"
|
||||
marked-footnote: "npm:^1.0.0"
|
||||
@ -4752,7 +4838,7 @@ __metadata:
|
||||
resolution: "@snort/system-react@workspace:packages/system-react"
|
||||
dependencies:
|
||||
"@snort/shared": "npm:^1.0.17"
|
||||
"@snort/system": "npm:^1.5.0"
|
||||
"@snort/system": "npm:^1.5.1"
|
||||
"@types/react": "npm:^18.2.14"
|
||||
react: "npm:^18.2.0"
|
||||
typescript: "npm:^5.2.2"
|
||||
@ -4787,7 +4873,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@snort/system@npm:^1.0.21, @snort/system@npm:^1.2.11, @snort/system@npm:^1.5.0, @snort/system@workspace:*, @snort/system@workspace:packages/system":
|
||||
"@snort/system@npm:^1.0.21, @snort/system@npm:^1.2.11, @snort/system@npm:^1.5.1, @snort/system@workspace:*, @snort/system@workspace:packages/system":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@snort/system@workspace:packages/system"
|
||||
dependencies:
|
||||
@ -4829,7 +4915,7 @@ __metadata:
|
||||
"@lightninglabs/lnc-web": "npm:^0.3.1-alpha"
|
||||
"@scure/base": "npm:^1.1.6"
|
||||
"@snort/shared": "npm:^1.0.17"
|
||||
"@snort/system": "npm:^1.5.0"
|
||||
"@snort/system": "npm:^1.5.1"
|
||||
"@types/debug": "npm:^4.1.12"
|
||||
"@webbtc/webln-types": "npm:^3.0.0"
|
||||
debug: "npm:^4.3.4"
|
||||
@ -7143,6 +7229,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"clsx@npm:2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "clsx@npm:2.1.1"
|
||||
checksum: 10/cdfb57fa6c7649bbff98d9028c2f0de2f91c86f551179541cf784b1cfdc1562dcb951955f46d54d930a3879931a980e32a46b598acaea274728dbe068deca919
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"co@npm:^4.6.0":
|
||||
version: 4.6.0
|
||||
resolution: "co@npm:4.6.0"
|
||||
@ -8927,6 +9020,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"events@npm:^3.3.0":
|
||||
version: 3.3.0
|
||||
resolution: "events@npm:3.3.0"
|
||||
checksum: 10/a3d47e285e28d324d7180f1e493961a2bbb4cad6412090e4dec114f4db1f5b560c7696ee8e758f55e23913ede856e3689cd3aa9ae13c56b5d8314cd3b3ddd1be
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"execa@npm:^5.0.0":
|
||||
version: 5.1.1
|
||||
resolution: "execa@npm:5.1.1"
|
||||
@ -11087,6 +11187,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"livekit-client@npm:^2.5.2":
|
||||
version: 2.5.2
|
||||
resolution: "livekit-client@npm:2.5.2"
|
||||
dependencies:
|
||||
"@livekit/protocol": "npm:1.20.1"
|
||||
events: "npm:^3.3.0"
|
||||
loglevel: "npm:^1.8.0"
|
||||
sdp-transform: "npm:^2.14.1"
|
||||
ts-debounce: "npm:^4.0.0"
|
||||
tslib: "npm:2.7.0"
|
||||
typed-emitter: "npm:^2.1.0"
|
||||
webrtc-adapter: "npm:^9.0.0"
|
||||
checksum: 10/d1be5b6969c7b8261eb74199ce1bee8a0204d0b38bc445563e9a11423bb002ed376a236fc9276378f7f5d4c8ec792222caa2963956dc506e1b4c090512898ab5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"local-pkg@npm:^0.4.3":
|
||||
version: 0.4.3
|
||||
resolution: "local-pkg@npm:0.4.3"
|
||||
@ -11161,6 +11277,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loglevel@npm:1.9.1":
|
||||
version: 1.9.1
|
||||
resolution: "loglevel@npm:1.9.1"
|
||||
checksum: 10/863cbbcddf850a937482c604e2d11586574a5110b746bb49c7cc04739e01f6035f6db841d25377106dd330bca7142d74995f15a97c5f3ea0af86d9472d4a99f4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loglevel@npm:^1.8.0":
|
||||
version: 1.9.2
|
||||
resolution: "loglevel@npm:1.9.2"
|
||||
checksum: 10/6153d8db308323f7ee20130bc40309e7a976c30a10379d8666b596d9c6441965c3e074c8d7ee3347fe5cfc059c0375b6f3e8a10b93d5b813cc5547f5aa412a29
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lokijs@npm:^1.5.12":
|
||||
version: 1.5.12
|
||||
resolution: "lokijs@npm:1.5.12"
|
||||
@ -13517,6 +13647,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rxjs@npm:*, rxjs@npm:7.8.1":
|
||||
version: 7.8.1
|
||||
resolution: "rxjs@npm:7.8.1"
|
||||
dependencies:
|
||||
tslib: "npm:^2.1.0"
|
||||
checksum: 10/b10cac1a5258f885e9dd1b70d23c34daeb21b61222ee735d2ec40a8685bdca40429000703a44f0e638c27a684ac139e1c37e835d2a0dc16f6fc061a138ae3abb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"safe-array-concat@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "safe-array-concat@npm:1.0.1"
|
||||
@ -13595,6 +13734,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sdp-transform@npm:^2.14.1":
|
||||
version: 2.14.2
|
||||
resolution: "sdp-transform@npm:2.14.2"
|
||||
bin:
|
||||
sdp-verify: checker.js
|
||||
checksum: 10/a6fd2eb5914dcbb80eecf887b5ff15620fbeefa41e750e69d54c5b80fdd37026e969d716f486c567a35d8ab95f33e765d27b0531b741cea2e80593a5cba8a49d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sdp@npm:^3.2.0":
|
||||
version: 3.2.0
|
||||
resolution: "sdp@npm:3.2.0"
|
||||
checksum: 10/3ea337c24f91f7429c79b97f1a16c19a5abb3b6672ce7c05cc931314af1318cdf3a7a88e66ea1ee71e05bf41bf3a20d5940b1c93f3099e820cec60068ddbd9b4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"semver@npm:^6.3.0, semver@npm:^6.3.1":
|
||||
version: 6.3.1
|
||||
resolution: "semver@npm:6.3.1"
|
||||
@ -14506,6 +14661,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-debounce@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "ts-debounce@npm:4.0.0"
|
||||
checksum: 10/346a5f753fd2d855befe351c29782ee998c0ecd309f7650082c438ef5833cc4e2c70d8eea5d8a277d5b42fa997a6e9ba9eab5b88edd8d1e8d292367dcd09ef8b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-interface-checker@npm:^0.1.9":
|
||||
version: 0.1.13
|
||||
resolution: "ts-interface-checker@npm:0.1.13"
|
||||
@ -14610,6 +14772,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tslib@npm:2.7.0, tslib@npm:^2.1.0":
|
||||
version: 2.7.0
|
||||
resolution: "tslib@npm:2.7.0"
|
||||
checksum: 10/9a5b47ddac65874fa011c20ff76db69f97cf90c78cff5934799ab8894a5342db2d17b4e7613a087046bc1d133d21547ddff87ac558abeec31ffa929c88b7fce6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tslib@npm:^1.8.1":
|
||||
version: 1.14.1
|
||||
resolution: "tslib@npm:1.14.1"
|
||||
@ -14778,6 +14947,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typed-emitter@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "typed-emitter@npm:2.1.0"
|
||||
dependencies:
|
||||
rxjs: "npm:*"
|
||||
dependenciesMeta:
|
||||
rxjs:
|
||||
optional: true
|
||||
checksum: 10/95821a9e05784b972cc9d152891fd12a56cb4b1a7c57e768c02bea6a8984da7aff8f19404a7b69eea11fae2a3b6c0c510a4c510f575f50162c759ae9059f2520
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typedarray-to-buffer@npm:^3.1.5":
|
||||
version: 3.1.5
|
||||
resolution: "typedarray-to-buffer@npm:3.1.5"
|
||||
@ -15050,6 +15231,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"usehooks-ts@npm:3.1.0":
|
||||
version: 3.1.0
|
||||
resolution: "usehooks-ts@npm:3.1.0"
|
||||
dependencies:
|
||||
lodash.debounce: "npm:^4.0.8"
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17 || ^18
|
||||
checksum: 10/6aef8affd3c053a3040b7421816dab85eb21601c5203496a705bafc32eb973fb519a2b0ddda527962e361d248f3a1c49df130620efe871c8f89e897451ed1cc7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"utf-8-validate@npm:^5.0.2":
|
||||
version: 5.0.10
|
||||
resolution: "utf-8-validate@npm:5.0.10"
|
||||
@ -15394,6 +15586,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webrtc-adapter@npm:^9.0.0":
|
||||
version: 9.0.1
|
||||
resolution: "webrtc-adapter@npm:9.0.1"
|
||||
dependencies:
|
||||
sdp: "npm:^3.2.0"
|
||||
checksum: 10/5e73ddb6fb807e28fc4bb727bdee2717a697bcf24cfbe1e401c5a3c57d61627fa000b6185470ec3c9fcc1dca42093b67776742c7fde7002fbc14da272a020cbf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"websocket-polyfill@npm:^0.0.3":
|
||||
version: 0.0.3
|
||||
resolution: "websocket-polyfill@npm:0.0.3"
|
||||
|
Reference in New Issue
Block a user