diff --git a/app.js b/app.js index 33f95b5..51421d2 100644 --- a/app.js +++ b/app.js @@ -1,3 +1,9 @@ +/** + * integrating mediasoup server with a node.js application + */ + +/* Please follow mediasoup installation requirements */ +/* https://mediasoup.org/documentation/v3/mediasoup/installation/ */ import express from 'express' const app = express() @@ -6,9 +12,15 @@ import fs from 'fs' import path from 'path' const __dirname = path.resolve() -// import { Server } from 'socket.io' import Server from 'socket.io' -import mediasoup from 'mediasoup' +import mediasoup, { getSupportedRtpCapabilities } from 'mediasoup' + +let worker +let router = {} +let producerTransport +let consumerTransport +let producer +let consumer app.get('/', (req, res) => { res.send('Hello from mediasoup app!') @@ -27,9 +39,9 @@ httpsServer.listen(3000, () => { console.log('listening on port: ' + 3000) }) -// const io = new Server(httpsServer) const io = new Server(httpsServer) +// socket.io namespace (could represent a room?) const peers = io.of('/mediasoup') /** @@ -40,12 +52,6 @@ const peers = io.of('/mediasoup') * |-> Consumer Transport(s) * |-> Consumer **/ - let worker - let routers = {} - let producerTransport - let consumerTransport - let producer - let consumer const createWorker = async () => { worker = await mediasoup.createWorker({ @@ -88,145 +94,135 @@ const mediaCodecs = [ ] peers.on('connection', async socket => { - - console.log('[connection]'); - + console.log(socket.id) socket.emit('connection-success', { - socketId: socket.id + socketId: socket.id, + existsProducer: producer ? true : false, }) - + socket.on('disconnect', () => { // do some cleanup - console.log('[disconnect]') + console.log('peer disconnected') }) - - socket.on('create-router', async (data) => { - const routerId = data.assetId; + + socket.on('createRoom', async ({ callId }, callback) => { + if (router[callId] === undefined) { + // worker.createRouter(options) + // options = { mediaCodecs, appData } + // mediaCodecs -> defined above + // appData -> custom application data - we are not supplying any + // none of the two are required + router[callId] = await worker.createRouter({ mediaCodecs }) + console.log(`Router ID: ${router[callId].id}`) + } - console.log('[create-router]', routerId) + getRtpCapabilities(callId, callback) + }) - routers[routerId] = await worker.createRouter({ mediaCodecs }) - // console.log('🔴 Create routers', routers); + const getRtpCapabilities = (callId, callback) => { + const rtpCapabilities = router[callId].rtpCapabilities - // for (const key in routers) { - // if (Object.hasOwnProperty.call(routers, key)) { - // const element = routers[key]; - // console.log('🔴', key, element); - // } - // } - - // Client emits a request for RTP Capabilities - // This event responds to the request - socket.on('getRtpCapabilities', (callback) => { - console.log('[getRtpCapabilities]') - - const rtpCapabilities = routers[routerId].rtpCapabilities - - // call callback from the client and send back the rtpCapabilities - callback({ rtpCapabilities }) + callback({ rtpCapabilities }) + } + + // Client emits a request to create server side Transport + // We need to differentiate between the producer and consumer transports + socket.on('createWebRtcTransport', async ({ sender, callId }, callback) => { + console.log(`Is this a sender request? ${sender} | callId ${callId}`) + // The client indicates if it is a producer or a consumer + // if sender is true, indicates a producer else a consumer + if (sender) + producerTransport = await createWebRtcTransportLayer(callId, callback) + else + consumerTransport = await createWebRtcTransportLayer(callId, callback) + }) + + // see client's socket.emit('transport-connect', ...) + socket.on('transport-connect', async ({ dtlsParameters }) => { + console.log('DTLS PARAMS... ', { dtlsParameters }) + await producerTransport.connect({ dtlsParameters }) + }) + + // see client's socket.emit('transport-produce', ...) + socket.on('transport-produce', async ({ kind, rtpParameters, appData }, callback) => { + // call produce based on the prameters from the client + producer = await producerTransport.produce({ + kind, + rtpParameters, }) - - // Client emits a request to create server side Transport - // We need to differentiate between the producer and consumer transports - socket.on('createWebRtcTransport', async ({ sender }, callback) => { - console.log(`Is this a sender request? ${sender}`) - // The client indicates if it is a producer or a consumer - // if sender is true, indicates a producer else a consumer - if (sender) - producerTransport = await createWebRtcTransport(routerId, callback) - else - consumerTransport = await createWebRtcTransport(routerId, callback) + + console.log('Producer ID: ', producer.id, producer.kind) + + producer.on('transportclose', () => { + console.log('transport for this producer closed ') + producer.close() }) - - // see client's socket.emit('transport-connect', ...) - socket.on('transport-connect', async ({ dtlsParameters }) => { - console.log('DTLS PARAMS... ', { dtlsParameters }) - await producerTransport.connect({ dtlsParameters }) - }) - - // see client's socket.emit('transport-produce', ...) - socket.on('transport-produce', async ({ kind, rtpParameters, appData }, callback) => { - // call produce based on the prameters from the client - producer = await producerTransport.produce({ - kind, - rtpParameters, - }) - - console.log('Producer ID:', producer.id, producer.kind) - - producer.on('transportclose', () => { - console.log('transport for this producer closed ') - producer.close() - }) - - // Send back to the client the Producer's id - callback({ - id: producer.id - }) + + // Send back to the client the Producer's id + callback({ + id: producer.id }) - // see client's socket.emit('transport-recv-connect', ...) - socket.on('transport-recv-connect', async ({ dtlsParameters }) => { - console.log(`DTLS PARAMS: ${dtlsParameters}`) - await consumerTransport.connect({ dtlsParameters }) - }) - - socket.on('consume', async ({ rtpCapabilities }, callback) => { - try { - console.log('[consume] Producer ID:', producer.id, producer.kind) - // check if the routers can consume the specified producer - if (routers[routerId].canConsume({ + }) + + // see client's socket.emit('transport-recv-connect', ...) + socket.on('transport-recv-connect', async ({ dtlsParameters }) => { + console.log(`DTLS PARAMS: ${dtlsParameters}`) + await consumerTransport.connect({ dtlsParameters }) + }) + + socket.on('consume', async ({ rtpCapabilities, callId }, callback) => { + try { + // check if the router can consume the specified producer + if (router[callId].canConsume({ + producerId: producer.id, + rtpCapabilities + })) { + // transport can now consume and return a consumer + consumer = await consumerTransport.consume({ producerId: producer.id, - rtpCapabilities - })) { - // transport can now consume and return a consumer - consumer = await consumerTransport.consume({ - producerId: producer.id, - rtpCapabilities, - paused: true, - }) - - consumer.on('transportclose', () => { - console.log('transport close from consumer') - }) - - consumer.on('producerclose', () => { - console.log('producer of consumer closed') - }) - - // from the consumer extract the following params - // to send back to the Client - const params = { - id: consumer.id, - producerId: producer.id, - kind: consumer.kind, - rtpParameters: consumer.rtpParameters, - } - // send the parameters to the client - callback({ params }) - } else { - console.log("Can't consume!!!", routers[routerId].canConsume()); - } - } catch (error) { - console.log(error.message) - callback({ - params: { - error: error - } + rtpCapabilities, + paused: true, }) - } - }) - - socket.on('consumer-resume', async () => { - console.log('consumer resume') - await consumer.resume() - }) + consumer.on('transportclose', () => { + console.log('transport close from consumer') + }) + + consumer.on('producerclose', () => { + console.log('producer of consumer closed') + }) + + // from the consumer extract the following params + // to send back to the Client + const params = { + id: consumer.id, + producerId: producer.id, + kind: consumer.kind, + rtpParameters: consumer.rtpParameters, + } + + // send the parameters to the client + callback({ params }) + } + } catch (error) { + console.log(error.message) + callback({ + params: { + error: error + } + }) + } + }) + + socket.on('consumer-resume', async () => { + console.log('consumer resume') + await consumer.resume() }) }) - -const createWebRtcTransport = async (routerId, callback) => { +const createWebRtcTransportLayer = async (callId, callback) => { try { + console.log('createWebRtcTransportLayer | callId', callId); // https://mediasoup.org/documentation/v3/mediasoup/api/#WebRtcTransportOptions const webRtcTransport_options = { listenIps: [ @@ -239,9 +235,9 @@ const createWebRtcTransport = async (routerId, callback) => { enableTcp: true, preferUdp: true, } - - // https://mediasoup.org/documentation/v3/mediasoup/api/#routers-createWebRtcTransport - let transport = await routers[routerId].createWebRtcTransport(webRtcTransport_options) + console.log('🔴 router[callId]', JSON.stringify(router)); + // https://mediasoup.org/documentation/v3/mediasoup/api/#router-createWebRtcTransport + let transport = await router[callId].createWebRtcTransport(webRtcTransport_options) console.log(`transport id: ${transport.id}`) transport.on('dtlsstatechange', dtlsState => { @@ -268,7 +264,7 @@ const createWebRtcTransport = async (routerId, callback) => { return transport } catch (error) { - console.log(error) + console.log('11111', error) callback({ params: { error: error diff --git a/public/bundle.js b/public/bundle.js index 204b726..498634a 100644 --- a/public/bundle.js +++ b/public/bundle.js @@ -2405,7 +2405,7 @@ function numberIsNaN (obj) { } }).call(this)}).call(this,require("buffer").Buffer) -},{"base64-js":6,"buffer":10,"ieee754":38}],11:[function(require,module,exports){ +},{"base64-js":6,"buffer":10,"ieee754":37}],11:[function(require,module,exports){ /** * Slice reference. */ @@ -2792,7 +2792,7 @@ function localstorage() { } }).call(this)}).call(this,require('_process')) -},{"./debug":15,"_process":79}],15:[function(require,module,exports){ +},{"./debug":15,"_process":78}],15:[function(require,module,exports){ /** * This is the common logic for both the Node.js and web browser @@ -2996,7 +2996,7 @@ function coerce(val) { return val; } -},{"ms":76}],16:[function(require,module,exports){ +},{"ms":75}],16:[function(require,module,exports){ module.exports = require('./socket'); @@ -3008,7 +3008,7 @@ module.exports = require('./socket'); */ module.exports.parser = require('engine.io-parser'); -},{"./socket":17,"engine.io-parser":28}],17:[function(require,module,exports){ +},{"./socket":17,"engine.io-parser":27}],17:[function(require,module,exports){ (function (global){(function (){ /** * Module dependencies. @@ -3755,7 +3755,7 @@ Socket.prototype.filterUpgrades = function (upgrades) { }; }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./transport":18,"./transports/index":19,"component-emitter":12,"debug":25,"engine.io-parser":28,"indexof":39,"parseqs":77,"parseuri":78}],18:[function(require,module,exports){ +},{"./transport":18,"./transports/index":19,"component-emitter":12,"debug":25,"engine.io-parser":27,"indexof":38,"parseqs":76,"parseuri":77}],18:[function(require,module,exports){ /** * Module dependencies. */ @@ -3914,7 +3914,7 @@ Transport.prototype.onClose = function () { this.emit('close'); }; -},{"component-emitter":12,"engine.io-parser":28}],19:[function(require,module,exports){ +},{"component-emitter":12,"engine.io-parser":27}],19:[function(require,module,exports){ (function (global){(function (){ /** * Module dependencies @@ -4869,7 +4869,7 @@ Polling.prototype.uri = function () { return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query; }; -},{"../transport":18,"component-inherit":13,"debug":25,"engine.io-parser":28,"parseqs":77,"xmlhttprequest-ssl":24,"yeast":95}],23:[function(require,module,exports){ +},{"../transport":18,"component-inherit":13,"debug":25,"engine.io-parser":27,"parseqs":76,"xmlhttprequest-ssl":24,"yeast":94}],23:[function(require,module,exports){ (function (global){(function (){ /** * Module dependencies. @@ -5159,7 +5159,7 @@ WS.prototype.check = function () { }; }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../transport":18,"component-inherit":13,"debug":25,"engine.io-parser":28,"parseqs":77,"ws":9,"yeast":95}],24:[function(require,module,exports){ +},{"../transport":18,"component-inherit":13,"debug":25,"engine.io-parser":27,"parseqs":76,"ws":9,"yeast":94}],24:[function(require,module,exports){ (function (global){(function (){ // browser shim for xmlhttprequest module @@ -5200,111 +5200,41 @@ module.exports = function (opts) { }; }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"has-cors":37}],25:[function(require,module,exports){ +},{"has-cors":36}],25:[function(require,module,exports){ (function (process){(function (){ -/* eslint-env browser */ - /** * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. */ +exports = module.exports = require('./debug'); +exports.log = log; exports.formatArgs = formatArgs; exports.save = save; exports.load = load; exports.useColors = useColors; -exports.storage = localstorage(); -exports.destroy = (() => { - let warned = false; - - return () => { - if (!warned) { - warned = true; - console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); - } - }; -})(); +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); /** * Colors. */ exports.colors = [ - '#0000CC', - '#0000FF', - '#0033CC', - '#0033FF', - '#0066CC', - '#0066FF', - '#0099CC', - '#0099FF', - '#00CC00', - '#00CC33', - '#00CC66', - '#00CC99', - '#00CCCC', - '#00CCFF', - '#3300CC', - '#3300FF', - '#3333CC', - '#3333FF', - '#3366CC', - '#3366FF', - '#3399CC', - '#3399FF', - '#33CC00', - '#33CC33', - '#33CC66', - '#33CC99', - '#33CCCC', - '#33CCFF', - '#6600CC', - '#6600FF', - '#6633CC', - '#6633FF', - '#66CC00', - '#66CC33', - '#9900CC', - '#9900FF', - '#9933CC', - '#9933FF', - '#99CC00', - '#99CC33', - '#CC0000', - '#CC0033', - '#CC0066', - '#CC0099', - '#CC00CC', - '#CC00FF', - '#CC3300', - '#CC3333', - '#CC3366', - '#CC3399', - '#CC33CC', - '#CC33FF', - '#CC6600', - '#CC6633', - '#CC9900', - '#CC9933', - '#CCCC00', - '#CCCC33', - '#FF0000', - '#FF0033', - '#FF0066', - '#FF0099', - '#FF00CC', - '#FF00FF', - '#FF3300', - '#FF3333', - '#FF3366', - '#FF3399', - '#FF33CC', - '#FF33FF', - '#FF6600', - '#FF6633', - '#FF9900', - '#FF9933', - '#FFCC00', - '#FFCC33' + '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', + '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', + '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', + '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', + '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', + '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', + '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', + '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', + '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', + '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', + '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' ]; /** @@ -5315,32 +5245,44 @@ exports.colors = [ * TODO: add a `localStorage` variable to explicitly enable/disable colors */ -// eslint-disable-next-line complexity function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { - return true; - } + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; + } - // Internet Explorer and Edge do not support colors. - if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { - return false; - } + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } - // Is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // Is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // Is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // Double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); } +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; + } +}; + + /** * Colorize log arguments if enabled. * @@ -5348,49 +5290,52 @@ function useColors() { */ function formatArgs(args) { - args[0] = (this.useColors ? '%c' : '') + - this.namespace + - (this.useColors ? ' %c' : ' ') + - args[0] + - (this.useColors ? '%c ' : ' ') + - '+' + module.exports.humanize(this.diff); + var useColors = this.useColors; - if (!this.useColors) { - return; - } + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); - const c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit'); + if (!useColors) return; - // The final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - let index = 0; - let lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, match => { - if (match === '%%') { - return; - } - index++; - if (match === '%c') { - // We only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit') - args.splice(lastC, 0, c); + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); } /** - * Invokes `console.debug()` when available. - * No-op when `console.debug` is not a "function". - * If `console.debug` is not available, falls back - * to `console.log`. + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". * * @api public */ -exports.log = console.debug || console.log || (() => {}); + +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); +} /** * Save `namespaces`. @@ -5398,17 +5343,15 @@ exports.log = console.debug || console.log || (() => {}); * @param {String} namespaces * @api private */ + function save(namespaces) { - try { - if (namespaces) { - exports.storage.setItem('debug', namespaces); - } else { - exports.storage.removeItem('debug'); - } - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} } /** @@ -5417,23 +5360,27 @@ function save(namespaces) { * @return {String} returns the previously persisted debug modes * @api private */ + function load() { - let r; - try { - r = exports.storage.getItem('debug'); - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } + var r; + try { + r = exports.storage.debug; + } catch(e) {} - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } - return r; + return r; } +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + /** * Localstorage attempts to return the localstorage. * @@ -5446,474 +5393,240 @@ function load() { */ function localstorage() { - try { - // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context - // The Browser also has localStorage in the global context. - return localStorage; - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } + try { + return window.localStorage; + } catch (e) {} } -module.exports = require('./common')(exports); - -const {formatters} = module.exports; - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -formatters.j = function (v) { - try { - return JSON.stringify(v); - } catch (error) { - return '[UnexpectedJSONParseError]: ' + error.message; - } -}; - }).call(this)}).call(this,require('_process')) -},{"./common":26,"_process":79}],26:[function(require,module,exports){ +},{"./debug":26,"_process":78}],26:[function(require,module,exports){ /** * This is the common logic for both the Node.js and web browser * implementations of `debug()`. + * + * Expose `debug()` as the module. */ -function setup(env) { - createDebug.debug = createDebug; - createDebug.default = createDebug; - createDebug.coerce = coerce; - createDebug.disable = disable; - createDebug.enable = enable; - createDebug.enabled = enabled; - createDebug.humanize = require('ms'); - createDebug.destroy = destroy; +exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = require('ms'); - Object.keys(env).forEach(key => { - createDebug[key] = env[key]; - }); - - /** - * The currently active debug mode names, and names to skip. - */ - - createDebug.names = []; - createDebug.skips = []; - - /** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - createDebug.formatters = {}; - - /** - * Selects a color for a debug namespace - * @param {String} namespace The namespace string for the debug instance to be colored - * @return {Number|String} An ANSI color code for the given namespace - * @api private - */ - function selectColor(namespace) { - let hash = 0; - - for (let i = 0; i < namespace.length; i++) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; - } - createDebug.selectColor = selectColor; - - /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - function createDebug(namespace) { - let prevTime; - let enableOverride = null; - let namespacesCache; - let enabledCache; - - function debug(...args) { - // Disabled? - if (!debug.enabled) { - return; - } - - const self = debug; - - // Set `diff` timestamp - const curr = Number(new Date()); - const ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - args[0] = createDebug.coerce(args[0]); - - if (typeof args[0] !== 'string') { - // Anything else let's inspect with %O - args.unshift('%O'); - } - - // Apply any `formatters` transformations - let index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { - // If we encounter an escaped % then don't increase the array index - if (match === '%%') { - return '%'; - } - index++; - const formatter = createDebug.formatters[format]; - if (typeof formatter === 'function') { - const val = args[index]; - match = formatter.call(self, val); - - // Now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // Apply env-specific formatting (colors, etc.) - createDebug.formatArgs.call(self, args); - - const logFn = self.log || createDebug.log; - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.useColors = createDebug.useColors(); - debug.color = createDebug.selectColor(namespace); - debug.extend = extend; - debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. - - Object.defineProperty(debug, 'enabled', { - enumerable: true, - configurable: false, - get: () => { - if (enableOverride !== null) { - return enableOverride; - } - if (namespacesCache !== createDebug.namespaces) { - namespacesCache = createDebug.namespaces; - enabledCache = createDebug.enabled(namespace); - } - - return enabledCache; - }, - set: v => { - enableOverride = v; - } - }); - - // Env-specific initialization logic for debug instances - if (typeof createDebug.init === 'function') { - createDebug.init(debug); - } - - return debug; - } - - function extend(namespace, delimiter) { - const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); - newDebug.log = this.log; - return newDebug; - } - - /** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - function enable(namespaces) { - createDebug.save(namespaces); - createDebug.namespaces = namespaces; - - createDebug.names = []; - createDebug.skips = []; - - let i; - const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - const len = split.length; - - for (i = 0; i < len; i++) { - if (!split[i]) { - // ignore empty strings - continue; - } - - namespaces = split[i].replace(/\*/g, '.*?'); - - if (namespaces[0] === '-') { - createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$')); - } else { - createDebug.names.push(new RegExp('^' + namespaces + '$')); - } - } - } - - /** - * Disable debug output. - * - * @return {String} namespaces - * @api public - */ - function disable() { - const namespaces = [ - ...createDebug.names.map(toNamespace), - ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) - ].join(','); - createDebug.enable(''); - return namespaces; - } - - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - function enabled(name) { - if (name[name.length - 1] === '*') { - return true; - } - - let i; - let len; - - for (i = 0, len = createDebug.skips.length; i < len; i++) { - if (createDebug.skips[i].test(name)) { - return false; - } - } - - for (i = 0, len = createDebug.names.length; i < len; i++) { - if (createDebug.names[i].test(name)) { - return true; - } - } - - return false; - } - - /** - * Convert regexp to namespace - * - * @param {RegExp} regxep - * @return {String} namespace - * @api private - */ - function toNamespace(regexp) { - return regexp.toString() - .substring(2, regexp.toString().length - 2) - .replace(/\.\*\?$/, '*'); - } - - /** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - function coerce(val) { - if (val instanceof Error) { - return val.stack || val.message; - } - return val; - } - - /** - * XXX DO NOT USE. This is a temporary stub function. - * XXX It WILL be removed in the next major release. - */ - function destroy() { - console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); - } - - createDebug.enable(createDebug.load()); - - return createDebug; -} - -module.exports = setup; - -},{"ms":27}],27:[function(require,module,exports){ /** - * Helpers. + * Active `debug` instances. + */ +exports.instances = []; + +/** + * The currently active debug mode names, and names to skip. */ -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var w = d * 7; -var y = d * 365.25; +exports.names = []; +exports.skips = []; /** - * Parse or format the given `val`. + * Map of special "%n" handling functions, for the debug "format" argument. * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} - * @api public + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". */ -module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isFinite(val)) { - return options.long ? fmtLong(val) : fmtShort(val); - } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); -}; +exports.formatters = {}; /** - * Parse the given `str` and return milliseconds. - * - * @param {String} str + * Select a color. + * @param {String} namespace * @return {Number} * @api private */ -function parse(str) { - str = String(str); - if (str.length > 100) { - return; +function selectColor(namespace) { + var hash = 0, i; + + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer } - var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; + + return exports.colors[Math.abs(hash) % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function createDebug(namespace) { + + var prevTime; + + function debug() { + // disabled? + if (!debug.enabled) return; + + var self = debug; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); + + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'weeks': - case 'week': - case 'w': - return n * w; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; + + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } + + exports.instances.push(debug); + + return debug; +} + +function destroy () { + var index = exports.instances.indexOf(this); + if (index !== -1) { + exports.instances.splice(index, 1); + return true; + } else { + return false; } } /** - * Short format for `ms`. + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. * - * @param {Number} ms - * @return {String} + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + exports.names = []; + exports.skips = []; + + var i; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < exports.instances.length; i++) { + var instance = exports.instances[i]; + instance.enabled = exports.enabled(instance.namespace); + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} * @api private */ -function fmtShort(ms) { - var msAbs = Math.abs(ms); - if (msAbs >= d) { - return Math.round(ms / d) + 'd'; - } - if (msAbs >= h) { - return Math.round(ms / h) + 'h'; - } - if (msAbs >= m) { - return Math.round(ms / m) + 'm'; - } - if (msAbs >= s) { - return Math.round(ms / s) + 's'; - } - return ms + 'ms'; +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; } -/** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtLong(ms) { - var msAbs = Math.abs(ms); - if (msAbs >= d) { - return plural(ms, msAbs, d, 'day'); - } - if (msAbs >= h) { - return plural(ms, msAbs, h, 'hour'); - } - if (msAbs >= m) { - return plural(ms, msAbs, m, 'minute'); - } - if (msAbs >= s) { - return plural(ms, msAbs, s, 'second'); - } - return ms + ' ms'; -} - -/** - * Pluralization helper. - */ - -function plural(ms, msAbs, n, name) { - var isPlural = msAbs >= n * 1.5; - return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); -} - -},{}],28:[function(require,module,exports){ +},{"ms":75}],27:[function(require,module,exports){ /** * Module dependencies. */ @@ -6520,7 +6233,7 @@ exports.decodePayloadAsBinary = function (data, binaryType, callback) { }); }; -},{"./keys":29,"./utf8":30,"after":1,"arraybuffer.slice":2,"base64-arraybuffer":5,"blob":7,"has-binary2":36}],29:[function(require,module,exports){ +},{"./keys":28,"./utf8":29,"after":1,"arraybuffer.slice":2,"base64-arraybuffer":5,"blob":7,"has-binary2":35}],28:[function(require,module,exports){ /** * Gets the keys for an object. @@ -6541,7 +6254,7 @@ module.exports = Object.keys || function keys (obj){ return arr; }; -},{}],30:[function(require,module,exports){ +},{}],29:[function(require,module,exports){ /*! https://mths.be/utf8js v2.1.2 by @mathias */ var stringFromCharCode = String.fromCharCode; @@ -6753,7 +6466,7 @@ module.exports = { decode: utf8decode }; -},{}],31:[function(require,module,exports){ +},{}],30:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -7252,7 +6965,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) { } } -},{}],32:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ const debug = require('debug')('h264-profile-level-id'); /* eslint-disable no-console */ @@ -7707,13 +7420,720 @@ function isLevelAsymmetryAllowed(params = {}) ); } -},{"debug":33}],33:[function(require,module,exports){ -arguments[4][25][0].apply(exports,arguments) -},{"./common":34,"_process":79,"dup":25}],34:[function(require,module,exports){ -arguments[4][26][0].apply(exports,arguments) -},{"dup":26,"ms":35}],35:[function(require,module,exports){ -arguments[4][27][0].apply(exports,arguments) -},{"dup":27}],36:[function(require,module,exports){ +},{"debug":32}],32:[function(require,module,exports){ +(function (process){(function (){ +/* eslint-env browser */ + +/** + * This is the web browser implementation of `debug()`. + */ + +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +exports.destroy = (() => { + let warned = false; + + return () => { + if (!warned) { + warned = true; + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + }; +})(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +// eslint-disable-next-line complexity +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.debug()` when available. + * No-op when `console.debug` is not a "function". + * If `console.debug` is not available, falls back + * to `console.log`. + * + * @api public + */ +exports.log = console.debug || console.log || (() => {}); + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ +function load() { + let r; + try { + r = exports.storage.getItem('debug'); + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +module.exports = require('./common')(exports); + +const {formatters} = module.exports; + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; + +}).call(this)}).call(this,require('_process')) +},{"./common":33,"_process":78}],33:[function(require,module,exports){ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = require('ms'); + createDebug.destroy = destroy; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return '%'; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + + return enabledCache; + }, + set: v => { + enableOverride = v; + } + }); + + // Env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + return debug; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = namespaces; + + createDebug.names = []; + createDebug.skips = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + let i; + let len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + + /** + * Convert regexp to namespace + * + * @param {RegExp} regxep + * @return {String} namespace + * @api private + */ + function toNamespace(regexp) { + return regexp.toString() + .substring(2, regexp.toString().length - 2) + .replace(/\.\*\?$/, '*'); + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + /** + * XXX DO NOT USE. This is a temporary stub function. + * XXX It WILL be removed in the next major release. + */ + function destroy() { + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + + createDebug.enable(createDebug.load()); + + return createDebug; +} + +module.exports = setup; + +},{"ms":34}],34:[function(require,module,exports){ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} + +},{}],35:[function(require,module,exports){ (function (Buffer){(function (){ /* global Blob File */ @@ -7781,7 +8201,7 @@ function hasBinary (obj) { } }).call(this)}).call(this,require("buffer").Buffer) -},{"buffer":10,"isarray":40}],37:[function(require,module,exports){ +},{"buffer":10,"isarray":39}],36:[function(require,module,exports){ /** * Module exports. @@ -7800,7 +8220,7 @@ try { module.exports = false; } -},{}],38:[function(require,module,exports){ +},{}],37:[function(require,module,exports){ /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m @@ -7887,7 +8307,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],39:[function(require,module,exports){ +},{}],38:[function(require,module,exports){ var indexOf = [].indexOf; @@ -7898,14 +8318,14 @@ module.exports = function(arr, obj){ } return -1; }; -},{}],40:[function(require,module,exports){ +},{}],39:[function(require,module,exports){ var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; -},{}],41:[function(require,module,exports){ +},{}],40:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Consumer = void 0; @@ -8087,7 +8507,7 @@ class Consumer extends EnhancedEventEmitter_1.EnhancedEventEmitter { } exports.Consumer = Consumer; -},{"./EnhancedEventEmitter":45,"./Logger":46,"./errors":51}],42:[function(require,module,exports){ +},{"./EnhancedEventEmitter":44,"./Logger":45,"./errors":50}],41:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DataConsumer = void 0; @@ -8243,7 +8663,7 @@ class DataConsumer extends EnhancedEventEmitter_1.EnhancedEventEmitter { } exports.DataConsumer = DataConsumer; -},{"./EnhancedEventEmitter":45,"./Logger":46}],43:[function(require,module,exports){ +},{"./EnhancedEventEmitter":44,"./Logger":45}],42:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DataProducer = void 0; @@ -8415,7 +8835,7 @@ class DataProducer extends EnhancedEventEmitter_1.EnhancedEventEmitter { } exports.DataProducer = DataProducer; -},{"./EnhancedEventEmitter":45,"./Logger":46,"./errors":51}],44:[function(require,module,exports){ +},{"./EnhancedEventEmitter":44,"./Logger":45,"./errors":50}],43:[function(require,module,exports){ "use strict"; /* global RTCRtpTransceiver */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { @@ -8810,7 +9230,7 @@ class Device { } exports.Device = Device; -},{"./EnhancedEventEmitter":45,"./Logger":46,"./Transport":50,"./errors":51,"./handlers/Chrome55":52,"./handlers/Chrome67":53,"./handlers/Chrome70":54,"./handlers/Chrome74":55,"./handlers/Edge11":56,"./handlers/Firefox60":57,"./handlers/ReactNative":59,"./handlers/Safari11":60,"./handlers/Safari12":61,"./ortc":69,"./utils":72,"bowser":8}],45:[function(require,module,exports){ +},{"./EnhancedEventEmitter":44,"./Logger":45,"./Transport":49,"./errors":50,"./handlers/Chrome55":51,"./handlers/Chrome67":52,"./handlers/Chrome70":53,"./handlers/Chrome74":54,"./handlers/Edge11":55,"./handlers/Firefox60":56,"./handlers/ReactNative":58,"./handlers/Safari11":59,"./handlers/Safari12":60,"./ortc":68,"./utils":71,"bowser":8}],44:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnhancedEventEmitter = void 0; @@ -8882,7 +9302,7 @@ class EnhancedEventEmitter extends events_1.EventEmitter { } exports.EnhancedEventEmitter = EnhancedEventEmitter; -},{"./Logger":46,"events":31}],46:[function(require,module,exports){ +},{"./Logger":45,"events":30}],45:[function(require,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; @@ -8921,7 +9341,7 @@ class Logger { } exports.Logger = Logger; -},{"debug":73}],47:[function(require,module,exports){ +},{"debug":72}],46:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Producer = void 0; @@ -9199,7 +9619,7 @@ class Producer extends EnhancedEventEmitter_1.EnhancedEventEmitter { } exports.Producer = Producer; -},{"./EnhancedEventEmitter":45,"./Logger":46,"./errors":51}],48:[function(require,module,exports){ +},{"./EnhancedEventEmitter":44,"./Logger":45,"./errors":50}],47:[function(require,module,exports){ "use strict"; /** * The RTP capabilities define what mediasoup or an endpoint can receive at @@ -9207,11 +9627,11 @@ exports.Producer = Producer; */ Object.defineProperty(exports, "__esModule", { value: true }); -},{}],49:[function(require,module,exports){ +},{}],48:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -},{}],50:[function(require,module,exports){ +},{}],49:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -9895,7 +10315,7 @@ class Transport extends EnhancedEventEmitter_1.EnhancedEventEmitter { } exports.Transport = Transport; -},{"./Consumer":41,"./DataConsumer":42,"./DataProducer":43,"./EnhancedEventEmitter":45,"./Logger":46,"./Producer":47,"./errors":51,"./ortc":69,"./utils":72,"awaitqueue":3}],51:[function(require,module,exports){ +},{"./Consumer":40,"./DataConsumer":41,"./DataProducer":42,"./EnhancedEventEmitter":44,"./Logger":45,"./Producer":46,"./errors":50,"./ortc":68,"./utils":71,"awaitqueue":3}],50:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InvalidStateError = exports.UnsupportedError = void 0; @@ -9936,7 +10356,7 @@ class InvalidStateError extends Error { } exports.InvalidStateError = InvalidStateError; -},{}],52:[function(require,module,exports){ +},{}],51:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -10457,7 +10877,7 @@ class Chrome55 extends HandlerInterface_1.HandlerInterface { } exports.Chrome55 = Chrome55; -},{"../Logger":46,"../errors":51,"../ortc":69,"../utils":72,"./HandlerInterface":58,"./sdp/RemoteSdp":64,"./sdp/commonUtils":65,"./sdp/planBUtils":66,"sdp-transform":81}],53:[function(require,module,exports){ +},{"../Logger":45,"../errors":50,"../ortc":68,"../utils":71,"./HandlerInterface":57,"./sdp/RemoteSdp":63,"./sdp/commonUtils":64,"./sdp/planBUtils":65,"sdp-transform":80}],52:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -11025,7 +11445,7 @@ class Chrome67 extends HandlerInterface_1.HandlerInterface { } exports.Chrome67 = Chrome67; -},{"../Logger":46,"../ortc":69,"../utils":72,"./HandlerInterface":58,"./sdp/RemoteSdp":64,"./sdp/commonUtils":65,"./sdp/planBUtils":66,"sdp-transform":81}],54:[function(require,module,exports){ +},{"../Logger":45,"../ortc":68,"../utils":71,"./HandlerInterface":57,"./sdp/RemoteSdp":63,"./sdp/commonUtils":64,"./sdp/planBUtils":65,"sdp-transform":80}],53:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -11600,7 +12020,7 @@ class Chrome70 extends HandlerInterface_1.HandlerInterface { } exports.Chrome70 = Chrome70; -},{"../Logger":46,"../ortc":69,"../scalabilityModes":70,"../utils":72,"./HandlerInterface":58,"./sdp/RemoteSdp":64,"./sdp/commonUtils":65,"./sdp/unifiedPlanUtils":67,"sdp-transform":81}],55:[function(require,module,exports){ +},{"../Logger":45,"../ortc":68,"../scalabilityModes":69,"../utils":71,"./HandlerInterface":57,"./sdp/RemoteSdp":63,"./sdp/commonUtils":64,"./sdp/unifiedPlanUtils":66,"sdp-transform":80}],54:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -12189,7 +12609,7 @@ class Chrome74 extends HandlerInterface_1.HandlerInterface { } exports.Chrome74 = Chrome74; -},{"../Logger":46,"../ortc":69,"../scalabilityModes":70,"../utils":72,"./HandlerInterface":58,"./sdp/RemoteSdp":64,"./sdp/commonUtils":65,"./sdp/unifiedPlanUtils":67,"sdp-transform":81}],56:[function(require,module,exports){ +},{"../Logger":45,"../ortc":68,"../scalabilityModes":69,"../utils":71,"./HandlerInterface":57,"./sdp/RemoteSdp":63,"./sdp/commonUtils":64,"./sdp/unifiedPlanUtils":66,"sdp-transform":80}],55:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -12612,7 +13032,7 @@ class Edge11 extends HandlerInterface_1.HandlerInterface { } exports.Edge11 = Edge11; -},{"../Logger":46,"../errors":51,"../ortc":69,"../utils":72,"./HandlerInterface":58,"./ortc/edgeUtils":62}],57:[function(require,module,exports){ +},{"../Logger":45,"../errors":50,"../ortc":68,"../utils":71,"./HandlerInterface":57,"./ortc/edgeUtils":61}],56:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -13201,7 +13621,7 @@ class Firefox60 extends HandlerInterface_1.HandlerInterface { } exports.Firefox60 = Firefox60; -},{"../Logger":46,"../errors":51,"../ortc":69,"../utils":72,"./HandlerInterface":58,"./sdp/RemoteSdp":64,"./sdp/commonUtils":65,"./sdp/unifiedPlanUtils":67,"sdp-transform":81}],58:[function(require,module,exports){ +},{"../Logger":45,"../errors":50,"../ortc":68,"../utils":71,"./HandlerInterface":57,"./sdp/RemoteSdp":63,"./sdp/commonUtils":64,"./sdp/unifiedPlanUtils":66,"sdp-transform":80}],57:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HandlerInterface = void 0; @@ -13213,7 +13633,7 @@ class HandlerInterface extends EnhancedEventEmitter_1.EnhancedEventEmitter { } exports.HandlerInterface = HandlerInterface; -},{"../EnhancedEventEmitter":45}],59:[function(require,module,exports){ +},{"../EnhancedEventEmitter":44}],58:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -13748,7 +14168,7 @@ class ReactNative extends HandlerInterface_1.HandlerInterface { } exports.ReactNative = ReactNative; -},{"../Logger":46,"../errors":51,"../ortc":69,"../utils":72,"./HandlerInterface":58,"./sdp/RemoteSdp":64,"./sdp/commonUtils":65,"./sdp/planBUtils":66,"sdp-transform":81}],60:[function(require,module,exports){ +},{"../Logger":45,"../errors":50,"../ortc":68,"../utils":71,"./HandlerInterface":57,"./sdp/RemoteSdp":63,"./sdp/commonUtils":64,"./sdp/planBUtils":65,"sdp-transform":80}],59:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -14308,7 +14728,7 @@ class Safari11 extends HandlerInterface_1.HandlerInterface { } exports.Safari11 = Safari11; -},{"../Logger":46,"../ortc":69,"../utils":72,"./HandlerInterface":58,"./sdp/RemoteSdp":64,"./sdp/commonUtils":65,"./sdp/planBUtils":66,"sdp-transform":81}],61:[function(require,module,exports){ +},{"../Logger":45,"../ortc":68,"../utils":71,"./HandlerInterface":57,"./sdp/RemoteSdp":63,"./sdp/commonUtils":64,"./sdp/planBUtils":65,"sdp-transform":80}],60:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -14865,7 +15285,7 @@ class Safari12 extends HandlerInterface_1.HandlerInterface { } exports.Safari12 = Safari12; -},{"../Logger":46,"../ortc":69,"../utils":72,"./HandlerInterface":58,"./sdp/RemoteSdp":64,"./sdp/commonUtils":65,"./sdp/unifiedPlanUtils":67,"sdp-transform":81}],62:[function(require,module,exports){ +},{"../Logger":45,"../ortc":68,"../utils":71,"./HandlerInterface":57,"./sdp/RemoteSdp":63,"./sdp/commonUtils":64,"./sdp/unifiedPlanUtils":66,"sdp-transform":80}],61:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -14949,7 +15369,7 @@ function mangleRtpParameters(rtpParameters) { } exports.mangleRtpParameters = mangleRtpParameters; -},{"../../utils":72}],63:[function(require,module,exports){ +},{"../../utils":71}],62:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -15483,7 +15903,7 @@ function getCodecName(codec) { return mimeTypeMatch[2]; } -},{"../../utils":72}],64:[function(require,module,exports){ +},{"../../utils":71}],63:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -15764,7 +16184,7 @@ class RemoteSdp { } exports.RemoteSdp = RemoteSdp; -},{"../../Logger":46,"./MediaSection":63,"sdp-transform":81}],65:[function(require,module,exports){ +},{"../../Logger":45,"./MediaSection":62,"sdp-transform":80}],64:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -15960,7 +16380,7 @@ function applyCodecParameters({ offerRtpParameters, answerMediaObject }) { } exports.applyCodecParameters = applyCodecParameters; -},{"sdp-transform":81}],66:[function(require,module,exports){ +},{"sdp-transform":80}],65:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addLegacySimulcast = exports.getRtpEncodings = void 0; @@ -16106,7 +16526,7 @@ function addLegacySimulcast({ offerMediaObject, track, numStreams }) { } exports.addLegacySimulcast = addLegacySimulcast; -},{}],67:[function(require,module,exports){ +},{}],66:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addLegacySimulcast = exports.getRtpEncodings = void 0; @@ -16231,7 +16651,7 @@ function addLegacySimulcast({ offerMediaObject, numStreams }) { } exports.addLegacySimulcast = addLegacySimulcast; -},{}],68:[function(require,module,exports){ +},{}],67:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -16278,7 +16698,7 @@ exports.version = '3.6.54'; var scalabilityModes_1 = require("./scalabilityModes"); Object.defineProperty(exports, "parseScalabilityMode", { enumerable: true, get: function () { return scalabilityModes_1.parse; } }); -},{"./Device":44,"./scalabilityModes":70,"./types":71,"debug":73}],69:[function(require,module,exports){ +},{"./Device":43,"./scalabilityModes":69,"./types":70,"debug":72}],68:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -17125,7 +17545,7 @@ function reduceRtcpFeedback(codecA, codecB) { return reducedRtcpFeedback; } -},{"./utils":72,"h264-profile-level-id":32}],70:[function(require,module,exports){ +},{"./utils":71,"h264-profile-level-id":31}],69:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parse = void 0; @@ -17147,7 +17567,7 @@ function parse(scalabilityMode) { } exports.parse = parse; -},{}],71:[function(require,module,exports){ +},{}],70:[function(require,module,exports){ "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; @@ -17175,7 +17595,7 @@ __exportStar(require("./SctpParameters"), exports); __exportStar(require("./handlers/HandlerInterface"), exports); __exportStar(require("./errors"), exports); -},{"./Consumer":41,"./DataConsumer":42,"./DataProducer":43,"./Device":44,"./Producer":47,"./RtpParameters":48,"./SctpParameters":49,"./Transport":50,"./errors":51,"./handlers/HandlerInterface":58}],72:[function(require,module,exports){ +},{"./Consumer":40,"./DataConsumer":41,"./DataProducer":42,"./Device":43,"./Producer":46,"./RtpParameters":47,"./SctpParameters":48,"./Transport":49,"./errors":50,"./handlers/HandlerInterface":57}],71:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateRandomNumber = exports.clone = void 0; @@ -17196,13 +17616,13 @@ function generateRandomNumber() { } exports.generateRandomNumber = generateRandomNumber; -},{}],73:[function(require,module,exports){ -arguments[4][25][0].apply(exports,arguments) -},{"./common":74,"_process":79,"dup":25}],74:[function(require,module,exports){ -arguments[4][26][0].apply(exports,arguments) -},{"dup":26,"ms":75}],75:[function(require,module,exports){ -arguments[4][27][0].apply(exports,arguments) -},{"dup":27}],76:[function(require,module,exports){ +},{}],72:[function(require,module,exports){ +arguments[4][32][0].apply(exports,arguments) +},{"./common":73,"_process":78,"dup":32}],73:[function(require,module,exports){ +arguments[4][33][0].apply(exports,arguments) +},{"dup":33,"ms":74}],74:[function(require,module,exports){ +arguments[4][34][0].apply(exports,arguments) +},{"dup":34}],75:[function(require,module,exports){ /** * Helpers. */ @@ -17356,7 +17776,7 @@ function plural(ms, n, name) { return Math.ceil(ms / n) + ' ' + name + 's'; } -},{}],77:[function(require,module,exports){ +},{}],76:[function(require,module,exports){ /** * Compiles a querystring * Returns string representation of the object @@ -17395,7 +17815,7 @@ exports.decode = function(qs){ return qry; }; -},{}],78:[function(require,module,exports){ +},{}],77:[function(require,module,exports){ /** * Parses an URI * @@ -17436,7 +17856,7 @@ module.exports = function parseuri(str) { return uri; }; -},{}],79:[function(require,module,exports){ +},{}],78:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -17622,7 +18042,7 @@ process.chdir = function (dir) { }; process.umask = function() { return 0; }; -},{}],80:[function(require,module,exports){ +},{}],79:[function(require,module,exports){ var grammar = module.exports = { v: [{ name: 'version', @@ -18118,7 +18538,7 @@ Object.keys(grammar).forEach(function (key) { }); }); -},{}],81:[function(require,module,exports){ +},{}],80:[function(require,module,exports){ var parser = require('./parser'); var writer = require('./writer'); @@ -18131,7 +18551,7 @@ exports.parseRemoteCandidates = parser.parseRemoteCandidates; exports.parseImageAttributes = parser.parseImageAttributes; exports.parseSimulcastStreamList = parser.parseSimulcastStreamList; -},{"./parser":82,"./writer":83}],82:[function(require,module,exports){ +},{"./parser":81,"./writer":82}],81:[function(require,module,exports){ var toIntIfInt = function (v) { return String(Number(v)) === v ? Number(v) : v; }; @@ -18257,7 +18677,7 @@ exports.parseSimulcastStreamList = function (str) { }); }; -},{"./grammar":80}],83:[function(require,module,exports){ +},{"./grammar":79}],82:[function(require,module,exports){ var grammar = require('./grammar'); // customized util.format - discards excess arguments and can void middle ones @@ -18373,7 +18793,7 @@ module.exports = function (session, opts) { return sdp.join('\r\n') + '\r\n'; }; -},{"./grammar":80}],84:[function(require,module,exports){ +},{"./grammar":79}],83:[function(require,module,exports){ /** * Module dependencies. @@ -18469,7 +18889,7 @@ exports.connect = lookup; exports.Manager = require('./manager'); exports.Socket = require('./socket'); -},{"./manager":85,"./socket":87,"./url":88,"debug":14,"socket.io-parser":90}],85:[function(require,module,exports){ +},{"./manager":84,"./socket":86,"./url":87,"debug":14,"socket.io-parser":89}],84:[function(require,module,exports){ /** * Module dependencies. @@ -19044,7 +19464,7 @@ Manager.prototype.onreconnect = function () { this.emitAll('reconnect', attempt); }; -},{"./on":86,"./socket":87,"backo2":4,"component-bind":11,"component-emitter":12,"debug":14,"engine.io-client":16,"indexof":39,"socket.io-parser":90}],86:[function(require,module,exports){ +},{"./on":85,"./socket":86,"backo2":4,"component-bind":11,"component-emitter":12,"debug":14,"engine.io-client":16,"indexof":38,"socket.io-parser":89}],85:[function(require,module,exports){ /** * Module exports. @@ -19070,7 +19490,7 @@ function on (obj, ev, fn) { }; } -},{}],87:[function(require,module,exports){ +},{}],86:[function(require,module,exports){ /** * Module dependencies. @@ -19490,7 +19910,7 @@ Socket.prototype.compress = function (compress) { return this; }; -},{"./on":86,"component-bind":11,"component-emitter":12,"debug":14,"parseqs":77,"socket.io-parser":90,"to-array":94}],88:[function(require,module,exports){ +},{"./on":85,"component-bind":11,"component-emitter":12,"debug":14,"parseqs":76,"socket.io-parser":89,"to-array":93}],87:[function(require,module,exports){ (function (global){(function (){ /** @@ -19569,7 +19989,7 @@ function url (uri, loc) { } }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"debug":14,"parseuri":78}],89:[function(require,module,exports){ +},{"debug":14,"parseuri":77}],88:[function(require,module,exports){ (function (global){(function (){ /*global Blob,File*/ @@ -19714,7 +20134,7 @@ exports.removeBlobs = function(data, callback) { }; }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./is-buffer":91,"isarray":40}],90:[function(require,module,exports){ +},{"./is-buffer":90,"isarray":39}],89:[function(require,module,exports){ /** * Module dependencies. @@ -20124,7 +20544,7 @@ function error(msg) { }; } -},{"./binary":89,"./is-buffer":91,"component-emitter":12,"debug":92,"has-binary2":36,"isarray":40}],91:[function(require,module,exports){ +},{"./binary":88,"./is-buffer":90,"component-emitter":12,"debug":91,"has-binary2":35,"isarray":39}],90:[function(require,module,exports){ (function (global){(function (){ module.exports = isBuf; @@ -20141,433 +20561,11 @@ function isBuf(obj) { } }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],92:[function(require,module,exports){ -(function (process){(function (){ -/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = require('./debug'); -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = 'undefined' != typeof chrome - && 'undefined' != typeof chrome.storage - ? chrome.storage.local - : localstorage(); - -/** - * Colors. - */ - -exports.colors = [ - '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', - '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', - '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', - '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', - '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', - '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', - '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', - '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', - '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', - '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', - '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' -]; - -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { - return true; - } - - // Internet Explorer and Edge do not support colors. - if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { - return false; - } - - // is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -exports.formatters.j = function(v) { - try { - return JSON.stringify(v); - } catch (err) { - return '[UnexpectedJSONParseError]: ' + err.message; - } -}; - - -/** - * Colorize log arguments if enabled. - * - * @api public - */ - -function formatArgs(args) { - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return; - - var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') - - // the final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - var index = 0; - var lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, function(match) { - if ('%%' === match) return; - index++; - if ('%c' === match) { - // we only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); -} - -/** - * Invokes `console.log()` when available. - * No-op when `console.log` is not a "function". - * - * @api public - */ - -function log() { - // this hackery is required for IE8/9, where - // the `console.log` function doesn't have 'apply' - return 'object' === typeof console - && console.log - && Function.prototype.apply.call(console.log, console, arguments); -} - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ - -function save(namespaces) { - try { - if (null == namespaces) { - exports.storage.removeItem('debug'); - } else { - exports.storage.debug = namespaces; - } - } catch(e) {} -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ - -function load() { - var r; - try { - r = exports.storage.debug; - } catch(e) {} - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } - - return r; -} - -/** - * Enable namespaces listed in `localStorage.debug` initially. - */ - -exports.enable(load()); - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage() { - try { - return window.localStorage; - } catch (e) {} -} - -}).call(this)}).call(this,require('_process')) -},{"./debug":93,"_process":79}],93:[function(require,module,exports){ - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - * - * Expose `debug()` as the module. - */ - -exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; -exports.coerce = coerce; -exports.disable = disable; -exports.enable = enable; -exports.enabled = enabled; -exports.humanize = require('ms'); - -/** - * Active `debug` instances. - */ -exports.instances = []; - -/** - * The currently active debug mode names, and names to skip. - */ - -exports.names = []; -exports.skips = []; - -/** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - -exports.formatters = {}; - -/** - * Select a color. - * @param {String} namespace - * @return {Number} - * @api private - */ - -function selectColor(namespace) { - var hash = 0, i; - - for (i in namespace) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return exports.colors[Math.abs(hash) % exports.colors.length]; -} - -/** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - -function createDebug(namespace) { - - var prevTime; - - function debug() { - // disabled? - if (!debug.enabled) return; - - var self = debug; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // turn the `arguments` into a proper Array - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %O - args.unshift('%O'); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { - // if we encounter an escaped % then don't increase the array index - if (match === '%%') return match; - index++; - var formatter = exports.formatters[format]; - if ('function' === typeof formatter) { - var val = args[index]; - match = formatter.call(self, val); - - // now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // apply env-specific formatting (colors, etc.) - exports.formatArgs.call(self, args); - - var logFn = debug.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.enabled = exports.enabled(namespace); - debug.useColors = exports.useColors(); - debug.color = selectColor(namespace); - debug.destroy = destroy; - - // env-specific initialization logic for debug instances - if ('function' === typeof exports.init) { - exports.init(debug); - } - - exports.instances.push(debug); - - return debug; -} - -function destroy () { - var index = exports.instances.indexOf(this); - if (index !== -1) { - exports.instances.splice(index, 1); - return true; - } else { - return false; - } -} - -/** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - -function enable(namespaces) { - exports.save(namespaces); - - exports.names = []; - exports.skips = []; - - var i; - var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - var len = split.length; - - for (i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } - - for (i = 0; i < exports.instances.length; i++) { - var instance = exports.instances[i]; - instance.enabled = exports.enabled(instance.namespace); - } -} - -/** - * Disable debug output. - * - * @api public - */ - -function disable() { - exports.enable(''); -} - -/** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - -function enabled(name) { - if (name[name.length - 1] === '*') { - return true; - } - var i, len; - for (i = 0, len = exports.skips.length; i < len; i++) { - if (exports.skips[i].test(name)) { - return false; - } - } - for (i = 0, len = exports.names.length; i < len; i++) { - if (exports.names[i].test(name)) { - return true; - } - } - return false; -} - -/** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - -function coerce(val) { - if (val instanceof Error) return val.stack || val.message; - return val; -} - -},{"ms":76}],94:[function(require,module,exports){ +},{}],91:[function(require,module,exports){ +arguments[4][25][0].apply(exports,arguments) +},{"./debug":92,"_process":78,"dup":25}],92:[function(require,module,exports){ +arguments[4][26][0].apply(exports,arguments) +},{"dup":26,"ms":75}],93:[function(require,module,exports){ module.exports = toArray function toArray(list, index) { @@ -20582,7 +20580,7 @@ function toArray(list, index) { return array } -},{}],95:[function(require,module,exports){ +},{}],94:[function(require,module,exports){ 'use strict'; var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('') @@ -20652,61 +20650,90 @@ yeast.encode = encode; yeast.decode = decode; module.exports = yeast; -},{}],96:[function(require,module,exports){ -const io = require("socket.io-client"); +},{}],95:[function(require,module,exports){ +const io = require('socket.io-client') const mediasoupClient = require('mediasoup-client') +const urlParams = new URLSearchParams(location.search); -const ASSET_ID = 71 -const ACCOUNT_ID = 1 +const ASSET_ID = parseInt(urlParams.get('assetId')) || null; +const ACCOUNT_ID = parseInt(urlParams.get('accountId')) || null; +let callId = parseInt(urlParams.get('callId')) || null; +const IS_PRODUCER = urlParams.get('producer') === 'true' ? true : false +console.log('ASSET_ID', ASSET_ID, '| ACCOUNT_ID', ACCOUNT_ID, '| callId', callId, ' | IS_PRODUCER', IS_PRODUCER) -let hub = io('https://hub.dev.linx.safemobile.com/', { - reconnect: false, - transports: ['websocket'], -}) +let socket +hub = io('https://hub.dev.linx.safemobile.com/') -hub.on('connect', async () => { - console.log('hub.connected', hub.connected); - hub.emit( - 'ars', - JSON.stringify({ - ars: true, - asset_id: ASSET_ID, - account_id: ACCOUNT_ID, +if (IS_PRODUCER === true) { + hub.on('connect', async () => { + console.log('hub.connected', hub.connected); + hub.emit( + 'ars', + JSON.stringify({ + ars: true, + asset_id: ASSET_ID, + account_id: ACCOUNT_ID, + }) + ); + + hub.on('video', (data) => { + const parsedData = JSON.parse(data); + console.log('video', parsedData) + originAssetId = parsedData.origin_asset_id; + originAssetName = parsedData.origin_asset_name; + originAssetTypeName = parsedData.origin_asset_type_name; + callId = parsedData.video_call_id; + + console.log('IS_PRODUCER', IS_PRODUCER); + + if (parsedData.type === 'notify-request' && IS_PRODUCER) { + getLocalStream() + } + + // setTimeout(() => { + // !IS_PRODUCER && goConnect() + // }, 1000); + // getRtpCapabilities() }) - ); -}); - -hub.on("connect_error", (error) => { - console.log('connect_error', error); -}); - -hub.on('connection', async socket => { - console.log('connection') -}) - -hub.on('disconnect', async socket => { - console.log('disconnect') -}) - -// ------------------------------------------------ - -const mediasoup = io('/mediasoup') - -mediasoup.on('connection-success', ({ socketId }) => { - console.log('mediasoup.connected', mediasoup.connected) - - mediasoup.emit('create-router', { - assetId: ASSET_ID }) + hub.on('connect_error', (error) => { + console.log('connect_error', error); + }); + + hub.on('connection', () => { + console.log('connection') + }) + + hub.on('disconnect', () => { + console.log('disconnect') + }) +} + + +socket = io('https://localhost:3000/mediasoup') + +socket.on('connection-success', ({ socketId, existsProducer }) => { + console.log(socketId, existsProducer) + // if (IS_PRODUCER) { getLocalStream() } + // setInterval(() => { + // if (!IS_PRODUCER && existsProducer) { goConnect() } + + // }, 5000); + if (!IS_PRODUCER && existsProducer && consumer === undefined) { goConnect() } }) + + let device let rtpCapabilities let producerTransport let consumerTransport let producer let consumer +let originAssetId +let originAssetName +let originAssetTypeName // https://mediasoup.org/documentation/v3/mediasoup-client/api/#ProducerOptions // https://mediasoup.org/documentation/v3/mediasoup-client/api/#transport-produce @@ -20735,18 +20762,19 @@ let params = { } } -const streamSuccess = async (stream) => { +const streamSuccess = (stream) => { localVideo.srcObject = stream const track = stream.getVideoTracks()[0] params = { track, ...params } + + goConnect() } const getLocalStream = () => { - - navigator.getUserMedia({ + navigator.mediaDevices.getUserMedia({ audio: false, video: { width: { @@ -20758,11 +20786,21 @@ const getLocalStream = () => { max: 1080, } } - }, streamSuccess, error => { + }) + .then(streamSuccess) + .catch(error => { console.log(error.message) }) } +const goConnect = () => { + device === undefined ? getRtpCapabilities() : goCreateTransport() +} + +const goCreateTransport = () => { + IS_PRODUCER ? createSendTransport() : createRecvTransport() +} + // A device is an endpoint connecting to a Router on the // server side to send/recive media const createDevice = async () => { @@ -20776,7 +20814,10 @@ const createDevice = async () => { routerRtpCapabilities: rtpCapabilities }) - console.log('RTP Capabilities', device.rtpCapabilities) + console.log('Device RTP Capabilities', device.rtpCapabilities) + + // once the device loads, create transport + goCreateTransport() } catch (error) { console.log(error) @@ -20789,19 +20830,22 @@ const getRtpCapabilities = () => { // make a request to the server for Router RTP Capabilities // see server's socket.on('getRtpCapabilities', ...) // the server sends back data object which contains rtpCapabilities - mediasoup.emit('getRtpCapabilities', (data) => { + socket.emit('createRoom', { callId }, (data) => { console.log(`Router RTP Capabilities... ${data.rtpCapabilities}`) // we assign to local variable and will be used when // loading the client Device (see createDevice above) rtpCapabilities = data.rtpCapabilities + + // once we have rtpCapabilities from the Router, create Device + createDevice() }) } const createSendTransport = () => { // see server's socket.on('createWebRtcTransport', sender?, ...) // this is a call from Producer, so sender = true - mediasoup.emit('createWebRtcTransport', { sender: true }, ({ params }) => { + socket.emit('createWebRtcTransport', { sender: true, callId }, ({ params }) => { // The server sends back params needed // to create Send Transport on the client side if (params.error) { @@ -20823,7 +20867,7 @@ const createSendTransport = () => { try { // Signal local DTLS parameters to the server side transport // see server's socket.on('transport-connect', ...) - await mediasoup.emit('transport-connect', { + await socket.emit('transport-connect', { dtlsParameters, }) @@ -20843,7 +20887,7 @@ const createSendTransport = () => { // with the following parameters and produce // and expect back a server side producer id // see server's socket.on('transport-produce', ...) - await mediasoup.emit('transport-produce', { + await socket.emit('transport-produce', { kind: parameters.kind, rtpParameters: parameters.rtpParameters, appData: parameters.appData, @@ -20856,6 +20900,8 @@ const createSendTransport = () => { errback(error) } }) + + connectSendTransport() }) } @@ -20874,15 +20920,32 @@ const connectSendTransport = async () => { producer.on('transportclose', () => { console.log('transport ended') - // close video track }) + + const answer = { + origin_asset_id: ASSET_ID, + dest_asset_id: originAssetId, + type: 'notify-answer', + origin_asset_priority: 1, + origin_asset_type_name: originAssetTypeName, + origin_asset_name: originAssetName, + video_call_id: callId, + answer: 'accepted', // answer: 'rejected' + }; + console.log('SEND answer', answer); + + hub.emit( + 'video', + JSON.stringify(answer) + ); } const createRecvTransport = async () => { + console.log('createRecvTransport'); // see server's socket.on('consume', sender?, ...) // this is a call from Consumer, so sender = false - await mediasoup.emit('createWebRtcTransport', { sender: false }, ({ params }) => { + await socket.emit('createWebRtcTransport', { sender: false, callId }, ({ params }) => { // The server sends back params needed // to create Send Transport on the client side if (params.error) { @@ -20904,7 +20967,7 @@ const createRecvTransport = async () => { try { // Signal local DTLS parameters to the server side transport // see server's socket.on('transport-recv-connect', ...) - await mediasoup.emit('transport-recv-connect', { + await socket.emit('transport-recv-connect', { dtlsParameters, }) @@ -20915,6 +20978,8 @@ const createRecvTransport = async () => { errback(error) } }) + + connectRecvTransport() }) } @@ -20923,15 +20988,16 @@ const connectRecvTransport = async () => { // for consumer, we need to tell the server first // to create a consumer based on the rtpCapabilities and consume // if the router can consume, it will send back a set of params as below - await mediasoup.emit('consume', { + await socket.emit('consume', { rtpCapabilities: device.rtpCapabilities, + callId }, async ({ params }) => { if (params.error) { console.log('Cannot Consume') return } - console.log('params', params) + console.log(params) // then consume with the local consumer transport // which creates a consumer consumer = await consumerTransport.consume({ @@ -20944,20 +21010,16 @@ const connectRecvTransport = async () => { // destructure and retrieve the video track from the producer const { track } = consumer - remoteVideo.srcObject = new MediaStream([track]) + const stream = new MediaStream([track]) + remoteVideo.srcObject = stream // the server consumer started with media paused // so we need to inform the server to resume - console.log('consumer-resume'); - mediasoup.emit('consumer-resume') + socket.emit('consumer-resume') + console.log('consumer', consumer); }) } btnLocalVideo.addEventListener('click', getLocalStream) -btnRtpCapabilities.addEventListener('click', getRtpCapabilities) -btnDevice.addEventListener('click', createDevice) -btnCreateSendTransport.addEventListener('click', createSendTransport) -btnConnectSendTransport.addEventListener('click', connectSendTransport) -btnRecvSendTransport.addEventListener('click', createRecvTransport) -btnConnectRecvTransport.addEventListener('click', connectRecvTransport) -},{"mediasoup-client":68,"socket.io-client":84}]},{},[96]); +btnRecvSendTransport.addEventListener('click', goConnect) +},{"mediasoup-client":67,"socket.io-client":83}]},{},[95]); diff --git a/public/index.html b/public/index.html index 4edfc10..6a6ddae 100644 --- a/public/index.html +++ b/public/index.html @@ -25,8 +25,6 @@ -
-
@@ -49,11 +47,16 @@ + - +
- + +
+
+
+
diff --git a/public/index.js b/public/index.js index 20003a7..254c91d 100644 --- a/public/index.js +++ b/public/index.js @@ -1,57 +1,86 @@ -const io = require("socket.io-client"); +const io = require('socket.io-client') const mediasoupClient = require('mediasoup-client') +const urlParams = new URLSearchParams(location.search); -const ASSET_ID = 71 -const ACCOUNT_ID = 1 +const ASSET_ID = parseInt(urlParams.get('assetId')) || null; +const ACCOUNT_ID = parseInt(urlParams.get('accountId')) || null; +let callId = parseInt(urlParams.get('callId')) || null; +const IS_PRODUCER = urlParams.get('producer') === 'true' ? true : false +console.log('ASSET_ID', ASSET_ID, '| ACCOUNT_ID', ACCOUNT_ID, '| callId', callId, ' | IS_PRODUCER', IS_PRODUCER) -let hub = io('https://hub.dev.linx.safemobile.com/', { - reconnect: false, - transports: ['websocket'], -}) +let socket +hub = io('https://hub.dev.linx.safemobile.com/') -hub.on('connect', async () => { - console.log('hub.connected', hub.connected); - hub.emit( - 'ars', - JSON.stringify({ - ars: true, - asset_id: ASSET_ID, - account_id: ACCOUNT_ID, +if (IS_PRODUCER === true) { + hub.on('connect', async () => { + console.log('hub.connected', hub.connected); + hub.emit( + 'ars', + JSON.stringify({ + ars: true, + asset_id: ASSET_ID, + account_id: ACCOUNT_ID, + }) + ); + + hub.on('video', (data) => { + const parsedData = JSON.parse(data); + console.log('video', parsedData) + originAssetId = parsedData.origin_asset_id; + originAssetName = parsedData.origin_asset_name; + originAssetTypeName = parsedData.origin_asset_type_name; + callId = parsedData.video_call_id; + + console.log('IS_PRODUCER', IS_PRODUCER); + + if (parsedData.type === 'notify-request' && IS_PRODUCER) { + getLocalStream() + } + + // setTimeout(() => { + // !IS_PRODUCER && goConnect() + // }, 1000); + // getRtpCapabilities() }) - ); -}); - -hub.on("connect_error", (error) => { - console.log('connect_error', error); -}); - -hub.on('connection', async socket => { - console.log('connection') -}) - -hub.on('disconnect', async socket => { - console.log('disconnect') -}) - -// ------------------------------------------------ - -const mediasoup = io('/mediasoup') - -mediasoup.on('connection-success', ({ socketId }) => { - console.log('mediasoup.connected', mediasoup.connected) - - mediasoup.emit('create-router', { - assetId: ASSET_ID }) + hub.on('connect_error', (error) => { + console.log('connect_error', error); + }); + + hub.on('connection', () => { + console.log('connection') + }) + + hub.on('disconnect', () => { + console.log('disconnect') + }) +} + + +socket = io('https://localhost:3000/mediasoup') + +socket.on('connection-success', ({ socketId, existsProducer }) => { + console.log(socketId, existsProducer) + // if (IS_PRODUCER) { getLocalStream() } + // setInterval(() => { + // if (!IS_PRODUCER && existsProducer) { goConnect() } + + // }, 5000); + if (!IS_PRODUCER && existsProducer && consumer === undefined) { goConnect() } }) + + let device let rtpCapabilities let producerTransport let consumerTransport let producer let consumer +let originAssetId +let originAssetName +let originAssetTypeName // https://mediasoup.org/documentation/v3/mediasoup-client/api/#ProducerOptions // https://mediasoup.org/documentation/v3/mediasoup-client/api/#transport-produce @@ -80,18 +109,19 @@ let params = { } } -const streamSuccess = async (stream) => { +const streamSuccess = (stream) => { localVideo.srcObject = stream const track = stream.getVideoTracks()[0] params = { track, ...params } + + goConnect() } const getLocalStream = () => { - - navigator.getUserMedia({ + navigator.mediaDevices.getUserMedia({ audio: false, video: { width: { @@ -103,11 +133,21 @@ const getLocalStream = () => { max: 1080, } } - }, streamSuccess, error => { + }) + .then(streamSuccess) + .catch(error => { console.log(error.message) }) } +const goConnect = () => { + device === undefined ? getRtpCapabilities() : goCreateTransport() +} + +const goCreateTransport = () => { + IS_PRODUCER ? createSendTransport() : createRecvTransport() +} + // A device is an endpoint connecting to a Router on the // server side to send/recive media const createDevice = async () => { @@ -121,7 +161,10 @@ const createDevice = async () => { routerRtpCapabilities: rtpCapabilities }) - console.log('RTP Capabilities', device.rtpCapabilities) + console.log('Device RTP Capabilities', device.rtpCapabilities) + + // once the device loads, create transport + goCreateTransport() } catch (error) { console.log(error) @@ -134,19 +177,22 @@ const getRtpCapabilities = () => { // make a request to the server for Router RTP Capabilities // see server's socket.on('getRtpCapabilities', ...) // the server sends back data object which contains rtpCapabilities - mediasoup.emit('getRtpCapabilities', (data) => { + socket.emit('createRoom', { callId }, (data) => { console.log(`Router RTP Capabilities... ${data.rtpCapabilities}`) // we assign to local variable and will be used when // loading the client Device (see createDevice above) rtpCapabilities = data.rtpCapabilities + + // once we have rtpCapabilities from the Router, create Device + createDevice() }) } const createSendTransport = () => { // see server's socket.on('createWebRtcTransport', sender?, ...) // this is a call from Producer, so sender = true - mediasoup.emit('createWebRtcTransport', { sender: true }, ({ params }) => { + socket.emit('createWebRtcTransport', { sender: true, callId }, ({ params }) => { // The server sends back params needed // to create Send Transport on the client side if (params.error) { @@ -168,7 +214,7 @@ const createSendTransport = () => { try { // Signal local DTLS parameters to the server side transport // see server's socket.on('transport-connect', ...) - await mediasoup.emit('transport-connect', { + await socket.emit('transport-connect', { dtlsParameters, }) @@ -188,7 +234,7 @@ const createSendTransport = () => { // with the following parameters and produce // and expect back a server side producer id // see server's socket.on('transport-produce', ...) - await mediasoup.emit('transport-produce', { + await socket.emit('transport-produce', { kind: parameters.kind, rtpParameters: parameters.rtpParameters, appData: parameters.appData, @@ -201,6 +247,8 @@ const createSendTransport = () => { errback(error) } }) + + connectSendTransport() }) } @@ -219,15 +267,32 @@ const connectSendTransport = async () => { producer.on('transportclose', () => { console.log('transport ended') - // close video track }) + + const answer = { + origin_asset_id: ASSET_ID, + dest_asset_id: originAssetId, + type: 'notify-answer', + origin_asset_priority: 1, + origin_asset_type_name: originAssetTypeName, + origin_asset_name: originAssetName, + video_call_id: callId, + answer: 'accepted', // answer: 'rejected' + }; + console.log('SEND answer', answer); + + hub.emit( + 'video', + JSON.stringify(answer) + ); } const createRecvTransport = async () => { + console.log('createRecvTransport'); // see server's socket.on('consume', sender?, ...) // this is a call from Consumer, so sender = false - await mediasoup.emit('createWebRtcTransport', { sender: false }, ({ params }) => { + await socket.emit('createWebRtcTransport', { sender: false, callId }, ({ params }) => { // The server sends back params needed // to create Send Transport on the client side if (params.error) { @@ -249,7 +314,7 @@ const createRecvTransport = async () => { try { // Signal local DTLS parameters to the server side transport // see server's socket.on('transport-recv-connect', ...) - await mediasoup.emit('transport-recv-connect', { + await socket.emit('transport-recv-connect', { dtlsParameters, }) @@ -260,6 +325,8 @@ const createRecvTransport = async () => { errback(error) } }) + + connectRecvTransport() }) } @@ -268,15 +335,16 @@ const connectRecvTransport = async () => { // for consumer, we need to tell the server first // to create a consumer based on the rtpCapabilities and consume // if the router can consume, it will send back a set of params as below - await mediasoup.emit('consume', { + await socket.emit('consume', { rtpCapabilities: device.rtpCapabilities, + callId }, async ({ params }) => { if (params.error) { console.log('Cannot Consume') return } - console.log('params', params) + console.log(params) // then consume with the local consumer transport // which creates a consumer consumer = await consumerTransport.consume({ @@ -289,19 +357,15 @@ const connectRecvTransport = async () => { // destructure and retrieve the video track from the producer const { track } = consumer - remoteVideo.srcObject = new MediaStream([track]) + const stream = new MediaStream([track]) + remoteVideo.srcObject = stream // the server consumer started with media paused // so we need to inform the server to resume - console.log('consumer-resume'); - mediasoup.emit('consumer-resume') + socket.emit('consumer-resume') + console.log('consumer', consumer); }) } btnLocalVideo.addEventListener('click', getLocalStream) -btnRtpCapabilities.addEventListener('click', getRtpCapabilities) -btnDevice.addEventListener('click', createDevice) -btnCreateSendTransport.addEventListener('click', createSendTransport) -btnConnectSendTransport.addEventListener('click', connectSendTransport) -btnRecvSendTransport.addEventListener('click', createRecvTransport) -btnConnectRecvTransport.addEventListener('click', connectRecvTransport) \ No newline at end of file +btnRecvSendTransport.addEventListener('click', goConnect) \ No newline at end of file