active type fix

This commit is contained in:
murdle 2025-12-07 23:50:59 +02:00
parent c8347ad5a3
commit c8b738f28d

View File

@ -16,13 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { Stream } from "@spacebar/util"; import { Stream } from "@spacebar/util";
import { import { mediaServer, Send, VoiceOPCodes, VoicePayload, WebRtcWebSocket } from "@spacebar/webrtc";
mediaServer,
Send,
VoiceOPCodes,
VoicePayload,
WebRtcWebSocket,
} from "@spacebar/webrtc";
import type { WebRtcClient } from "@spacebarchat/spacebar-webrtc-types"; import type { WebRtcClient } from "@spacebarchat/spacebar-webrtc-types";
import { validateSchema, VoiceVideoSchema } from "@spacebar/schemas"; import { validateSchema, VoiceVideoSchema } from "@spacebar/schemas";
@ -46,7 +40,7 @@ export async function onVideo(this: WebRtcWebSocket, payload: VoicePayload) {
} }
} }
const stream = d.streams?.find((element) => element.active); const stream = d.streams?.find((element) => element.active ?? true);
const clientsThatNeedUpdate = new Set<WebRtcClient<WebRtcWebSocket>>(); const clientsThatNeedUpdate = new Set<WebRtcClient<WebRtcWebSocket>>();
const wantsToProduceAudio = d.audio_ssrc !== 0; const wantsToProduceAudio = d.audio_ssrc !== 0;
@ -60,9 +54,7 @@ export async function onVideo(this: WebRtcWebSocket, payload: VoicePayload) {
try { try {
await Promise.race([ await Promise.race([
new Promise<void>((resolve, reject) => { new Promise<void>((resolve, reject) => {
this.webRtcClient?.emitter.once("connected", () => this.webRtcClient?.emitter.once("connected", () => resolve());
resolve(),
);
}), }),
new Promise<void>((resolve, reject) => { new Promise<void>((resolve, reject) => {
// Reject after 3 seconds if still not connected // Reject after 3 seconds if still not connected
@ -93,28 +85,19 @@ export async function onVideo(this: WebRtcWebSocket, payload: VoicePayload) {
if (wantsToProduceAudio) { if (wantsToProduceAudio) {
// check if we are already producing audio, if not, publish a new audio track for it // check if we are already producing audio, if not, publish a new audio track for it
if (!this.webRtcClient!.isProducingAudio()) { if (!this.webRtcClient!.isProducingAudio()) {
console.log( console.log(`[${this.user_id}] publishing new audio track ssrc:${d.audio_ssrc}`);
`[${this.user_id}] publishing new audio track ssrc:${d.audio_ssrc}`,
);
await this.webRtcClient.publishTrack("audio", { await this.webRtcClient.publishTrack("audio", {
audio_ssrc: d.audio_ssrc, audio_ssrc: d.audio_ssrc,
}); });
} }
// now check that all clients have subscribed to our audio // now check that all clients have subscribed to our audio
for (const client of mediaServer.getClientsForRtcServer<WebRtcWebSocket>( for (const client of mediaServer.getClientsForRtcServer<WebRtcWebSocket>(voiceRoomId)) {
voiceRoomId,
)) {
if (client.user_id === this.user_id) continue; if (client.user_id === this.user_id) continue;
if (!client.isSubscribedToTrack(this.user_id, "audio")) { if (!client.isSubscribedToTrack(this.user_id, "audio")) {
console.log( console.log(`[${client.user_id}] subscribing to audio track ssrcs: ${d.audio_ssrc}`);
`[${client.user_id}] subscribing to audio track ssrcs: ${d.audio_ssrc}`, await client.subscribeToTrack(this.webRtcClient.user_id, "audio");
);
await client.subscribeToTrack(
this.webRtcClient.user_id,
"audio",
);
clientsThatNeedUpdate.add(client); clientsThatNeedUpdate.add(client);
} }
@ -122,12 +105,10 @@ export async function onVideo(this: WebRtcWebSocket, payload: VoicePayload) {
} }
// check if client has signaled that it will send video // check if client has signaled that it will send video
if (wantsToProduceVideo) { if (wantsToProduceVideo) {
this.webRtcClient!.videoStream = { ...stream, type: "video" }; // client sends "screen" on go live but expects "video" on response this.webRtcClient!.videoStream = { ...stream, type: "video", active: stream.active ?? true }; // client sends "screen" on go live but expects "video" on response
// check if we are already publishing video, if not, publish a new video track for it // check if we are already publishing video, if not, publish a new video track for it
if (!this.webRtcClient!.isProducingVideo()) { if (!this.webRtcClient!.isProducingVideo()) {
console.log( console.log(`[${this.user_id}] publishing new video track ssrc:${d.video_ssrc}`);
`[${this.user_id}] publishing new video track ssrc:${d.video_ssrc}`,
);
await this.webRtcClient.publishTrack("video", { await this.webRtcClient.publishTrack("video", {
video_ssrc: d.video_ssrc, video_ssrc: d.video_ssrc,
rtx_ssrc: d.rtx_ssrc, rtx_ssrc: d.rtx_ssrc,
@ -135,19 +116,12 @@ export async function onVideo(this: WebRtcWebSocket, payload: VoicePayload) {
} }
// now check that all clients have subscribed to our video track // now check that all clients have subscribed to our video track
for (const client of mediaServer.getClientsForRtcServer<WebRtcWebSocket>( for (const client of mediaServer.getClientsForRtcServer<WebRtcWebSocket>(voiceRoomId)) {
voiceRoomId,
)) {
if (client.user_id === this.user_id) continue; if (client.user_id === this.user_id) continue;
if (!client.isSubscribedToTrack(this.user_id, "video")) { if (!client.isSubscribedToTrack(this.user_id, "video")) {
console.log( console.log(`[${client.user_id}] subscribing to video track ssrc: ${d.video_ssrc}`);
`[${client.user_id}] subscribing to video track ssrc: ${d.video_ssrc}`, await client.subscribeToTrack(this.webRtcClient.user_id, "video");
);
await client.subscribeToTrack(
this.webRtcClient.user_id,
"video",
);
clientsThatNeedUpdate.add(client); clientsThatNeedUpdate.add(client);
} }
@ -163,9 +137,7 @@ export async function onVideo(this: WebRtcWebSocket, payload: VoicePayload) {
d: { d: {
user_id: this.user_id, user_id: this.user_id,
// can never send audio ssrc as 0, it will mess up client state for some reason. send server generated ssrc as backup // can never send audio ssrc as 0, it will mess up client state for some reason. send server generated ssrc as backup
audio_ssrc: audio_ssrc: ssrcs.audio_ssrc ?? this.webRtcClient!.getIncomingStreamSSRCs().audio_ssrc,
ssrcs.audio_ssrc ??
this.webRtcClient!.getIncomingStreamSSRCs().audio_ssrc,
video_ssrc: ssrcs.video_ssrc ?? 0, video_ssrc: ssrcs.video_ssrc ?? 0,
rtx_ssrc: ssrcs.rtx_ssrc ?? 0, rtx_ssrc: ssrcs.rtx_ssrc ?? 0,
streams: d.streams?.map((x) => ({ streams: d.streams?.map((x) => ({
@ -173,6 +145,7 @@ export async function onVideo(this: WebRtcWebSocket, payload: VoicePayload) {
ssrc: ssrcs.video_ssrc ?? 0, ssrc: ssrcs.video_ssrc ?? 0,
rtx_ssrc: ssrcs.rtx_ssrc ?? 0, rtx_ssrc: ssrcs.rtx_ssrc ?? 0,
type: "video", type: "video",
active: x.active ?? true,
})), })),
} as VoiceVideoSchema, } as VoiceVideoSchema,
}); });
@ -181,14 +154,10 @@ export async function onVideo(this: WebRtcWebSocket, payload: VoicePayload) {
} }
// check if we are not subscribed to producers in this server, if not, subscribe // check if we are not subscribed to producers in this server, if not, subscribe
export async function subscribeToProducers( export async function subscribeToProducers(this: WebRtcWebSocket): Promise<void> {
this: WebRtcWebSocket,
): Promise<void> {
if (!this.webRtcClient || !this.webRtcClient.webrtcConnected) return; if (!this.webRtcClient || !this.webRtcClient.webrtcConnected) return;
const clients = mediaServer.getClientsForRtcServer<WebRtcWebSocket>( const clients = mediaServer.getClientsForRtcServer<WebRtcWebSocket>(this.webRtcClient.voiceRoomId);
this.webRtcClient.voiceRoomId,
);
await Promise.all( await Promise.all(
Array.from(clients).map(async (client) => { Array.from(clients).map(async (client) => {
@ -196,42 +165,26 @@ export async function subscribeToProducers(
if (client.user_id === this.user_id) return; // cannot subscribe to self if (client.user_id === this.user_id) return; // cannot subscribe to self
if ( if (client.isProducingAudio() && !this.webRtcClient!.isSubscribedToTrack(client.user_id, "audio")) {
client.isProducingAudio() && await this.webRtcClient!.subscribeToTrack(client.user_id, "audio");
!this.webRtcClient!.isSubscribedToTrack(client.user_id, "audio")
) {
await this.webRtcClient!.subscribeToTrack(
client.user_id,
"audio",
);
needsUpdate = true; needsUpdate = true;
} }
if ( if (client.isProducingVideo() && !this.webRtcClient!.isSubscribedToTrack(client.user_id, "video")) {
client.isProducingVideo() && await this.webRtcClient!.subscribeToTrack(client.user_id, "video");
!this.webRtcClient!.isSubscribedToTrack(client.user_id, "video")
) {
await this.webRtcClient!.subscribeToTrack(
client.user_id,
"video",
);
needsUpdate = true; needsUpdate = true;
} }
if (!needsUpdate) return; if (!needsUpdate) return;
const ssrcs = this.webRtcClient!.getOutgoingStreamSSRCsForUser( const ssrcs = this.webRtcClient!.getOutgoingStreamSSRCsForUser(client.user_id);
client.user_id,
);
await Send(this, { await Send(this, {
op: VoiceOPCodes.VIDEO, op: VoiceOPCodes.VIDEO,
d: { d: {
user_id: client.user_id, user_id: client.user_id,
// can never send audio ssrc as 0, it will mess up client state for some reason. send server generated ssrc as backup // can never send audio ssrc as 0, it will mess up client state for some reason. send server generated ssrc as backup
audio_ssrc: audio_ssrc: ssrcs.audio_ssrc ?? client.getIncomingStreamSSRCs().audio_ssrc,
ssrcs.audio_ssrc ??
client.getIncomingStreamSSRCs().audio_ssrc,
video_ssrc: ssrcs.video_ssrc ?? 0, video_ssrc: ssrcs.video_ssrc ?? 0,
rtx_ssrc: ssrcs.rtx_ssrc ?? 0, rtx_ssrc: ssrcs.rtx_ssrc ?? 0,
streams: [ streams: [