livekit-client
Advanced tools
Comparing version 0.2.0 to 0.3.0
import 'webrtc-adapter'; | ||
import { ParticipantInfo, TrackType } from '../proto/model'; | ||
import { JoinResponse, SignalRequest, TrackPublishedResponse } from '../proto/rtc'; | ||
import { JoinResponse, SignalRequest, SignalTarget, TrackPublishedResponse } from '../proto/rtc'; | ||
export interface ConnectionInfo { | ||
@@ -17,6 +17,6 @@ host: string; | ||
sendAnswer(answer: RTCSessionDescriptionInit): void; | ||
sendIceCandidate(candidate: RTCIceCandidateInit): void; | ||
sendIceCandidate(candidate: RTCIceCandidateInit, target: SignalTarget): void; | ||
sendMuteTrack(trackSid: string, muted: boolean): void; | ||
sendAddTrack(cid: string, name: string, type: TrackType): void; | ||
sendNegotiate(): void; | ||
close(): void; | ||
readonly isConnected: boolean; | ||
@@ -26,6 +26,5 @@ onClose?: (reason: string) => void; | ||
onOffer?: (sd: RTCSessionDescriptionInit) => void; | ||
onTrickle?: (sd: RTCIceCandidateInit) => void; | ||
onTrickle?: (sd: RTCIceCandidateInit, target: SignalTarget) => void; | ||
onParticipantUpdate?: (updates: ParticipantInfo[]) => void; | ||
onLocalTrackPublished?: (res: TrackPublishedResponse) => void; | ||
onNegotiateRequested?: () => void; | ||
} | ||
@@ -37,3 +36,3 @@ export declare class RTCClientImpl { | ||
onOffer?: (sd: RTCSessionDescriptionInit) => void; | ||
onTrickle?: (sd: RTCIceCandidateInit) => void; | ||
onTrickle?: (sd: RTCIceCandidateInit, target: SignalTarget) => void; | ||
onParticipantUpdate?: (updates: ParticipantInfo[]) => void; | ||
@@ -48,6 +47,5 @@ onLocalTrackPublished?: (res: TrackPublishedResponse) => void; | ||
sendAnswer(answer: RTCSessionDescriptionInit): void; | ||
sendIceCandidate(candidate: RTCIceCandidateInit): void; | ||
sendIceCandidate(candidate: RTCIceCandidateInit, target: SignalTarget): void; | ||
sendMuteTrack(trackSid: string, muted: boolean): void; | ||
sendAddTrack(cid: string, name: string, type: TrackType): void; | ||
sendNegotiate(): void; | ||
sendRequest(req: SignalRequest): void; | ||
@@ -54,0 +52,0 @@ private handleSignalResponse; |
@@ -82,3 +82,3 @@ "use strict"; | ||
} | ||
sendIceCandidate(candidate) { | ||
sendIceCandidate(candidate, target) { | ||
loglevel_1.default.debug('sending ice candidate', candidate); | ||
@@ -88,2 +88,3 @@ this.sendRequest({ | ||
candidateInit: JSON.stringify(candidate), | ||
target: target, | ||
}, | ||
@@ -109,5 +110,2 @@ }); | ||
} | ||
sendNegotiate() { | ||
this.sendRequest({ negotiate: {} }); | ||
} | ||
sendRequest(req) { | ||
@@ -136,3 +134,3 @@ if (!this.ws) { | ||
if (this.onTrickle) { | ||
this.onTrickle(candidate); | ||
this.onTrickle(candidate, msg.trickle.target); | ||
} | ||
@@ -150,7 +148,2 @@ } | ||
} | ||
else if (msg.negotiate) { | ||
if (this.onNegotiateRequested) { | ||
this.onNegotiateRequested(); | ||
} | ||
} | ||
else { | ||
@@ -157,0 +150,0 @@ console.warn('unsupported message', msg); |
@@ -28,4 +28,2 @@ "use strict"; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const client = new RTCClient_1.RTCClientImpl(); | ||
const room = new Room_1.default(client); | ||
// set defaults | ||
@@ -39,7 +37,14 @@ options || (options = {}); | ||
loglevel_1.default.setLevel(options.logLevel); | ||
let config = { | ||
iceServers: [ | ||
{ | ||
urls: ['stun:stun.l.google.com:19302', 'stun:stun1.l.google.com:19302'], | ||
}, | ||
], | ||
}; | ||
if (options.iceServers) { | ||
room.engine.peerConn.setConfiguration({ | ||
iceServers: options.iceServers, | ||
}); | ||
config.iceServers = options.iceServers; | ||
} | ||
const client = new RTCClient_1.RTCClientImpl(); | ||
const room = new Room_1.default(client, config); | ||
// connect to room | ||
@@ -46,0 +51,0 @@ yield room.connect(info, token); |
@@ -5,7 +5,7 @@ import { TrackType, Room, ParticipantInfo, TrackInfo } from './model'; | ||
/** | ||
* participant joining initially, and during negotiations | ||
* initial join exchange, for publisher | ||
*/ | ||
offer?: SessionDescription | undefined; | ||
/** | ||
* participant responding to server-issued offers | ||
* participant answering publisher offer | ||
*/ | ||
@@ -20,6 +20,2 @@ answer?: SessionDescription | undefined; | ||
/** | ||
* when client needs to negotiate | ||
*/ | ||
negotiate?: NegotiationRequest | undefined; | ||
/** | ||
* mute a track client is subscribed to | ||
@@ -35,7 +31,7 @@ */ | ||
/** | ||
* sent when offer is answered | ||
* sent when server answers publisher | ||
*/ | ||
answer?: SessionDescription | undefined; | ||
/** | ||
* sent when server needs to negotiate, always offer | ||
* sent when server is sending subscriber an offer | ||
*/ | ||
@@ -55,6 +51,2 @@ offer?: SessionDescription | undefined; | ||
trackPublished?: TrackPublishedResponse | undefined; | ||
/** | ||
* sent to participant when they should initiate negotiation | ||
*/ | ||
negotiate?: NegotiationResponse | undefined; | ||
} | ||
@@ -71,2 +63,3 @@ export interface AddTrackRequest { | ||
candidateInit: string; | ||
target: SignalTarget; | ||
} | ||
@@ -86,2 +79,3 @@ export interface MuteTrackRequest { | ||
otherParticipants: ParticipantInfo[]; | ||
serverVersion: string; | ||
} | ||
@@ -92,7 +86,2 @@ export interface TrackPublishedResponse { | ||
} | ||
/** | ||
* empty | ||
*/ | ||
export interface NegotiationResponse { | ||
} | ||
export interface SessionDescription { | ||
@@ -109,2 +98,9 @@ /** | ||
export declare const protobufPackage = "livekit"; | ||
export declare enum SignalTarget { | ||
PUBLISHER = 0, | ||
SUBSCRIBER = 1, | ||
UNRECOGNIZED = -1 | ||
} | ||
export declare function signalTargetFromJSON(object: any): SignalTarget; | ||
export declare function signalTargetToJSON(object: SignalTarget): string; | ||
export declare const SignalRequest: { | ||
@@ -166,9 +162,2 @@ encode(message: SignalRequest, writer?: Writer): Writer; | ||
}; | ||
export declare const NegotiationResponse: { | ||
encode(_: NegotiationResponse, writer?: Writer): Writer; | ||
decode(input: Uint8Array | Reader, length?: number | undefined): NegotiationResponse; | ||
fromJSON(_: any): NegotiationResponse; | ||
fromPartial(_: DeepPartial<NegotiationResponse>): NegotiationResponse; | ||
toJSON(_: NegotiationResponse): unknown; | ||
}; | ||
export declare const SessionDescription: { | ||
@@ -175,0 +164,0 @@ encode(message: SessionDescription, writer?: Writer): Writer; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ParticipantUpdate = exports.SessionDescription = exports.NegotiationResponse = exports.TrackPublishedResponse = exports.JoinResponse = exports.NegotiationRequest = exports.MuteTrackRequest = exports.TrickleRequest = exports.AddTrackRequest = exports.SignalResponse = exports.SignalRequest = exports.protobufPackage = void 0; | ||
exports.ParticipantUpdate = exports.SessionDescription = exports.TrackPublishedResponse = exports.JoinResponse = exports.NegotiationRequest = exports.MuteTrackRequest = exports.TrickleRequest = exports.AddTrackRequest = exports.SignalResponse = exports.SignalRequest = exports.signalTargetToJSON = exports.signalTargetFromJSON = exports.SignalTarget = exports.protobufPackage = void 0; | ||
/* eslint-disable */ | ||
@@ -16,2 +16,3 @@ const model_1 = require("./model"); | ||
candidateInit: "", | ||
target: 0, | ||
}; | ||
@@ -23,7 +24,8 @@ const baseMuteTrackRequest = { | ||
const baseNegotiationRequest = {}; | ||
const baseJoinResponse = {}; | ||
const baseJoinResponse = { | ||
serverVersion: "", | ||
}; | ||
const baseTrackPublishedResponse = { | ||
cid: "", | ||
}; | ||
const baseNegotiationResponse = {}; | ||
const baseSessionDescription = { | ||
@@ -35,2 +37,34 @@ type: "", | ||
exports.protobufPackage = 'livekit'; | ||
var SignalTarget; | ||
(function (SignalTarget) { | ||
SignalTarget[SignalTarget["PUBLISHER"] = 0] = "PUBLISHER"; | ||
SignalTarget[SignalTarget["SUBSCRIBER"] = 1] = "SUBSCRIBER"; | ||
SignalTarget[SignalTarget["UNRECOGNIZED"] = -1] = "UNRECOGNIZED"; | ||
})(SignalTarget = exports.SignalTarget || (exports.SignalTarget = {})); | ||
function signalTargetFromJSON(object) { | ||
switch (object) { | ||
case 0: | ||
case "PUBLISHER": | ||
return SignalTarget.PUBLISHER; | ||
case 1: | ||
case "SUBSCRIBER": | ||
return SignalTarget.SUBSCRIBER; | ||
case -1: | ||
case "UNRECOGNIZED": | ||
default: | ||
return SignalTarget.UNRECOGNIZED; | ||
} | ||
} | ||
exports.signalTargetFromJSON = signalTargetFromJSON; | ||
function signalTargetToJSON(object) { | ||
switch (object) { | ||
case SignalTarget.PUBLISHER: | ||
return "PUBLISHER"; | ||
case SignalTarget.SUBSCRIBER: | ||
return "SUBSCRIBER"; | ||
default: | ||
return "UNKNOWN"; | ||
} | ||
} | ||
exports.signalTargetToJSON = signalTargetToJSON; | ||
exports.SignalRequest = { | ||
@@ -53,7 +87,4 @@ encode(message, writer = minimal_1.Writer.create()) { | ||
} | ||
if (message.negotiate !== undefined) { | ||
exports.NegotiationRequest.encode(message.negotiate, writer.uint32(58).fork()).ldelim(); | ||
} | ||
if (message.muteSubscribed !== undefined) { | ||
exports.MuteTrackRequest.encode(message.muteSubscribed, writer.uint32(66).fork()).ldelim(); | ||
exports.MuteTrackRequest.encode(message.muteSubscribed, writer.uint32(50).fork()).ldelim(); | ||
} | ||
@@ -84,6 +115,3 @@ return writer; | ||
break; | ||
case 7: | ||
message.negotiate = exports.NegotiationRequest.decode(reader, reader.uint32()); | ||
break; | ||
case 8: | ||
case 6: | ||
message.muteSubscribed = exports.MuteTrackRequest.decode(reader, reader.uint32()); | ||
@@ -130,8 +158,2 @@ break; | ||
} | ||
if (object.negotiate !== undefined && object.negotiate !== null) { | ||
message.negotiate = exports.NegotiationRequest.fromJSON(object.negotiate); | ||
} | ||
else { | ||
message.negotiate = undefined; | ||
} | ||
if (object.muteSubscribed !== undefined && object.muteSubscribed !== null) { | ||
@@ -177,8 +199,2 @@ message.muteSubscribed = exports.MuteTrackRequest.fromJSON(object.muteSubscribed); | ||
} | ||
if (object.negotiate !== undefined && object.negotiate !== null) { | ||
message.negotiate = exports.NegotiationRequest.fromPartial(object.negotiate); | ||
} | ||
else { | ||
message.negotiate = undefined; | ||
} | ||
if (object.muteSubscribed !== undefined && object.muteSubscribed !== null) { | ||
@@ -199,3 +215,2 @@ message.muteSubscribed = exports.MuteTrackRequest.fromPartial(object.muteSubscribed); | ||
message.mute !== undefined && (obj.mute = message.mute ? exports.MuteTrackRequest.toJSON(message.mute) : undefined); | ||
message.negotiate !== undefined && (obj.negotiate = message.negotiate ? exports.NegotiationRequest.toJSON(message.negotiate) : undefined); | ||
message.muteSubscribed !== undefined && (obj.muteSubscribed = message.muteSubscribed ? exports.MuteTrackRequest.toJSON(message.muteSubscribed) : undefined); | ||
@@ -225,5 +240,2 @@ return obj; | ||
} | ||
if (message.negotiate !== undefined) { | ||
exports.NegotiationResponse.encode(message.negotiate, writer.uint32(58).fork()).ldelim(); | ||
} | ||
return writer; | ||
@@ -256,5 +268,2 @@ }, | ||
break; | ||
case 7: | ||
message.negotiate = exports.NegotiationResponse.decode(reader, reader.uint32()); | ||
break; | ||
default: | ||
@@ -305,8 +314,2 @@ reader.skipType(tag & 7); | ||
} | ||
if (object.negotiate !== undefined && object.negotiate !== null) { | ||
message.negotiate = exports.NegotiationResponse.fromJSON(object.negotiate); | ||
} | ||
else { | ||
message.negotiate = undefined; | ||
} | ||
return message; | ||
@@ -352,8 +355,2 @@ }, | ||
} | ||
if (object.negotiate !== undefined && object.negotiate !== null) { | ||
message.negotiate = exports.NegotiationResponse.fromPartial(object.negotiate); | ||
} | ||
else { | ||
message.negotiate = undefined; | ||
} | ||
return message; | ||
@@ -369,3 +366,2 @@ }, | ||
message.trackPublished !== undefined && (obj.trackPublished = message.trackPublished ? exports.TrackPublishedResponse.toJSON(message.trackPublished) : undefined); | ||
message.negotiate !== undefined && (obj.negotiate = message.negotiate ? exports.NegotiationResponse.toJSON(message.negotiate) : undefined); | ||
return obj; | ||
@@ -459,2 +455,3 @@ }, | ||
writer.uint32(10).string(message.candidateInit); | ||
writer.uint32(16).int32(message.target); | ||
return writer; | ||
@@ -472,2 +469,5 @@ }, | ||
break; | ||
case 2: | ||
message.target = reader.int32(); | ||
break; | ||
default: | ||
@@ -488,2 +488,8 @@ reader.skipType(tag & 7); | ||
} | ||
if (object.target !== undefined && object.target !== null) { | ||
message.target = signalTargetFromJSON(object.target); | ||
} | ||
else { | ||
message.target = 0; | ||
} | ||
return message; | ||
@@ -499,2 +505,8 @@ }, | ||
} | ||
if (object.target !== undefined && object.target !== null) { | ||
message.target = object.target; | ||
} | ||
else { | ||
message.target = 0; | ||
} | ||
return message; | ||
@@ -505,2 +517,3 @@ }, | ||
message.candidateInit !== undefined && (obj.candidateInit = message.candidateInit); | ||
message.target !== undefined && (obj.target = signalTargetToJSON(message.target)); | ||
return obj; | ||
@@ -616,2 +629,3 @@ }, | ||
} | ||
writer.uint32(34).string(message.serverVersion); | ||
return writer; | ||
@@ -636,2 +650,5 @@ }, | ||
break; | ||
case 4: | ||
message.serverVersion = reader.string(); | ||
break; | ||
default: | ||
@@ -664,2 +681,8 @@ reader.skipType(tag & 7); | ||
} | ||
if (object.serverVersion !== undefined && object.serverVersion !== null) { | ||
message.serverVersion = String(object.serverVersion); | ||
} | ||
else { | ||
message.serverVersion = ""; | ||
} | ||
return message; | ||
@@ -687,2 +710,8 @@ }, | ||
} | ||
if (object.serverVersion !== undefined && object.serverVersion !== null) { | ||
message.serverVersion = object.serverVersion; | ||
} | ||
else { | ||
message.serverVersion = ""; | ||
} | ||
return message; | ||
@@ -700,2 +729,3 @@ }, | ||
} | ||
message.serverVersion !== undefined && (obj.serverVersion = message.serverVersion); | ||
return obj; | ||
@@ -771,33 +801,2 @@ }, | ||
}; | ||
exports.NegotiationResponse = { | ||
encode(_, writer = minimal_1.Writer.create()) { | ||
return writer; | ||
}, | ||
decode(input, length) { | ||
const reader = input instanceof Uint8Array ? new minimal_1.Reader(input) : input; | ||
let end = length === undefined ? reader.len : reader.pos + length; | ||
const message = Object.assign({}, baseNegotiationResponse); | ||
while (reader.pos < end) { | ||
const tag = reader.uint32(); | ||
switch (tag >>> 3) { | ||
default: | ||
reader.skipType(tag & 7); | ||
break; | ||
} | ||
} | ||
return message; | ||
}, | ||
fromJSON(_) { | ||
const message = Object.assign({}, baseNegotiationResponse); | ||
return message; | ||
}, | ||
fromPartial(_) { | ||
const message = Object.assign({}, baseNegotiationResponse); | ||
return message; | ||
}, | ||
toJSON(_) { | ||
const obj = {}; | ||
return obj; | ||
}, | ||
}; | ||
exports.SessionDescription = { | ||
@@ -804,0 +803,0 @@ encode(message, writer = minimal_1.Writer.create()) { |
@@ -9,1 +9,4 @@ export declare class LivekitError { | ||
} | ||
export declare class UnsupportedServer extends LivekitError { | ||
constructor(message?: string); | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TrackInvalidError = exports.LivekitError = void 0; | ||
exports.UnsupportedServer = exports.TrackInvalidError = exports.LivekitError = void 0; | ||
class LivekitError { | ||
@@ -13,6 +13,12 @@ constructor(code, message) { | ||
constructor(message) { | ||
super(53300, message || 'Track is invalid'); | ||
super(20, message || 'Track is invalid'); | ||
} | ||
} | ||
exports.TrackInvalidError = TrackInvalidError; | ||
class UnsupportedServer extends LivekitError { | ||
constructor(message) { | ||
super(10, message || 'Unsupported server'); | ||
} | ||
} | ||
exports.UnsupportedServer = UnsupportedServer; | ||
//# sourceMappingURL=errors.js.map |
@@ -115,7 +115,7 @@ "use strict"; | ||
// add data track | ||
track.dataChannel = this.engine.peerConn.createDataChannel(track.name, track.dataChannelInit); | ||
track.dataChannel = this.engine.publisher.pc.createDataChannel(track.name, track.dataChannelInit); | ||
} | ||
else { | ||
// store RTPSender | ||
track.sender = this.engine.peerConn.addTrack(track.mediaStreamTrack); | ||
track.sender = this.engine.publisher.pc.addTrack(track.mediaStreamTrack); | ||
} | ||
@@ -160,7 +160,6 @@ this.tracks.set(ti.sid, publication); | ||
} | ||
const senders = this.engine.peerConn.getSenders(); | ||
loglevel_1.default.debug('unpublishTrack:', `removing the track from ${senders.length} senders`, track); | ||
const senders = this.engine.publisher.pc.getSenders(); | ||
senders.forEach((sender) => { | ||
if (sender.track === mediaStreamTrack) { | ||
this.engine.peerConn.removeTrack(sender); | ||
this.engine.publisher.pc.removeTrack(sender); | ||
} | ||
@@ -167,0 +166,0 @@ }); |
@@ -22,3 +22,3 @@ /// <reference types="node" /> | ||
localParticipant: LocalParticipant; | ||
constructor(client: RTCClient); | ||
constructor(client: RTCClient, config?: RTCConfiguration); | ||
connect: (info: ConnectionInfo, token: string) => Promise<Room>; | ||
@@ -25,0 +25,0 @@ disconnect(): void; |
@@ -18,3 +18,5 @@ "use strict"; | ||
const loglevel_1 = __importDefault(require("loglevel")); | ||
const semver_1 = require("semver"); | ||
const model_1 = require("../proto/model"); | ||
const errors_1 = require("./errors"); | ||
const events_2 = require("./events"); | ||
@@ -32,3 +34,3 @@ const LocalParticipant_1 = require("./participant/LocalParticipant"); | ||
class Room extends events_1.EventEmitter { | ||
constructor(client) { | ||
constructor(client, config) { | ||
super(); | ||
@@ -43,2 +45,16 @@ this.state = RoomState.Disconnected; | ||
const joinResponse = yield this.engine.join(info, token); | ||
loglevel_1.default.debug('connected to Livekit Server', joinResponse.serverVersion); | ||
try { | ||
if (!joinResponse.serverVersion) { | ||
throw new errors_1.UnsupportedServer('unknown server version'); | ||
} | ||
const sv = new semver_1.SemVer(joinResponse.serverVersion); | ||
if (!(sv.major >= 0 && sv.minor >= 4)) { | ||
throw new errors_1.UnsupportedServer('requires server >= 0.4.x'); | ||
} | ||
} | ||
catch (err) { | ||
this.engine.close(); | ||
throw err; | ||
} | ||
this.state = RoomState.Connected; | ||
@@ -54,6 +70,15 @@ const pi = joinResponse.participant; | ||
this.sid = joinResponse.room.sid; | ||
return this; | ||
// don't return until ICE connected | ||
return new Promise((resolve, reject) => { | ||
this.engine.once(events_2.EngineEvent.Connected, () => { | ||
resolve(this); | ||
}); | ||
// timeout | ||
setTimeout(() => { | ||
reject('could not connect after timeout'); | ||
}, 5 * 1000); | ||
}); | ||
}); | ||
this.participants = new Map(); | ||
this.engine = new RTCEngine_1.RTCEngine(client); | ||
this.engine = new RTCEngine_1.RTCEngine(client, config); | ||
this.engine.on(events_2.EngineEvent.MediaTrackAdded, (mediaTrack) => { | ||
@@ -60,0 +85,0 @@ this.onTrackAdded(mediaTrack); |
@@ -6,5 +6,7 @@ /// <reference types="node" /> | ||
import { JoinResponse } from '../proto/rtc'; | ||
import { PCTransport } from './PCTransport'; | ||
import { Track } from './track/Track'; | ||
export declare class RTCEngine extends EventEmitter { | ||
peerConn: RTCPeerConnection; | ||
publisher: PCTransport; | ||
subscriber: PCTransport; | ||
client: RTCClient; | ||
@@ -18,5 +20,5 @@ privateDC?: RTCDataChannel; | ||
}; | ||
constructor(client: RTCClient); | ||
join: (info: ConnectionInfo, token: string) => Promise<JoinResponse>; | ||
createOffer: () => Promise<RTCSessionDescriptionInit>; | ||
constructor(client: RTCClient, config?: RTCConfiguration); | ||
join(info: ConnectionInfo, token: string): Promise<JoinResponse>; | ||
close(): Promise<void>; | ||
addTrack(cid: string, name: string, kind: Track.Kind): Promise<TrackInfo>; | ||
@@ -26,5 +28,3 @@ updateMuteStatus(trackSid: string, muted: boolean): void; | ||
private negotiate; | ||
private requestNegotiation; | ||
private onRTCConnected; | ||
private onICEConnected; | ||
} |
@@ -18,8 +18,10 @@ "use strict"; | ||
const loglevel_1 = __importDefault(require("loglevel")); | ||
const rtc_1 = require("../proto/rtc"); | ||
const errors_1 = require("./errors"); | ||
const events_2 = require("./events"); | ||
const PCTransport_1 = require("./PCTransport"); | ||
const Track_1 = require("./track/Track"); | ||
const placeholderDataChannel = '_private'; | ||
class RTCEngine extends events_1.EventEmitter { | ||
constructor(client) { | ||
constructor(client, config) { | ||
super(); | ||
@@ -30,18 +32,23 @@ this.rtcConnected = false; | ||
this.pendingTrackResolvers = {}; | ||
this.join = (info, token) => __awaiter(this, void 0, void 0, function* () { | ||
this.client = client; | ||
this.publisher = new PCTransport_1.PCTransport(config); | ||
this.subscriber = new PCTransport_1.PCTransport(config); | ||
this.configure(); | ||
} | ||
join(info, token) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const joinResponse = yield this.client.join(info, token); | ||
// create offer | ||
const offer = yield this.peerConn.createOffer(); | ||
yield this.peerConn.setLocalDescription(offer); | ||
const offer = yield this.publisher.pc.createOffer(); | ||
yield this.publisher.pc.setLocalDescription(offer); | ||
this.client.sendOffer(offer); | ||
return joinResponse; | ||
}); | ||
this.createOffer = () => __awaiter(this, void 0, void 0, function* () { | ||
const offer = yield this.peerConn.createOffer(); | ||
// TODO: set bitrate and other options | ||
return offer; | ||
} | ||
close() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.publisher.close(); | ||
this.subscriber.close(); | ||
this.client.close(); | ||
}); | ||
this.client = client; | ||
this.peerConn = new RTCPeerConnection(); | ||
this.configure(); | ||
} | ||
@@ -61,9 +68,11 @@ addTrack(cid, name, kind) { | ||
configure() { | ||
this.peerConn.onicecandidate = (ev) => { | ||
this.publisher.pc.onicecandidate = (ev) => { | ||
if (!ev.candidate) | ||
return; | ||
loglevel_1.default.trace('adding ICE candidate for peer', ev.candidate); | ||
// TODO: don't think we need this rtcConnected check, should be able to send | ||
// through right away | ||
if (this.rtcConnected) { | ||
// send it through | ||
this.client.sendIceCandidate(ev.candidate); | ||
this.client.sendIceCandidate(ev.candidate, rtc_1.SignalTarget.PUBLISHER); | ||
} | ||
@@ -74,27 +83,39 @@ else { | ||
}; | ||
this.peerConn.onnegotiationneeded = (ev) => { | ||
this.subscriber.pc.onicecandidate = (ev) => { | ||
if (!ev.candidate) | ||
return; | ||
this.client.sendIceCandidate(ev.candidate, rtc_1.SignalTarget.SUBSCRIBER); | ||
}; | ||
this.publisher.pc.onnegotiationneeded = (ev) => { | ||
if (!this.rtcConnected) { | ||
return; | ||
} | ||
this.requestNegotiation(); | ||
this.negotiate(); | ||
}; | ||
this.peerConn.oniceconnectionstatechange = (ev) => { | ||
if (this.peerConn.iceConnectionState === 'connected' && | ||
this.publisher.pc.oniceconnectionstatechange = (ev) => { | ||
if (this.publisher.pc.iceConnectionState === 'connected' && | ||
!this.iceConnected) { | ||
this.onICEConnected(); | ||
loglevel_1.default.trace('ICE connected'); | ||
this.iceConnected = true; | ||
this.emit(events_2.EngineEvent.Connected); | ||
} | ||
// TODO: handle other connection states | ||
else if (this.publisher.pc.iceConnectionState === 'disconnected') { | ||
loglevel_1.default.trace('ICE disconnected'); | ||
this.iceConnected = false; | ||
this.emit(events_2.EngineEvent.Disconnected); | ||
} | ||
}; | ||
this.peerConn.ontrack = (ev) => { | ||
this.subscriber.pc.ontrack = (ev) => { | ||
loglevel_1.default.debug('engine fired track added', ev.track); | ||
this.emit(events_2.EngineEvent.MediaTrackAdded, ev.track, ev.streams); | ||
}; | ||
this.peerConn.ondatachannel = (ev) => { | ||
this.subscriber.pc.ondatachannel = (ev) => { | ||
this.emit(events_2.EngineEvent.DataChannelAdded, ev.channel); | ||
}; | ||
// always have a blank data channel, to ensure there isn't an empty ice-ufrag | ||
this.privateDC = this.peerConn.createDataChannel(placeholderDataChannel); | ||
this.privateDC = this.publisher.pc.createDataChannel(placeholderDataChannel); | ||
// configure signaling client | ||
this.client.onAnswer = (sd) => __awaiter(this, void 0, void 0, function* () { | ||
loglevel_1.default.debug('received server answer', sd.type, this.peerConn.signalingState); | ||
yield this.peerConn.setRemoteDescription(sd); | ||
loglevel_1.default.debug('received server answer', sd.type, this.publisher.pc.signalingState); | ||
yield this.publisher.setRemoteDescription(sd); | ||
// consider connected | ||
@@ -105,18 +126,20 @@ if (!this.rtcConnected) | ||
// add candidate on trickle | ||
this.client.onTrickle = (candidate) => { | ||
loglevel_1.default.debug('got ICE candidate from peer', candidate); | ||
this.peerConn.addIceCandidate(candidate); | ||
this.client.onTrickle = (candidate, target) => { | ||
loglevel_1.default.trace('got ICE candidate from peer', candidate, target); | ||
if (target === rtc_1.SignalTarget.PUBLISHER) { | ||
this.publisher.addIceCandidate(candidate); | ||
} | ||
else { | ||
this.subscriber.addIceCandidate(candidate); | ||
} | ||
}; | ||
// when server creates an offer for the client | ||
this.client.onOffer = (sd) => __awaiter(this, void 0, void 0, function* () { | ||
loglevel_1.default.debug('received server offer', sd.type, this.peerConn.signalingState); | ||
yield this.peerConn.setRemoteDescription(sd); | ||
loglevel_1.default.debug('received server offer', sd.type, this.subscriber.pc.signalingState); | ||
yield this.subscriber.setRemoteDescription(sd); | ||
// answer the offer | ||
const answer = yield this.peerConn.createAnswer(); | ||
yield this.peerConn.setLocalDescription(answer); | ||
const answer = yield this.subscriber.pc.createAnswer(); | ||
yield this.subscriber.pc.setLocalDescription(answer); | ||
this.client.sendAnswer(answer); | ||
}); | ||
this.client.onNegotiateRequested = () => { | ||
this.negotiate(); | ||
}; | ||
this.client.onParticipantUpdate = (updates) => { | ||
@@ -134,5 +157,2 @@ this.emit(events_2.EngineEvent.ParticipantUpdate, updates); | ||
}; | ||
this.client.onClose = (reason) => { | ||
this.emit(events_2.EngineEvent.Disconnected, reason); | ||
}; | ||
} | ||
@@ -142,12 +162,8 @@ negotiate() { | ||
// TODO: what if signaling state changed? will need to queue and retry | ||
loglevel_1.default.debug('starting to negotiate', this.peerConn.signalingState); | ||
const offer = yield this.peerConn.createOffer(); | ||
yield this.peerConn.setLocalDescription(offer); | ||
loglevel_1.default.debug('starting to negotiate', this.publisher.pc.signalingState); | ||
const offer = yield this.publisher.pc.createOffer(); | ||
yield this.publisher.pc.setLocalDescription(offer); | ||
this.client.sendOffer(offer); | ||
}); | ||
} | ||
requestNegotiation() { | ||
loglevel_1.default.debug('requesting negotiation'); | ||
this.client.sendNegotiate(); | ||
} | ||
// signaling channel connected | ||
@@ -159,12 +175,8 @@ onRTCConnected() { | ||
this.pendingCandidates.forEach((cand) => { | ||
this.client.sendIceCandidate(cand); | ||
this.client.sendIceCandidate(cand, rtc_1.SignalTarget.PUBLISHER); | ||
}); | ||
this.pendingCandidates = []; | ||
} | ||
onICEConnected() { | ||
loglevel_1.default.debug('ICE connected'); | ||
this.iceConnected = true; | ||
} | ||
} | ||
exports.RTCEngine = RTCEngine; | ||
//# sourceMappingURL=RTCEngine.js.map |
@@ -1,2 +0,2 @@ | ||
declare const version = "0.1.1"; | ||
declare const version = "0.3.0"; | ||
export { version }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.version = void 0; | ||
const version = '0.1.1'; | ||
const version = '0.3.0'; | ||
exports.version = version; | ||
//# sourceMappingURL=version.js.map |
{ | ||
"name": "livekit-client", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "JavaScript/TypeScript client SDK for LiveKit", | ||
@@ -17,2 +17,3 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@types/semver": "^7.3.4", | ||
"@types/ws": "^7.4.0", | ||
@@ -22,2 +23,3 @@ "events": "^3.2.0", | ||
"protobufjs": "^6.10.2", | ||
"semver": "^6.3.0", | ||
"webrtc-adapter": "^7.7.0" | ||
@@ -24,0 +26,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
286350
116
4462
7
+ Added@types/semver@^7.3.4
+ Addedsemver@^6.3.0
+ Added@types/semver@7.5.8(transitive)
+ Addedsemver@6.3.1(transitive)