UNPKG

janky

Version:

Janus Interface

209 lines (190 loc) 7.37 kB
import Janus, { JanusJS } from "janus-gateway"; import LocalRTC from "../repositories/LocalRTC"; import PublisherEventsHandler from "../services/PublisherEventsHandler"; import Publisher from "../services/Publisher"; import Videoroom from "./Videoroom"; import SubVideoroom from "./SubVideoroom"; import { RoomExistsResponse, WhatToPublish } from "../types"; import RemoteFeeds from "../repositories/RemoteFeeds"; import eventEmitter from "../repositories/eventEmitter"; import { LOCAL_EVENTS } from "../events"; import { toHaveStyle } from "@testing-library/jest-dom/matchers"; class PubVideoroom extends Videoroom{ protected readonly type = 'publisher'; protected handler: JanusJS.PluginHandle | undefined; private publisher: Publisher | undefined; constructor ( public readonly roomID: number, protected readonly userID: string, protected readonly janusSession: Janus, private readonly publishType: WhatToPublish ) { super(); } public unpublish() { return this.publisher?.unpublish(); } public switchByType(publishType: WhatToPublish) { this.publisher?.switchByType(publishType); } public switchByDevice( audioDeviceId: string | undefined, videoDeviceId: string | undefined ) { return this.publisher?.switchByDevice(audioDeviceId, videoDeviceId); } public muteAudio() { this.handler?.muteAudio(); } public unmuteAudio() { this.handler?.unmuteAudio(); } public muteVideo() { this.handler?.muteVideo(); } public unmuteVideo() { this.handler?.unmuteVideo(); } public async initiate(): Promise<JanusJS.PluginHandle> { await this.attachVideoroom(); if( !(await this.checkRoomExists()) ){ await this.createRoom(); } await this.joinRoom(); LocalRTC.setHandler(this.handler as JanusJS.PluginHandle); //to be removed return this.handler as JanusJS.PluginHandle; }; protected attachVideoroom(): Promise<JanusJS.PluginHandle> { return new Promise<JanusJS.PluginHandle>((resolves: (value: JanusJS.PluginHandle) => void) => { this.janusSession.attach({ plugin: 'janus.plugin.videoroom', opaqueId: this.userID.toString(), success: async (handle: JanusJS.PluginHandle): Promise<JanusJS.PluginCallbacks> => { this.handler = handle; eventEmitter.emit(LOCAL_EVENTS.HANDLER, handle); await this.perpareRTC(); resolves(handle); return {}; }, onmessage: async (msg: JanusJS.Message, jsep: JanusJS.JSEP) => { await this.handleMessages(msg, jsep); }, onlocaltrack(track, on) { //I don't know if we should use them at all! eventEmitter.emit(LOCAL_EVENTS.LOCAL_TRACK, track, on); }, iceState: function(state) { console.log("ICE state changed to " + state); }, mediaState: function(medium, on, mid) { console.log("Janus " + (on ? "started" : "stopped") + " receiving our " + medium + " (mid=" + mid + ")"); }, webrtcState: function(on) { console.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now"); }, slowLink: function(uplink, lost, mid) { console.warn("Janus reports problems " + (uplink ? "sending" : "receiving") + " packets on mid " + mid + " (" + lost + " lost packets)"); }, } as JanusJS.PluginOptions); }); }; private checkRoomExists(): Promise<boolean> { return new Promise<boolean>((resolves: (value: boolean)=> void ) => { const message = { 'request': 'exists', 'room': this.roomID }; this.handler?.send({ message, success: ({exists}: RoomExistsResponse) => { resolves(exists); } }); }) } private createRoom(): Promise<void> { return new Promise<void>((resolves: ()=> void, rejects: (reason: string) => void) => { const message = { "request": "create", "room": this.roomID, "permanent": false, // "fir_freq": 10, "description": this.roomID.toString(), "is_private": false, 'publishers': 3, 'audiolevel_event': true, 'notify_joining': true, 'audio_active_packets': 100 }; this.handler?.send({ message, success: (res) => { if(res.error_code && res.error) { rejects(res.error); return; } resolves(); } }); }); } private joinRoom(): Promise<void> { return new Promise<void>((resolve: () => void) => { const message = { "request": "join", "room": this.roomID, "ptype": this.type, "display": this.userID, }; this.handler?.send({ message, success: () => { resolve()}, }); }); } protected async perpareRTC(): Promise<void> { const handler = this.handler as JanusJS.PluginHandle; this.publisher = new Publisher('publisher_front', handler, this.publishType); } protected async handleMessages(msg: JanusJS.Message, jsep: JanusJS.JSEP) : Promise<void> { new PublisherEventsHandler({ msg, jsep, handleRemoteSDP: () => (this.handler as JanusJS.PluginHandle).handleRemoteJsep({jsep}), sendOffer: () => (this.publisher as Publisher).doOffering(), handlePublishers: (list: any) => this.handlePublishers(list), }); } private async handlePublishers(list: any): Promise<void> { console.debug("Got a list of available publishers/feeds:", list); for(let p of list) { let rid = p.id; let streams = p.streams; let display = p.display; for(let i in streams) { let stream = streams[i]; stream["id"] = rid; stream["display"] = display; } await this.handleNewRemoteFeed(rid, display, streams); } }; private async handleNewRemoteFeed(rid: number, pubID: string, streams: any): Promise<void> { const subvideoroom = new SubVideoroom( this.roomID, pubID, this.janusSession, rid, streams ); const subHandle = await subvideoroom.initiate(); RemoteFeeds.setFeed({ id: rid, userID: pubID, handler: subHandle, streams: streams }); } }; export default PubVideoroom;