From 79d20bfac0d704010e439d9a4d3301f6bf5800e5 Mon Sep 17 00:00:00 2001 From: bustardcelly Date: Thu, 12 Jul 2018 18:26:11 +0200 Subject: [PATCH 01/16] adding webhook tests. --- package.json | 2 +- .../README.md | 125 ++++++++ .../index.html | 39 +++ .../publishStreamManagerProxyWebhook/index.js | 227 +++++++++++++++ .../README.md | 132 +++++++++ .../index.html | 40 +++ .../index.js | 266 ++++++++++++++++++ src/page/testbed-menu-sm-webhook.html | 23 ++ src/page/testbed-menu-sm.html | 1 + 9 files changed, 854 insertions(+), 1 deletion(-) create mode 100644 src/page/sm-webhook-test/publishStreamManagerProxyWebhook/README.md create mode 100644 src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.html create mode 100644 src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.js create mode 100644 src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/README.md create mode 100644 src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.html create mode 100644 src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.js create mode 100644 src/page/testbed-menu-sm-webhook.html diff --git a/package.json b/package.json index b7ccf5de..790b8279 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "red5pro-html-sdk-testbed", - "version": "5.0.0", + "version": "5.1.0", "description": "Testbed examples for Red5 Pro HTML SDK", "main": "src/js/index.js", "repository": { diff --git a/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/README.md b/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/README.md new file mode 100644 index 00000000..88c8a7ab --- /dev/null +++ b/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/README.md @@ -0,0 +1,125 @@ +# Publishing RTC Streams over stream manager proxy + +The streammanager WebRTC proxy is a communication layer built inside streammanager web application which allows it to act as a proxy gateway for webrtc publishers / subscribers. The target use case of this communication layer is to facilitate a secure browser client to be able to connect to a "unsecure" remote websocket endpoint for consuming WebRTC services offered by Red5pro. + +Streammanager autoscaling works with dynamic nodes which are associated with dynamic IP addresses and cannot have a SSL attached to them. The proxy layer helps publishers to connect and initiate a WebRTC publish session from a `secure` (ssl enabled) domain to a `unsecure` Red5pro origin having using an IP address. + + +**Please refer to the [Basic Publisher Documentation](../publish/README.md) to learn more about the basic setup.** + +> In order to properly run the Stream Manager examples, you will need to configure you server for cluster infrastructure as described in the following documentation: [https://www.red5pro.com/docs/server/autoscale/](https://www.red5pro.com/docs/server/autoscale/). + +> You also need to ensure that the stream manager proxy layer is `enabled`. The configuration section can be found in stream manager's config file - `red5-web.properties` + +` +## WEBSOCKET PROXY SECTION +proxy.enabled=false +` + +## Example Code + +- **[index.html](index.html)** +- **[index.js](index.js)** + +## Setup + +In order to publish, you first need to connect to the Stream Manager. The Stream Manager knows which origins are valid (part of a cluster) & available for publishing. + +```js + +function requestOrigin (configuration) { + var host = configuration.host; + var app = configuration.app; + var proxy = configuration.proxy; + var streamName = configuration.stream1; + var port = serverSettings.httpport.toString(); + var portURI = (port.length > 0 ? ':' + port : ''); + var baseUrl = isSecure ? protocol + '://' + host : protocol + '://' + host + portURI; + var apiVersion = configuration.streamManagerAPI || '2.0'; + var url = baseUrl + '/streammanager/api/' + apiVersion + '/event/' + app + '/' + streamName + '?action=broadcast'; + return new Promise(function (resolve, reject) { + fetch(url) + .then(function (res) { + if (res.headers.get("content-type") && + res.headers.get("content-type").toLowerCase().indexOf("application/json") >= 0) { + return res.json(); + } + else { + throw new TypeError('Could not properly parse response.'); + } + }) + .then(function (json) { + resolve(json.serverAddress); + }) + .catch(function (error) { + var jsonError = typeof error === 'string' ? error : JSON.stringify(error, null, 2) + console.error('[PublisherStreamManagerTest] :: Error - Could not request Origin IP from Stream Manager. ' + jsonError) + reject(error) + }); + }); +} +``` + +[index.js #80](index.js#L80) + +The service returns a JSON object. In particular to note is the `serverAddress` attribute which will be the IP of the Origin server. + +``` + "name": "", + "scope": "", + "serverAddress": "", + "region": "" +} +``` + +Next we construct the configuration object for the publisher per supported protocol. Note that the `proxy` usage is applicable for `rtc` only. The origin address is set directly as host for `rtmp` publisher where as it is passed in through `connectionParams` for `rtc`. + +Another important to note is that for `rtc` publisher the target application is the proxy - the `streammanager` webapp and not the app that you want to publish to. The rtc configuration passes the actual target application name in `connectionParams` as `app`. + +``` +function determinePublisher (serverAddress) { + var config = Object.assign({}, + configuration, + defaultConfiguration, + getUserMediaConfiguration()); + var rtcConfig = Object.assign({}, config, { + protocol: getSocketLocationFromProtocol().protocol, + port: getSocketLocationFromProtocol().port, + streamName: config.stream1, + streamType: 'webrtc', + app: configuration.proxy, + connectionParams: { + host: serverAddress, + app: configuration.app + } + }); + var rtmpConfig = Object.assign({}, config, { + host: serverAddress, + protocol: 'rtmp', + port: serverSettings.rtmpport, + streamName: config.stream1, + swf: '../../lib/red5pro/red5pro-publisher.swf', + swfobjectURL: '../../lib/swfobject/swfobject.js', + productInstallURL: '../../lib/swfobject/playerProductInstall.swf', + mediaConstraint: { + video: { + width: config.cameraWidth, + height: config.cameraHeight, + } + } + }); + var publishOrder = config.publisherFailoverOrder + .split(',') + .map(function (item) { + return item.trim() + }); + + return PublisherBase.determinePublisher({ + rtc: rtcConfig, + rtmp: rtmpConfig + }, publishOrder); + } +``` + +[index.js #120](index.js#L120) + diff --git a/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.html b/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.html new file mode 100644 index 00000000..23163b73 --- /dev/null +++ b/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.html @@ -0,0 +1,39 @@ + + + + {{> meta title='Publish Stream Manager Proxy Test'}} + {{> header-scripts}} + {{> header-stylesheets}} + + + +
+ {{> version }} + {{> settings-link}} +
+
+

In order to properly run the Stream Manager examples, you will need to configure you server for cluster infrastructure as described in the following documentation:

+

https://www.red5pro.com/docs/server/autoscale/

+

Additionally to use this example stream manager proxy gateway should be enabled.

+
+
+ {{> test-info testTitle='Publish SM Proxy Webhook Test'}} + {{> status-field-publisher}} + {{> statistics-field}} +

Origin Address: N/A

+
+ +
+
+ + + {{> body-scripts}} + + + + diff --git a/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.js b/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.js new file mode 100644 index 00000000..5070483c --- /dev/null +++ b/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.js @@ -0,0 +1,227 @@ +(function(window, document, red5prosdk, sm_ext) { + 'use strict'; + + var serverSettings = (function() { + var settings = sessionStorage.getItem('r5proServerSettings'); + try { + return JSON.parse(settings); + } + catch (e) { + console.error('Could not read server settings from sessionstorage: ' + e.message); + } + return {}; + })(); + + var configuration = (function () { + var conf = sessionStorage.getItem('r5proTestBed'); + try { + return JSON.parse(conf); + } + catch (e) { + console.error('Could not read testbed configuration from sessionstorage: ' + e.message); + } + return {} + })(); + red5prosdk.setLogLevel(configuration.verboseLogging ? red5prosdk.LOG_LEVELS.TRACE : red5prosdk.LOG_LEVELS.WARN); + + // Stream Manager Extension Lib. + sm_ext.setLogLevel(configuration.verboseLogging ? red5prosdk.LOG_LEVELS.TRACE : red5prosdk.LOG_LEVELS.WARN); + // Extend the Red5Pro sdk. + sm_ext.decorate(); + + var targetPublisher; + + var updateStatusFromEvent = window.red5proHandlePublisherEvent; // defined in src/template/partial/status-field-publisher.hbs + var streamTitle = document.getElementById('stream-title'); + var statisticsField = document.getElementById('statistics-field'); + var addressField = document.getElementById('address-field'); + + var protocol = serverSettings.protocol; + var isSecure = protocol == 'https'; + function getSocketLocationFromProtocol () { + return !isSecure + ? {protocol: 'ws', port: serverSettings.wsport} + : {protocol: 'wss', port: serverSettings.wssport}; + } + + var defaultConfiguration = { + protocol: getSocketLocationFromProtocol().protocol, + port: getSocketLocationFromProtocol().port + }; + + function displayServerAddress (serverAddress, proxyAddress) + { + proxyAddress = (typeof proxyAddress === 'undefined') ? 'N/A' : proxyAddress; + addressField.innerText = ' Proxy Address: ' + proxyAddress + ' | ' + ' Origin Address: ' + serverAddress; + } + + function onBitrateUpdate (bitrate, packetsSent) { + statisticsField.innerText = 'Bitrate: ' + Math.floor(bitrate) + '. Packets Sent: ' + packetsSent + '.'; + } + + function onPublisherEvent (event) { + console.log('[Red5ProPublisher] ' + event.type + '.'); + updateStatusFromEvent(event); + } + function onPublishFail (message) { + console.error('[Red5ProPublisher] Publish Error :: ' + message); + } + function onPublishSuccess (publisher) { + console.log('[Red5ProPublisher] Publish Complete.'); + try { + window.trackBitrate(publisher.getPeerConnection(), onBitrateUpdate); + } + catch (e) { + // + } + } + function onUnpublishFail (message) { + console.error('[Red5ProPublisher] Unpublish Error :: ' + message); + } + function onUnpublishSuccess () { + console.log('[Red5ProPublisher] Unpublish Complete.'); + } + + function getUserMediaConfiguration () { + return { + mediaConstraints: { + audio: configuration.useAudio ? configuration.mediaConstraints.audio : false, + video: configuration.useVideo ? configuration.mediaConstraints.video : false + } + }; + } + + function getRTMPMediaConfiguration () { + return { + mediaConstraints: { + audio: configuration.useAudio ? configuration.mediaConstraints.audio : false, + video: configuration.useVideo ? { + width: configuration.cameraWidth, + height: configuration.cameraHeight + } : false + } + } + } + + function determinePublisher () { + + var autoscaleConfig = { + protocol: protocol, + host: configuration.host, + streamName: configuration.stream1, + scope: configuration.app, + apiVersion: configuration.streamManagerAPI || '3.0', + action: 'broadcast', + useProxy: true, + retryLimit: 3, + accessToken: configuration.streamManagerAccessToken + }; + + var config = Object.assign({}, + configuration, + defaultConfiguration, + getUserMediaConfiguration()); + var rtcConfig = Object.assign({}, config, { + protocol: getSocketLocationFromProtocol().protocol, + port: getSocketLocationFromProtocol().port, + host: configuration.host, + streamName: configuration.stream1 + }); + var rtmpConfig = Object.assign({}, config, { + host: configuration.host, + app: configuration.app, + protocol: 'rtmp', + port: serverSettings.rtmpport, + streamName: configuration.stream1, + backgroundColor: '#000000', + swf: '../../lib/red5pro/red5pro-publisher.swf', + swfobjectURL: '../../lib/swfobject/swfobject.js', + productInstallURL: '../../lib/swfobject/playerProductInstall.swf' + }, getRTMPMediaConfiguration()); + + var publishOrder = config.publisherFailoverOrder + .split(',') + .map(function (item) { + return item.trim() + }); + + if(window.query('view')) { + publishOrder = [window.query('view')]; + } + + // call the `autoscale` method now + // declared on publisher and subscriber refs. + return new red5prosdk.Red5ProPublisher() + .setPublishOrder(publishOrder) + .autoscale(autoscaleConfig, { + rtc: rtcConfig, + rtmp: rtmpConfig + }); + } + + function showAddress (publisher) { + var config = publisher.getOptions(); + console.log("Host = " + config.host + " | " + "app = " + config.app); + if (publisher.getType().toLowerCase() === 'rtc') { + displayServerAddress(config.connectionParams.host, config.host); + console.log("Using streammanager proxy for rtc"); + console.log("Proxy target = " + config.connectionParams.host + " | " + "Proxy app = " + config.connectionParams.app) + if(isSecure) { + console.log("Operating over secure connection | protocol: " + config.protocol + " | port: " + config.port); + } + else { + console.log("Operating over unsecure connection | protocol: " + config.protocol + " | port: " + config.port); + } + } + else { + displayServerAddress(config.host); + } + } + + function unpublish () { + return new Promise(function (resolve, reject) { + var publisher = targetPublisher; + publisher.unpublish() + .then(function () { + onUnpublishSuccess(); + resolve(); + }) + .catch(function (error) { + var jsonError = typeof error === 'string' ? error : JSON.stringify(error, 2, null); + onUnpublishFail('Unmount Error ' + jsonError); + reject(error); + }); + }); + } + + determinePublisher() + .then(function (publisherImpl) { + streamTitle.innerText = configuration.stream1; + targetPublisher = publisherImpl; + targetPublisher.on('*', onPublisherEvent); + showAddress(targetPublisher); + return targetPublisher.publish(); + }) + .then(function () { + onPublishSuccess(targetPublisher); + }) + .catch(function (error) { + var jsonError = typeof error === 'string' ? error : JSON.stringify(error, null, 2); + console.error('[Red5ProPublisher] :: Error in access of Origin IP: ' + jsonError); + updateStatusFromEvent({ + type: red5prosdk.PublisherEventTypes.CONNECT_FAILURE + }); + onPublishFail(jsonError); + }); + + window.addEventListener('beforeunload', function() { + function clearRefs () { + if (targetPublisher) { + targetPublisher.off('*', onPublisherEvent); + } + targetPublisher = undefined; + } + unpublish().then(clearRefs).catch(clearRefs); + window.untrackBitrate(); + }); +})(this, document, window.red5prosdk, window.red5prosdk_ext_stream_manager); diff --git a/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/README.md b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/README.md new file mode 100644 index 00000000..e5201f79 --- /dev/null +++ b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/README.md @@ -0,0 +1,132 @@ +# Subscribing RTC Streams over stream manager proxy + +The streammanager WebRTC proxy is a communication layer built inside streammanager web application which allows it to act as a proxy gateway for webrtc publishers / subscribers. The target use case of this communication layer is to facilitate a secure browser client to be able to connect to a "unsecure" remote websocket endpoint for consuming WebRTC services offered by Red5pro. + +Streammanager autoscaling works with dynamic nodes which are associated with dynamic IP addresses and cannot have a SSL attached to them. The proxy layer helps subscribers to connect and initiate a WebRTC `subscribe` session from a `secure` (ssl enabled) domain to a `unsecure` Red5pro origin having using an IP address. + +**Please refer to the [Basic Subscriber Documentation](../subscribe/README.md) to learn more about the basic setup.** + +> In order to properly run the Stream Manager examples, you will need to configure you server for cluster infrastructure as described in the following documentation: [https://www.red5pro.com/docs/server/autoscale/](https://www.red5pro.com/docs/server/autoscale/). + +> You also need to ensure that the stream manager proxy layer is `enabled`. The configuration section can be found in stream manager's config file - `red5-web.properties` + +```sh +## WEBSOCKET PROXY SECTION +proxy.enabled=false +``` + +## Example Code +- **[index.html](index.html)** +- **[index.js](index.js)** + +# Setup + +In order to subscribe, you first need to connect to the Stream Manager. The Stream Manager will know which origin is being used for the stream and accordingly will provide with an usable edge to consume the stream. + +```js +function requestEdge (configuration) { + var host = configuration.host; + var app = configuration.app; + var port = serverSettings.httpport.toString(); + var portURI = (port.length > 0 ? ':' + port : ''); + var baseUrl = isSecure ? protocol + '://' + host : protocol + '://' + host + portURI; + var streamName = configuration.stream1; + var apiVersion = configuration.streamManagerAPI || '2.0'; + var url = baseUrl + '/streammanager/api/' + apiVersion + '/event/' + app + '/' + streamName + '?action=subscribe'; + return new Promise(function (resolve, reject) { + fetch(url) + .then(function (res) { + if (res.headers.get("content-type") && + res.headers.get("content-type").toLowerCase().indexOf("application/json") >= 0) { + return res.json(); + } + else { + throw new TypeError('Could not properly parse response.'); + } + }) + .then(function (json) { + resolve(json.serverAddress); + }) + .catch(function (error) { + var jsonError = typeof error === 'string' ? error : JSON.stringify(error, null, 2) + console.error('[SubscribeStreamManagerTest] :: Error - Could not request Edge IP from Stream Manager. ' + jsonError) + reject(error) + }); + }); +} +``` + +[index.js #95](index.js#L95) + +The service returns a JSON object. In particular to note is the `serverAddress` attribute which will be the IP of the Edge server. + +```js + "name": "", + "scope": "", + "serverAddress": "", + "region": "" +} +``` + +Next we construct the configuration objects for the subscriber per supported protocol. Note that the proxy usage is applicable for `rtc` only. The edge address is set directly as host for `rtmp` or `hls` subscriber configuration, whereas it is passed in through connectionParams for `rtc`. + +Another important to note is that for `rtc` subscriber the target application is the `proxy` - the `streammanager` webapp and not the app that you want to subscribe to. The `rtc` configuration passes the actual target application name in connectionParams as `app`. + +```js +function determineSubscriber (serverAddress) { + var config = Object.assign({}, configuration, defaultConfiguration); + var rtcConfig = Object.assign({}, config, { + host: configuration.host, + protocol: getSocketLocationFromProtocol().protocol, + port: getSocketLocationFromProtocol().port, + app: configuration.proxy, + connectionParams: { + host: serverAddress, + app: configuration.app + }, + subscriptionId: 'subscriber-' + instanceId, + streamName: config.stream1 + }) + var rtmpConfig = Object.assign({}, config, { + host: serverAddress, + protocol: 'rtmp', + port: serverSettings.rtmpport, + streamName: config.stream1, + mimeType: 'rtmp/flv', + useVideoJS: false, + width: config.cameraWidth, + height: config.cameraHeight, + swf: '../../lib/red5pro/red5pro-subscriber.swf', + swfobjectURL: '../../lib/swfobject/swfobject.js', + productInstallURL: '../../lib/swfobject/playerProductInstall.swf' + }) + var hlsConfig = Object.assign({}, config, { + host: serverAddress, + protocol: protocol, + port: isSecure ? serverSettings.hlssport : serverSettings.hlsport, + streamName: config.stream1, + mimeType: 'application/x-mpegURL' + }) + + if (!config.useVideo) { + rtcConfig.videoEncoding = 'NONE'; + } + if (!config.useAudio) { + rtcConfig.audioEncoding = 'NONE'; + } + + var subscribeOrder = config.subscriberFailoverOrder + .split(',').map(function (item) { + return item.trim(); + }); + + return SubscriberBase.determineSubscriber({ + rtc: rtcConfig, + rtmp: rtmpConfig, + hls: hlsConfig + }, subscribeOrder); + } +``` + +[index.js #126](index.js#L126) + diff --git a/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.html b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.html new file mode 100644 index 00000000..68f7a5ed --- /dev/null +++ b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.html @@ -0,0 +1,40 @@ + + + + {{> meta title='Subscriber Stream Manager Proxy Test'}} + {{> header-scripts}} + {{> header-stylesheets}} + + + +
+ {{> version }} + {{> settings-link}} +
+
+

In order to properly run the Stream Manager examples, you will need to configure you server for cluster infrastructure as described in the following documentation:

+

https://www.red5pro.com/docs/server/autoscale/

+

Additionally to use this example stream manager proxy gateway should be enabled.

+
+
+ {{> test-info testTitle='Subscriber SM Webhook Test'}} + {{> status-field-subscriber}} + {{> statistics-field}} +

Edge Address: N/A

+
+ +
+
+ {{> body-scripts}} + + + diff --git a/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.js b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.js new file mode 100644 index 00000000..9a5aff29 --- /dev/null +++ b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.js @@ -0,0 +1,266 @@ +(function(window, document, red5prosdk, sm_ext) { + 'use strict'; + + var serverSettings = (function() { + var settings = sessionStorage.getItem('r5proServerSettings'); + try { + return JSON.parse(settings); + } + catch (e) { + console.error('Could not read server settings from sessionstorage: ' + e.message); + } + return {}; + })(); + + var configuration = (function () { + var conf = sessionStorage.getItem('r5proTestBed'); + try { + return JSON.parse(conf); + } + catch (e) { + console.error('Could not read testbed configuration from sessionstorage: ' + e.message); + } + return {} + })(); + red5prosdk.setLogLevel(configuration.verboseLogging ? red5prosdk.LOG_LEVELS.TRACE : red5prosdk.LOG_LEVELS.WARN); + // Stream Manager Extension Lib. + sm_ext.setLogLevel(configuration.verboseLogging ? red5prosdk.LOG_LEVELS.TRACE : red5prosdk.LOG_LEVELS.WARN); + // Extend the Red5Pro sdk. + sm_ext.decorate(); + + var targetSubscriber; + + var updateStatusFromEvent = function (event) { + var subTypes = red5prosdk.SubscriberEventTypes; + switch (event.type) { + case subTypes.CONNECT_FAILURE: + case subTypes.SUBSCRIBE_FAIL: + shutdownVideoElement(); + break; + } + window.red5proHandleSubscriberEvent(event); // defined in src/template/partial/status-field-subscriber.hbs + }; + var instanceId = Math.floor(Math.random() * 0x10000).toString(16); + var streamTitle = document.getElementById('stream-title'); + var statisticsField = document.getElementById('statistics-field'); + var addressField = document.getElementById('address-field'); + var protocol = serverSettings.protocol; + var isSecure = protocol === 'https'; + + var bitrate = 0; + var packetsReceived = 0; + var frameWidth = 0; + var frameHeight = 0; + function updateStatistics (b, p, w, h) { + statisticsField.innerText = 'Bitrate: ' + Math.floor(b) + '. Packets Received: ' + p + '.' + ' Resolution: ' + w + ', ' + h + '.'; + } + + function onBitrateUpdate (b, p) { + bitrate = b; + packetsReceived = p; + updateStatistics(bitrate, packetsReceived, frameWidth, frameHeight); + } + + function onResolutionUpdate (w, h) { + frameWidth = w; + frameHeight = h; + updateStatistics(bitrate, packetsReceived, frameWidth, frameHeight); + } + + function getSocketLocationFromProtocol () { + return !isSecure + ? {protocol: 'ws', port: serverSettings.wsport} + : {protocol: 'wss', port: serverSettings.wssport}; + } + + var defaultConfiguration = (function(useVideo, useAudio) { + var c = { + protocol: getSocketLocationFromProtocol().protocol, + port: getSocketLocationFromProtocol().port + }; + if (!useVideo) { + c.videoEncoding = red5prosdk.PlaybackVideoEncoder.NONE; + } + if (!useAudio) { + c.audioEncoding = red5prosdk.PlaybackAudioEncoder.NONE; + } + return c; + })(configuration.useVideo, configuration.useAudio); + + function shutdownVideoElement () { + var videoElement = document.getElementById('red5pro-subscriber'); + if (videoElement) { + videoElement.pause() + videoElement.src = '' + } + } + + function displayServerAddress (serverAddress, proxyAddress) { + proxyAddress = (typeof proxyAddress === 'undefined') ? 'N/A' : proxyAddress; + addressField.innerText = ' Proxy Address: ' + proxyAddress + ' | ' + ' Edge Address: ' + serverAddress; + } + + // Local lifecycle notifications. + function onSubscriberEvent (event) { + console.log('[Red5ProSubsriber] ' + event.type + '.'); + updateStatusFromEvent(event); + } + function onSubscribeFail (message) { + console.error('[Red5ProSubsriber] Subscribe Error :: ' + message); + } + function onSubscribeSuccess (subscriber) { + console.log('[Red5ProSubsriber] Subscribe Complete.'); + if (subscriber.getType().toLowerCase() === 'rtc') { + try { + window.trackBitrate(subscriber.getPeerConnection(), onBitrateUpdate, onResolutionUpdate); + } + catch (e) { + // + } + } + } + function onUnsubscribeFail (message) { + console.error('[Red5ProSubsriber] Unsubscribe Error :: ' + message); + } + function onUnsubscribeSuccess () { + console.log('[Red5ProSubsriber] Unsubscribe Complete.'); + } + + function determineSubscriber () { + + var config = Object.assign({}, configuration, defaultConfiguration); + var autoscaleConfig = { + protocol: protocol, + host: configuration.host, + streamName: configuration.stream1, + scope: configuration.app, + apiVersion: configuration.streamManagerAPI || '3.0', + action: 'subscribe', + useProxy: true, + retryLimit: 3, + accessToken: configuration.streamManagerAccessToken + }; + + var rtcConfig = Object.assign({}, config, { + host: configuration.host, + protocol: getSocketLocationFromProtocol().protocol, + port: getSocketLocationFromProtocol().port, + subscriptionId: 'subscriber-' + instanceId, + streamName: configuration.stream1 + }) + var rtmpConfig = Object.assign({}, config, { + host: configuration.host, + app: configuration.app, + protocol: 'rtmp', + port: serverSettings.rtmpport, + streamName: configuration.stream1, + width: configuration.cameraWidth, + height: configuration.cameraHeight, + swf: '../../lib/red5pro/red5pro-subscriber.swf', + swfobjectURL: '../../lib/swfobject/swfobject.js', + productInstallURL: '../../lib/swfobject/playerProductInstall.swf' + }) + var hlsConfig = Object.assign({}, config, { + host: configuration.host, + app: configuration.app, + protocol: 'http', + port: serverSettings.hlsport, + streamName: configuration.stream1, + mimeType: 'application/x-mpegURL' + }) + + if (!config.useVideo) { + rtcConfig.videoEncoding = 'NONE'; + } + if (!config.useAudio) { + rtcConfig.audioEncoding = 'NONE'; + } + + var subscribeOrder = configuration.subscriberFailoverOrder + .split(',').map(function (item) { + return item.trim(); + }); + + if (window.query('view')) { + subscribeOrder = [window.query('view')]; + } + + return new red5prosdk.Red5ProSubscriber() + .setPlaybackOrder(subscribeOrder) + .autoscale(autoscaleConfig, { + rtc: rtcConfig, + rtmp: rtmpConfig, + hls: hlsConfig + }); + } + + function showServerAddress (subscriber) { + var config = subscriber.getOptions(); + console.log("Host = " + config.host + " | " + "app = " + config.app); + if (subscriber.getType().toLowerCase() === 'rtc') { + displayServerAddress(config.connectionParams.host, config.host); + console.log("Using streammanager proxy for rtc"); + console.log("Proxy target = " + config.connectionParams.host + " | " + "Proxy app = " + config.connectionParams.app) + if(isSecure) { + console.log("Operating over secure connection | protocol: " + config.protocol + " | port: " + config.port); + } + else { + console.log("Operating over unsecure connection | protocol: " + config.protocol + " | port: " + config.port); + } + } + else { + displayServerAddress(config.host); + } + } + + // Request to unsubscribe. + function unsubscribe () { + return new Promise(function(resolve, reject) { + var subscriber = targetSubscriber + subscriber.unsubscribe() + .then(function () { + targetSubscriber.off('*', onSubscriberEvent); + targetSubscriber = undefined; + onUnsubscribeSuccess(); + resolve(); + }) + .catch(function (error) { + var jsonError = typeof error === 'string' ? error : JSON.stringify(error, null, 2); + onUnsubscribeFail(jsonError); + reject(error); + }); + }); + } + + determineSubscriber() + .then(function (subscriberImpl) { + streamTitle.innerText = configuration.stream1; + targetSubscriber = subscriberImpl; + // Subscribe to events. + targetSubscriber.on('*', onSubscriberEvent); + showServerAddress(targetSubscriber); + return targetSubscriber.subscribe(); + }) + .then(function (sub) { + onSubscribeSuccess(sub); + }) + .catch(function (error) { + var jsonError = typeof error === 'string' ? error : JSON.stringify(error, null, 2); + console.error('[Red5ProSubscriber] :: Error in subscribing - ' + jsonError); + onSubscribeFail(jsonError); + }); + + // Clean up. + window.addEventListener('beforeunload', function() { + function clearRefs () { + if (targetSubscriber) { + targetSubscriber.off('*', onSubscriberEvent); + } + targetSubscriber = undefined; + } + unsubscribe().then(clearRefs).catch(clearRefs); + window.untrackbitrate(); + }); + +})(this, document, window.red5prosdk); + diff --git a/src/page/testbed-menu-sm-webhook.html b/src/page/testbed-menu-sm-webhook.html new file mode 100644 index 00000000..1d570c8e --- /dev/null +++ b/src/page/testbed-menu-sm-webhook.html @@ -0,0 +1,23 @@ + + + + {{> meta title='Red5 Pro HTML SDK Testbed'}} + + + + + + + + diff --git a/src/page/testbed-menu-sm.html b/src/page/testbed-menu-sm.html index aa984056..ba1df9a9 100644 --- a/src/page/testbed-menu-sm.html +++ b/src/page/testbed-menu-sm.html @@ -14,6 +14,7 @@

Red5 Pro HTML Testbed


  • Non-Stream Manager Tests
  • +
  • Webhook & Stream Manager Tests
  • Publish - Stream Manager
  • Publish - Stream Manager Proxy
  • Publish - Stream Manager Proxy w/ Settings (RTC)
  • From 0249a7305805e205a56a0a19fc31b92c1b24539c Mon Sep 17 00:00:00 2001 From: bustardcelly Date: Thu, 12 Jul 2018 19:51:49 +0200 Subject: [PATCH 02/16] fixes once tested live. --- .../index.html | 2 +- .../index.html | 2 + .../index.js | 3 +- .../red5pro/red5pro-ext-stream-manager.min.js | 422 +----------------- 4 files changed, 7 insertions(+), 422 deletions(-) diff --git a/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.html b/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.html index 23163b73..3280e6ca 100644 --- a/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.html +++ b/src/page/sm-webhook-test/publishStreamManagerProxyWebhook/index.html @@ -31,7 +31,7 @@ - + {{> body-scripts}} diff --git a/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.html b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.html index 68f7a5ed..977fd4dc 100644 --- a/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.html +++ b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.html @@ -35,6 +35,8 @@ {{> body-scripts}} + + diff --git a/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.js b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.js index 9a5aff29..0d03610c 100644 --- a/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.js +++ b/src/page/sm-webhook-test/subscribeStreamManagerProxyWebhook/index.js @@ -262,5 +262,4 @@ window.untrackbitrate(); }); -})(this, document, window.red5prosdk); - +})(this, document, window.red5prosdk, window.red5prosdk_ext_stream_manager); diff --git a/static/lib/red5pro/red5pro-ext-stream-manager.min.js b/static/lib/red5pro/red5pro-ext-stream-manager.min.js index de0bee64..9770e08e 100644 --- a/static/lib/red5pro/red5pro-ext-stream-manager.min.js +++ b/static/lib/red5pro/red5pro-ext-stream-manager.min.js @@ -2,424 +2,8 @@ * * red5pro-extension-stream-manager - Library extension for Stream Manager support * Author: Infrared5 Inc. - * Version: 1.0.2 - * Url: undefined + * Version: 1.0.3 + * Url: https://github.com/infrared5/red5pro-extension-stream-manager#README.md * */ -!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.red5prosdk_ext_stream_manager=r():e.red5prosdk_ext_stream_manager=r()}(window,function(){return function(e){var r={};function o(t){if(r[t])return r[t].exports;var s=r[t]={i:t,l:!1,exports:{}};return e[t].call(s.exports,s,s.exports,o),s.l=!0,s.exports}return o.m=e,o.c=r,o.d=function(e,r,t){o.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,r){if(1&r&&(e=o(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(o.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var s in e)o.d(t,s,function(r){return e[r]}.bind(null,s));return t},o.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(r,"a",r),r},o.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},o.p="",o(o.s=0)}({"./node_modules/babel-runtime/core-js/json/stringify.js": -/*!**************************************************************!*\ - !*** ./node_modules/babel-runtime/core-js/json/stringify.js ***! - \**************************************************************/ -/*! no static exports found */function(e,r,o){e.exports={default:o(/*! core-js/library/fn/json/stringify */"./node_modules/core-js/library/fn/json/stringify.js"),__esModule:!0}},"./node_modules/babel-runtime/core-js/object/assign.js": -/*!*************************************************************!*\ - !*** ./node_modules/babel-runtime/core-js/object/assign.js ***! - \*************************************************************/ -/*! no static exports found */function(e,r,o){e.exports={default:o(/*! core-js/library/fn/object/assign */"./node_modules/core-js/library/fn/object/assign.js"),__esModule:!0}},"./node_modules/babel-runtime/core-js/object/define-property.js": -/*!**********************************************************************!*\ - !*** ./node_modules/babel-runtime/core-js/object/define-property.js ***! - \**********************************************************************/ -/*! no static exports found */function(e,r,o){e.exports={default:o(/*! core-js/library/fn/object/define-property */"./node_modules/core-js/library/fn/object/define-property.js"),__esModule:!0}},"./node_modules/babel-runtime/core-js/object/keys.js": -/*!***********************************************************!*\ - !*** ./node_modules/babel-runtime/core-js/object/keys.js ***! - \***********************************************************/ -/*! no static exports found */function(e,r,o){e.exports={default:o(/*! core-js/library/fn/object/keys */"./node_modules/core-js/library/fn/object/keys.js"),__esModule:!0}},"./node_modules/babel-runtime/core-js/promise.js": -/*!*******************************************************!*\ - !*** ./node_modules/babel-runtime/core-js/promise.js ***! - \*******************************************************/ -/*! no static exports found */function(e,r,o){e.exports={default:o(/*! core-js/library/fn/promise */"./node_modules/core-js/library/fn/promise.js"),__esModule:!0}},"./node_modules/babel-runtime/helpers/asyncToGenerator.js": -/*!****************************************************************!*\ - !*** ./node_modules/babel-runtime/helpers/asyncToGenerator.js ***! - \****************************************************************/ -/*! no static exports found */function(e,r,o){"use strict";r.__esModule=!0;var t,s=o(/*! ../core-js/promise */"./node_modules/babel-runtime/core-js/promise.js"),n=(t=s)&&t.__esModule?t:{default:t};r.default=function(e){return function(){var r=e.apply(this,arguments);return new n.default(function(e,o){return function t(s,i){try{var l=r[s](i),a=l.value}catch(e){return void o(e)}if(!l.done)return n.default.resolve(a).then(function(e){t("next",e)},function(e){t("throw",e)});e(a)}("next")})}}},"./node_modules/babel-runtime/helpers/classCallCheck.js": -/*!**************************************************************!*\ - !*** ./node_modules/babel-runtime/helpers/classCallCheck.js ***! - \**************************************************************/ -/*! no static exports found */function(e,r,o){"use strict";r.__esModule=!0,r.default=function(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}},"./node_modules/babel-runtime/helpers/createClass.js": -/*!***********************************************************!*\ - !*** ./node_modules/babel-runtime/helpers/createClass.js ***! - \***********************************************************/ -/*! no static exports found */function(e,r,o){"use strict";r.__esModule=!0;var t,s=o(/*! ../core-js/object/define-property */"./node_modules/babel-runtime/core-js/object/define-property.js"),n=(t=s)&&t.__esModule?t:{default:t};r.default=function(){function e(e,r){for(var o=0;o=i)return e;switch(e){case"%s":return String(n[s++]);case"%d":return Number(n[s++]);case"%j":try{return JSON.stringify(n[s++])}catch(e){return"[Circular]"}default:return e}}),a=n[s];se||(s=function(s){var n;s[0]instanceof Error?(o={err:r.serializers&&r.serializers.err?r.serializers.err(s[0]):E.err(s[0])},n={err:!0},t=1===s.length?[o.err.message]:Array.prototype.slice.call(s,1)):"object"!=typeof s[0]&&null!==s[0]||Array.isArray(s[0])?(o=null,t=Array.prototype.slice.call(s)):(o=s[0],t=1===s.length&&o.err&&o.err instanceof Error?[o.err.message]:Array.prototype.slice.call(s,1));var i=m(r.fields);i.level=e;var l=o?m(o):null;if(l&&(r.serializers&&r._applySerializers(l,n),Object.keys(l).forEach(function(e){i[e]=l[e]})),i.levelName=c[e],i.msg=t.length?j.apply(r,t):"",i.time||(i.time=new Date),r.src&&!i.src)try{throw new Error(f)}catch(e){var a=function(e,r){var o=e.split("\n");o[0]&&o[0].indexOf(f)>=0&&o.shift();var t=o[r],s=null;if(t){var n=/^\s*(at|.*@)\s*(.+)?$/.exec(t);s=Array.isArray(n)&&n[2]?n[2]:t}return s}(e.stack,2);a||p.src||_("Unable to determine src line info","src"),i.src=a||""}return i.v=g,i}(t),this._emit(s))}}w.prototype.addStream=function(e,r){void 0===r&&(r=n),(e=m(e)).type="raw",e.level=d(e.level||r),e.levelc;)if((l=a[c++])!=l)return!0}else for(;u>c;c++)if((e||c in a)&&a[c]===o)return e||c||0;return!e&&-1}}},"./node_modules/core-js/library/modules/_classof.js": -/*!**********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_classof.js ***! - \**********************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_cof */"./node_modules/core-js/library/modules/_cof.js"),s=o(/*! ./_wks */"./node_modules/core-js/library/modules/_wks.js")("toStringTag"),n="Arguments"==t(function(){return arguments}());e.exports=function(e){var r,o,i;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(o=function(e,r){try{return e[r]}catch(e){}}(r=Object(e),s))?o:n?t(r):"Object"==(i=t(r))&&"function"==typeof r.callee?"Arguments":i}},"./node_modules/core-js/library/modules/_cof.js": -/*!******************************************************!*\ - !*** ./node_modules/core-js/library/modules/_cof.js ***! - \******************************************************/ -/*! no static exports found */function(e,r){var o={}.toString;e.exports=function(e){return o.call(e).slice(8,-1)}},"./node_modules/core-js/library/modules/_core.js": -/*!*******************************************************!*\ - !*** ./node_modules/core-js/library/modules/_core.js ***! - \*******************************************************/ -/*! no static exports found */function(e,r){var o=e.exports={version:"2.5.7"};"number"==typeof __e&&(__e=o)},"./node_modules/core-js/library/modules/_ctx.js": -/*!******************************************************!*\ - !*** ./node_modules/core-js/library/modules/_ctx.js ***! - \******************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_a-function */"./node_modules/core-js/library/modules/_a-function.js");e.exports=function(e,r,o){if(t(e),void 0===r)return e;switch(o){case 1:return function(o){return e.call(r,o)};case 2:return function(o,t){return e.call(r,o,t)};case 3:return function(o,t,s){return e.call(r,o,t,s)}}return function(){return e.apply(r,arguments)}}},"./node_modules/core-js/library/modules/_defined.js": -/*!**********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_defined.js ***! - \**********************************************************/ -/*! no static exports found */function(e,r){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},"./node_modules/core-js/library/modules/_descriptors.js": -/*!**************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_descriptors.js ***! - \**************************************************************/ -/*! no static exports found */function(e,r,o){e.exports=!o(/*! ./_fails */"./node_modules/core-js/library/modules/_fails.js")(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},"./node_modules/core-js/library/modules/_dom-create.js": -/*!*************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_dom-create.js ***! - \*************************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_is-object */"./node_modules/core-js/library/modules/_is-object.js"),s=o(/*! ./_global */"./node_modules/core-js/library/modules/_global.js").document,n=t(s)&&t(s.createElement);e.exports=function(e){return n?s.createElement(e):{}}},"./node_modules/core-js/library/modules/_enum-bug-keys.js": -/*!****************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_enum-bug-keys.js ***! - \****************************************************************/ -/*! no static exports found */function(e,r){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},"./node_modules/core-js/library/modules/_export.js": -/*!*********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_export.js ***! - \*********************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_global */"./node_modules/core-js/library/modules/_global.js"),s=o(/*! ./_core */"./node_modules/core-js/library/modules/_core.js"),n=o(/*! ./_ctx */"./node_modules/core-js/library/modules/_ctx.js"),i=o(/*! ./_hide */"./node_modules/core-js/library/modules/_hide.js"),l=o(/*! ./_has */"./node_modules/core-js/library/modules/_has.js"),a=function(e,r,o){var u,c,d,f=e&a.F,m=e&a.G,y=e&a.S,j=e&a.P,p=e&a.B,_=e&a.W,h=m?s:s[r]||(s[r]={}),b=h.prototype,v=m?t:y?t[r]:(t[r]||{}).prototype;for(u in m&&(o=r),o)(c=!f&&v&&void 0!==v[u])&&l(h,u)||(d=c?v[u]:o[u],h[u]=m&&"function"!=typeof v[u]?o[u]:p&&c?n(d,t):_&&v[u]==d?function(e){var r=function(r,o,t){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(r);case 2:return new e(r,o)}return new e(r,o,t)}return e.apply(this,arguments)};return r.prototype=e.prototype,r}(d):j&&"function"==typeof d?n(Function.call,d):d,j&&((h.virtual||(h.virtual={}))[u]=d,e&a.R&&b&&!b[u]&&i(b,u,d)))};a.F=1,a.G=2,a.S=4,a.P=8,a.B=16,a.W=32,a.U=64,a.R=128,e.exports=a},"./node_modules/core-js/library/modules/_fails.js": -/*!********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_fails.js ***! - \********************************************************/ -/*! no static exports found */function(e,r){e.exports=function(e){try{return!!e()}catch(e){return!0}}},"./node_modules/core-js/library/modules/_for-of.js": -/*!*********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_for-of.js ***! - \*********************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_ctx */"./node_modules/core-js/library/modules/_ctx.js"),s=o(/*! ./_iter-call */"./node_modules/core-js/library/modules/_iter-call.js"),n=o(/*! ./_is-array-iter */"./node_modules/core-js/library/modules/_is-array-iter.js"),i=o(/*! ./_an-object */"./node_modules/core-js/library/modules/_an-object.js"),l=o(/*! ./_to-length */"./node_modules/core-js/library/modules/_to-length.js"),a=o(/*! ./core.get-iterator-method */"./node_modules/core-js/library/modules/core.get-iterator-method.js"),u={},c={};(r=e.exports=function(e,r,o,d,f){var m,y,j,p,_=f?function(){return e}:a(e),h=t(o,d,r?2:1),b=0;if("function"!=typeof _)throw TypeError(e+" is not iterable!");if(n(_)){for(m=l(e.length);m>b;b++)if((p=r?h(i(y=e[b])[0],y[1]):h(e[b]))===u||p===c)return p}else for(j=_.call(e);!(y=j.next()).done;)if((p=s(j,h,y.value,r))===u||p===c)return p}).BREAK=u,r.RETURN=c},"./node_modules/core-js/library/modules/_global.js": -/*!*********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_global.js ***! - \*********************************************************/ -/*! no static exports found */function(e,r){var o=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=o)},"./node_modules/core-js/library/modules/_has.js": -/*!******************************************************!*\ - !*** ./node_modules/core-js/library/modules/_has.js ***! - \******************************************************/ -/*! no static exports found */function(e,r){var o={}.hasOwnProperty;e.exports=function(e,r){return o.call(e,r)}},"./node_modules/core-js/library/modules/_hide.js": -/*!*******************************************************!*\ - !*** ./node_modules/core-js/library/modules/_hide.js ***! - \*******************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_object-dp */"./node_modules/core-js/library/modules/_object-dp.js"),s=o(/*! ./_property-desc */"./node_modules/core-js/library/modules/_property-desc.js");e.exports=o(/*! ./_descriptors */"./node_modules/core-js/library/modules/_descriptors.js")?function(e,r,o){return t.f(e,r,s(1,o))}:function(e,r,o){return e[r]=o,e}},"./node_modules/core-js/library/modules/_html.js": -/*!*******************************************************!*\ - !*** ./node_modules/core-js/library/modules/_html.js ***! - \*******************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_global */"./node_modules/core-js/library/modules/_global.js").document;e.exports=t&&t.documentElement},"./node_modules/core-js/library/modules/_ie8-dom-define.js": -/*!*****************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_ie8-dom-define.js ***! - \*****************************************************************/ -/*! no static exports found */function(e,r,o){e.exports=!o(/*! ./_descriptors */"./node_modules/core-js/library/modules/_descriptors.js")&&!o(/*! ./_fails */"./node_modules/core-js/library/modules/_fails.js")(function(){return 7!=Object.defineProperty(o(/*! ./_dom-create */"./node_modules/core-js/library/modules/_dom-create.js")("div"),"a",{get:function(){return 7}}).a})},"./node_modules/core-js/library/modules/_invoke.js": -/*!*********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_invoke.js ***! - \*********************************************************/ -/*! no static exports found */function(e,r){e.exports=function(e,r,o){var t=void 0===o;switch(r.length){case 0:return t?e():e.call(o);case 1:return t?e(r[0]):e.call(o,r[0]);case 2:return t?e(r[0],r[1]):e.call(o,r[0],r[1]);case 3:return t?e(r[0],r[1],r[2]):e.call(o,r[0],r[1],r[2]);case 4:return t?e(r[0],r[1],r[2],r[3]):e.call(o,r[0],r[1],r[2],r[3])}return e.apply(o,r)}},"./node_modules/core-js/library/modules/_iobject.js": -/*!**********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_iobject.js ***! - \**********************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_cof */"./node_modules/core-js/library/modules/_cof.js");e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==t(e)?e.split(""):Object(e)}},"./node_modules/core-js/library/modules/_is-array-iter.js": -/*!****************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_is-array-iter.js ***! - \****************************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_iterators */"./node_modules/core-js/library/modules/_iterators.js"),s=o(/*! ./_wks */"./node_modules/core-js/library/modules/_wks.js")("iterator"),n=Array.prototype;e.exports=function(e){return void 0!==e&&(t.Array===e||n[s]===e)}},"./node_modules/core-js/library/modules/_is-object.js": -/*!************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_is-object.js ***! - \************************************************************/ -/*! no static exports found */function(e,r){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},"./node_modules/core-js/library/modules/_iter-call.js": -/*!************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_iter-call.js ***! - \************************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_an-object */"./node_modules/core-js/library/modules/_an-object.js");e.exports=function(e,r,o,s){try{return s?r(t(o)[0],o[1]):r(o)}catch(r){var n=e.return;throw void 0!==n&&t(n.call(e)),r}}},"./node_modules/core-js/library/modules/_iter-create.js": -/*!**************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_iter-create.js ***! - \**************************************************************/ -/*! no static exports found */function(e,r,o){"use strict";var t=o(/*! ./_object-create */"./node_modules/core-js/library/modules/_object-create.js"),s=o(/*! ./_property-desc */"./node_modules/core-js/library/modules/_property-desc.js"),n=o(/*! ./_set-to-string-tag */"./node_modules/core-js/library/modules/_set-to-string-tag.js"),i={};o(/*! ./_hide */"./node_modules/core-js/library/modules/_hide.js")(i,o(/*! ./_wks */"./node_modules/core-js/library/modules/_wks.js")("iterator"),function(){return this}),e.exports=function(e,r,o){e.prototype=t(i,{next:s(1,o)}),n(e,r+" Iterator")}},"./node_modules/core-js/library/modules/_iter-define.js": -/*!**************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_iter-define.js ***! - \**************************************************************/ -/*! no static exports found */function(e,r,o){"use strict";var t=o(/*! ./_library */"./node_modules/core-js/library/modules/_library.js"),s=o(/*! ./_export */"./node_modules/core-js/library/modules/_export.js"),n=o(/*! ./_redefine */"./node_modules/core-js/library/modules/_redefine.js"),i=o(/*! ./_hide */"./node_modules/core-js/library/modules/_hide.js"),l=o(/*! ./_iterators */"./node_modules/core-js/library/modules/_iterators.js"),a=o(/*! ./_iter-create */"./node_modules/core-js/library/modules/_iter-create.js"),u=o(/*! ./_set-to-string-tag */"./node_modules/core-js/library/modules/_set-to-string-tag.js"),c=o(/*! ./_object-gpo */"./node_modules/core-js/library/modules/_object-gpo.js"),d=o(/*! ./_wks */"./node_modules/core-js/library/modules/_wks.js")("iterator"),f=!([].keys&&"next"in[].keys()),m=function(){return this};e.exports=function(e,r,o,y,j,p,_){a(o,r,y);var h,b,v,g=function(e){if(!f&&e in O)return O[e];switch(e){case"keys":case"values":return function(){return new o(this,e)}}return function(){return new o(this,e)}},w=r+" Iterator",x="values"==j,E=!1,O=e.prototype,S=O[d]||O["@@iterator"]||j&&O[j],k=S||g(j),P=j?x?g("entries"):k:void 0,L="Array"==r&&O.entries||S;if(L&&(v=c(L.call(new e)))!==Object.prototype&&v.next&&(u(v,w,!0),t||"function"==typeof v[d]||i(v,d,m)),x&&S&&"values"!==S.name&&(E=!0,k=function(){return S.call(this)}),t&&!_||!f&&!E&&O[d]||i(O,d,k),l[r]=k,l[w]=m,j)if(h={values:x?k:g("values"),keys:p?k:g("keys"),entries:P},_)for(b in h)b in O||n(O,b,h[b]);else s(s.P+s.F*(f||E),r,h);return h}},"./node_modules/core-js/library/modules/_iter-detect.js": -/*!**************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_iter-detect.js ***! - \**************************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_wks */"./node_modules/core-js/library/modules/_wks.js")("iterator"),s=!1;try{var n=[7][t]();n.return=function(){s=!0},Array.from(n,function(){throw 2})}catch(e){}e.exports=function(e,r){if(!r&&!s)return!1;var o=!1;try{var n=[7],i=n[t]();i.next=function(){return{done:o=!0}},n[t]=function(){return i},e(n)}catch(e){}return o}},"./node_modules/core-js/library/modules/_iter-step.js": -/*!************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_iter-step.js ***! - \************************************************************/ -/*! no static exports found */function(e,r){e.exports=function(e,r){return{value:r,done:!!e}}},"./node_modules/core-js/library/modules/_iterators.js": -/*!************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_iterators.js ***! - \************************************************************/ -/*! no static exports found */function(e,r){e.exports={}},"./node_modules/core-js/library/modules/_library.js": -/*!**********************************************************!*\ - !*** ./node_modules/core-js/library/modules/_library.js ***! - \**********************************************************/ -/*! no static exports found */function(e,r){e.exports=!0},"./node_modules/core-js/library/modules/_microtask.js": -/*!************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_microtask.js ***! - \************************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_global */"./node_modules/core-js/library/modules/_global.js"),s=o(/*! ./_task */"./node_modules/core-js/library/modules/_task.js").set,n=t.MutationObserver||t.WebKitMutationObserver,i=t.process,l=t.Promise,a="process"==o(/*! ./_cof */"./node_modules/core-js/library/modules/_cof.js")(i);e.exports=function(){var e,r,o,u=function(){var t,s;for(a&&(t=i.domain)&&t.exit();e;){s=e.fn,e=e.next;try{s()}catch(t){throw e?o():r=void 0,t}}r=void 0,t&&t.enter()};if(a)o=function(){i.nextTick(u)};else if(!n||t.navigator&&t.navigator.standalone)if(l&&l.resolve){var c=l.resolve(void 0);o=function(){c.then(u)}}else o=function(){s.call(t,u)};else{var d=!0,f=document.createTextNode("");new n(u).observe(f,{characterData:!0}),o=function(){f.data=d=!d}}return function(t){var s={fn:t,next:void 0};r&&(r.next=s),e||(e=s,o()),r=s}}},"./node_modules/core-js/library/modules/_new-promise-capability.js": -/*!*************************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_new-promise-capability.js ***! - \*************************************************************************/ -/*! no static exports found */function(e,r,o){"use strict";var t=o(/*! ./_a-function */"./node_modules/core-js/library/modules/_a-function.js");e.exports.f=function(e){return new function(e){var r,o;this.promise=new e(function(e,t){if(void 0!==r||void 0!==o)throw TypeError("Bad Promise constructor");r=e,o=t}),this.resolve=t(r),this.reject=t(o)}(e)}},"./node_modules/core-js/library/modules/_object-assign.js": -/*!****************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_object-assign.js ***! - \****************************************************************/ -/*! no static exports found */function(e,r,o){"use strict";var t=o(/*! ./_object-keys */"./node_modules/core-js/library/modules/_object-keys.js"),s=o(/*! ./_object-gops */"./node_modules/core-js/library/modules/_object-gops.js"),n=o(/*! ./_object-pie */"./node_modules/core-js/library/modules/_object-pie.js"),i=o(/*! ./_to-object */"./node_modules/core-js/library/modules/_to-object.js"),l=o(/*! ./_iobject */"./node_modules/core-js/library/modules/_iobject.js"),a=Object.assign;e.exports=!a||o(/*! ./_fails */"./node_modules/core-js/library/modules/_fails.js")(function(){var e={},r={},o=Symbol(),t="abcdefghijklmnopqrst";return e[o]=7,t.split("").forEach(function(e){r[e]=e}),7!=a({},e)[o]||Object.keys(a({},r)).join("")!=t})?function(e,r){for(var o=i(e),a=arguments.length,u=1,c=s.f,d=n.f;a>u;)for(var f,m=l(arguments[u++]),y=c?t(m).concat(c(m)):t(m),j=y.length,p=0;j>p;)d.call(m,f=y[p++])&&(o[f]=m[f]);return o}:a},"./node_modules/core-js/library/modules/_object-create.js": -/*!****************************************************************!*\ - !*** ./node_modules/core-js/library/modules/_object-create.js ***! - \****************************************************************/ -/*! no static exports found */function(e,r,o){var t=o(/*! ./_an-object */"./node_modules/core-js/library/modules/_an-object.js"),s=o(/*! ./_object-dps */"./node_modules/core-js/library/modules/_object-dps.js"),n=o(/*! ./_enum-bug-keys */"./node_modules/core-js/library/modules/_enum-bug-keys.js"),i=o(/*! ./_shared-key */"./node_modules/core-js/library/modules/_shared-key.js")("IE_PROTO"),l=function(){},a=function(){var e,r=o(/*! ./_dom-create */"./node_modules/core-js/library/modules/_dom-create.js")("iframe"),t=n.length;for(r.style.display="none",o(/*! ./_html */"./node_modules/core-js/library/modules/_html.js").appendChild(r),r.src="javascript:",(e=r.contentWindow.document).open(),e.write("