janky
Version:
Janus Interface
111 lines (97 loc) • 3.9 kB
text/typescript
import janus, { JanusJS } from "janus-gateway";
import RemoteFeeds from "../repositories/RemoteFeeds";
import { IncomingStreams } from "../types";
interface ReadyToSubscribeStreams {
feed: string;
mid: string;
}
class Subscriber {
private userID: string = '';
private rfid: string = '';
private streams: IncomingStreams[] = [];
constructor( private readonly roomID: number, private readonly handler: JanusJS.PluginHandle) {}
public async subscribeToNewFeeds(id: number, streams?: IncomingStreams[]): Promise<JanusJS.PluginHandle> {
if (!streams) {
streams = RemoteFeeds.getUserFeed(id)[0]?.streams ?? undefined;
}
const streamsToSubscribeTo = this.prepareStreamsToSubscribe(streams);
await this.sendJoinRequest(streamsToSubscribeTo);
this.saveNewFeed();
return this.handler as JanusJS.PluginHandle;
}
private shouldSkipVideo(stream: IncomingStreams): boolean {
// If the publisher is VP8/VP9 and this is an older Safari, let's avoid video
if(stream.type === "video" && janus.webRTCAdapter.browserDetails.browser === "safari" &&
(stream.codec === "vp9" || (stream.codec === "vp8" && !janus.safariVp8))) {
alert("Publisher is using " + stream.codec.toUpperCase +
", but Safari doesn't support it: disabling video stream #" + stream.mindex);
return true;
}
return false;
}
private prepareStreamsToSubscribe(streams: IncomingStreams[] | undefined): ReadyToSubscribeStreams[] {
this.streams = streams ?? [];
const streamsToSubscribeTo = [];
for (const stream of streams ?? []) {
if (this.shouldSkipVideo(stream)) {
continue;
}
streamsToSubscribeTo.push({
feed: stream.id,
mid: stream.mid
});
this.rfid = stream.id;
this.userID = stream.display;
}
return streamsToSubscribeTo;
}
private sendJoinRequest(streamsToSubscribeTo: ReadyToSubscribeStreams[]): Promise<void> {
return new Promise<void>((resolve, reject) => {
const message = {
request: "join",
room: this.roomID,
ptype: "subscriber",
streams: streamsToSubscribeTo,
use_msid: this.userID,
private_id: parseInt(this.userID)
};
this.handler?.send({
message,
success: (data) => {
if (data && data.error) {
reject(data.error);
} else {
resolve();
}
}
});
});
}
public doAnswer(jsep: JanusJS.JSEP) {
this.handler.createAnswer(
{
jsep: jsep,
// We only specify data channels here, as this way in
// case they were offered we'll enable them. Since we
// don't mention audio or video tracks, we autoaccept them
// as recvonly (since we won't capture anything ourselves)
success: (jsep) => {
console.debug("Got SDP!", jsep);
let body = { request: "start", room: this.roomID };
this.handler.send({ message: body, jsep: jsep });
},
error: (error) => {
console.error("WebRTC error:", error);
}
} as JanusJS.PluginCreateAnswerParam);
}
private saveNewFeed() {
RemoteFeeds.setFeed({
id: parseInt(this.rfid),
userID: this.userID,
handler: this.handler as JanusJS.PluginHandle,
streams: this.streams,
});
}
};
export default Subscriber;