UNPKG

@koush/ring-client-api

Version:

Unofficial API for Ring doorbells, cameras, security alarm system and smart lighting

110 lines (95 loc) 2.76 kB
import { MediaStreamTrack, RTCIceCandidate, RTCPeerConnection, RtcpPacket, RTCRtpCodecParameters, RtpPacket, } from '@koush/werift' import { Subject } from 'rxjs' import { logError, logInfo } from './util' const debug = false export class PeerConnection { pc onAudioRtp = new Subject<RtpPacket>() onAudioRtcp = new Subject<RtcpPacket>() onVideoRtp = new Subject<RtpPacket>() onVideoRtcp = new Subject<RtcpPacket>() returnAudioTrack = new MediaStreamTrack({ kind: 'audio' }) constructor() { const pc = (this.pc = new RTCPeerConnection({ codecs: { audio: [ new RTCRtpCodecParameters({ mimeType: 'audio/opus', clockRate: 48000, channels: 2, }), ], video: [ new RTCRtpCodecParameters({ mimeType: 'video/H264', clockRate: 90000, rtcpFeedback: [ { type: 'transport-cc' }, { type: 'ccm', parameter: 'fir' }, { type: 'nack' }, { type: 'nack', parameter: 'pli' }, { type: 'goog-remb' }, ], parameters: 'level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f', }), ], }, })), audioTransceiver = pc.addTransceiver('audio', { direction: 'sendrecv', }), videoTransceiver = pc.addTransceiver('video', { direction: 'recvonly', }) audioTransceiver.onTrack.subscribe((track) => { track.onReceiveRtp.subscribe((rtp) => { this.onAudioRtp.next(rtp) }) track.onReceiveRtcp.subscribe((rtcp) => { this.onAudioRtcp.next(rtcp) }) if (debug) { track.onReceiveRtp.once(() => { logInfo('received first audio packet') }) } }) videoTransceiver.onTrack.subscribe((track) => { track.onReceiveRtp.subscribe((rtp) => { this.onVideoRtp.next(rtp) }) track.onReceiveRtcp.subscribe((rtcp) => { this.onVideoRtcp.next(rtcp) }) track.onReceiveRtp.once(() => { if (debug) { logInfo('received first video packet') } setInterval( () => videoTransceiver.receiver.sendRtcpPLI(track.ssrc!), 2000 ) }) }) } async createAnswer(offer: { type: 'offer'; sdp: string }) { await this.pc.setRemoteDescription(offer) const answer = await this.pc.createAnswer() await this.pc.setLocalDescription(answer) return answer } addIceCandidate(candidate: RTCIceCandidate) { return this.pc.addIceCandidate(candidate) } close() { this.pc.close().catch(logError) } }