diff --git a/README.md b/README.md
index 9f3c1187..b22ca2bf 100644
--- a/README.md
+++ b/README.md
@@ -231,6 +231,10 @@ To define the **Host** with the server instance's IP, click the _Host_ field f t
| :-----
| _Demonstrates the failover mechanism of the Red5 Pro HTML SDK to select a subscriber based on browser support and to auto-reconnect on close of broadcast or loss of connection._
+| **[Renegotiation Policy](src/page/test/subscribeRenegotiationPolicy/)**
+| :-----
+| _Demonstrates ICE renegotiation stategies of the SDK during poor network conditions._
+
| **[Remote Call](src/page/test/subscribeRemoteCall)**
| :-----
| _Demonstrates receiving a remote message from broadcaster._
@@ -281,6 +285,11 @@ To define the **Host** with the server instance's IP, click the _Host_ field f t
| :-----
| _Demonstrates the failover mechanism of the Red5 Pro HTML SDK to select a subscriber based on browser support and to auto-reconnect on close of broadcast or loss of connection._
+| **[Stream Manager Proxy Renegotiation Policy](src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/)**
+| :-----
+| _Demonstrates ICE renegotiation stategies of the SDK during poor network conditions._
+
+
| **[Stream Manager Proxy Round Trip Authentication](src/page/sm-test/subscribeStreamManagerProxyRoundTripAuth)**
| :-----
| _Demonstrates subscribing using round trip authentication, region specified._
diff --git a/package-lock.json b/package-lock.json
index 4330c856..982a31ae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "red5pro-html-sdk-testbed",
- "version": "15.0.0",
+ "version": "15.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "red5pro-html-sdk-testbed",
- "version": "15.0.0",
+ "version": "15.1.0",
"license": "LICENSE",
"dependencies": {
"@babel/core": "^7.17.4"
diff --git a/package.json b/package.json
index 88568225..25c59b8f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "red5pro-html-sdk-testbed",
- "version": "15.1.0",
+ "version": "15.2.0",
"description": "Testbed examples for Red5 Pro HTML SDK",
"main": "src/js/index.js",
"repository": {
diff --git a/src/page/index.html b/src/page/index.html
index 83129561..6601305e 100644
--- a/src/page/index.html
+++ b/src/page/index.html
@@ -472,8 +472,10 @@
Statistics Reporting
});
enableStatisticsField.addEventListener('change', function () {
+ let value = statisticsEndpointField.value;
+ value = value && value.length > 0 ? value : undefined;
configuration.stats = enableStatisticsField.checked ? {
- endpoint: statisticsEndpointField.value,
+ endpoint: value === 'null' ? null : value,
interval: parseInt(statisticsIntervalField.value, 10) * 1000,
include: [],
} : undefined
@@ -491,7 +493,7 @@ Statistics Reporting
if (configuration.stats) {
let value = statisticsEndpointField.value;
value = value && value.length > 0 ? value : undefined;
- configuration.stats.endpoint = value;
+ configuration.stats.endpoint = value === 'null' ? null : value;
}
seal(configuration);
});
@@ -531,7 +533,7 @@ Statistics Reporting
authUsernameField.value = config.authentication.username;
authPasswordField.value = config.authentication.password;
authTokenField.value = config.authentication.token;
- authUsernameField.disabled = authPasswordField.disabled = !authEnabledField.checked;
+ authUsernameField.disabled = authPasswordField.disabled = authTokenField.disabled = !authEnabledField.checked;
enableStatisticsField.checked = config.stats ? true : false;
statisticsIntervalField.value = config.stats ? Math.floor(parseInt(config.stats.interval, 10) / 1000) : 5;
statisticsEndpointField.value = config.stats ? config.stats.endpoint : '';
diff --git a/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/README.md b/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/README.md
new file mode 100644
index 00000000..4a1c06c4
--- /dev/null
+++ b/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/README.md
@@ -0,0 +1,92 @@
+# Subscribe Renegotiation Policy
+
+This example demonstrates how to configure and test renegotiation policies for WebRTC subscribers using the Red5 HTML SDK. Renegotiation policies control how the subscriber handles network degradation and connection issues during the ICE negotiation phase of a WebRTC session.
+
+**Please refer to the [Basic Subscriber Documentation](../subscribe/README.md) to learn more about the basic setup.**
+
+## Example Code
+
+- **[index.html](index.html)**
+- **[index.js](index.js)**
+
+## Feature Overview
+
+The `renegotiationPolicy` feature of the Red5 HTML SDK allows you to configure how the WebRTC subscriber responds to network issues and connection degradation during the ICE negotiation phase. This is particularly useful for maintaining stream quality and connection stability in varying network conditions.
+
+### Available Policy Types
+
+1. **timeout** - Attempts to renegotiate the connection after a specified timeout interval when network conditions degrade. This policy allows you to set a custom timeout interval (in milliseconds).
+
+2. **disconnect** - Immediately disconnects the subscriber when network issues are detected, rather than attempting to renegotiate.
+
+3. **regression** - Uses a regression-based approach to handle network degradation, attempting to adapt the connection quality based on detected network conditions.
+
+> The `regression` policy is the most aggressive as it can be detected very early on in the negotiation phase, _however_ it does not always occur. It is recommended to go with the `timeout` policy.
+
+## Implementation
+
+The renegotiation policy is configured when initializing the WHEP subscriber:
+
+```js
+let rtcConfig = {
+ ...configuration,
+ streamName,
+ subscriptionId: 'subscriber-' + instanceId,
+ renegotiationPolicy: {
+ type: typeSelect.value, // 'timeout' | 'disconnect' | 'regression'
+ timeoutInterval: parseInt(timeoutIntervalSelect.value, 10) // Only used for TIMEOUT policy
+ }
+}
+
+targetSubscriber = new WHEPClient()
+await targetSubscriber.init(rtcConfig)
+await targetSubscriber.subscribe()
+```
+
+### Event Tracking
+
+The example tracks reconnection attempts through the `Reconnect.Start` event:
+
+```js
+if (event.type === 'Reconnect.Start') {
+ reconnectionAttempts++
+ reconnectionAttemptsField.innerText = reconnectionAttempts
+}
+```
+
+## How to Use
+
+1. **Open Chrome DevTools** - Press `F12` or right-click and select "Inspect"
+
+2. **Navigate to the Network Tab** - Click on the "Network" tab in DevTools
+
+3. **Enable Network Throttling**:
+ - Click the gear icon (⚙️) in the Network tab
+ - Select "Throttling" from the dropdown
+ - Choose "Slow 3G" or another throttling profile to simulate poor network conditions
+
+4. **Configure the Renegotiation Policy**:
+ - Select a **Policy Type** from the dropdown:
+ - `TIMEOUT` - Enables timeout interval selection
+ - `DISCONNECT` - Immediately disconnects on network issues
+ - `REGRESSION` - Uses regression-based adaptation
+ - If using `TIMEOUT`, select a **Timeout Interval** (1000-5000 milliseconds)
+
+5. **Start the Subscription**:
+ - Click the "Subscribe" button
+ - The subscriber will attempt to connect to the stream
+
+6. **Observe Behavior**:
+ - Watch the reconnection attempts counter increment as network issues are detected
+ - Monitor the subscriber status and statistics fields
+ - Observe how the selected policy handles the degraded network conditions
+
+7. **Test Recovery**:
+ - Reset the network throttling to "No throttling" or "Online"
+ - Observe how the subscriber recovers and maintains the connection
+
+## Notes
+
+- The timeout interval is only applicable when using the `TIMEOUT` policy type
+- The example uses the WHEP (WebRTC HTTP Egress Protocol) client for WebRTC-based subscriptions
+- Network throttling must be enabled in Chrome DevTools to properly test the renegotiation behavior
diff --git a/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/index.html b/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/index.html
new file mode 100644
index 00000000..ede40c90
--- /dev/null
+++ b/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/index.html
@@ -0,0 +1,85 @@
+
+{{> license}}
+
+
+ {{> meta title='Subscriber Stream Manager Proxy Renegotiation Policy Test'}}
+ {{> header-scripts}}
+ {{> header-stylesheets}}
+
+
+
+ {{> top-bar }}
+
+ {{> settings-link}}
+ {{> test-info testTitle='Subscriber Renegotiation Policy Test'}}
+
+
+
+
Use network throttling to simulate a slow network connection.
+
+ Open the Chrome DevTools
+ Navigate to the Network tab
+ Click the gear icon and select "Throttling"
+ Select "Slow 3G" from the dropdown
+ Select the Policy Type and Timeout Interval
+ Click the "Subscribe" button
+ Observe the renegotiation attempts and the status of the subscription
+ Reset the network throttling to unlimited after a few reconnection attempts
+
+
+
+
+ Select a Renegotiation Policy Type:
+
+ Timeout
+ Disconnect
+ Regression
+
+
+
+ Select a Timeout Interval (milliseconds):
+
+ 1000
+ 2000
+ 3000
+ 4000
+ 5000
+
+
+
+ Subscribe
+
+
+
+ Reconnection Attempts: 0
+
+
+ {{> status-field-subscriber}}
+ {{> statistics-field packets_field='Packets Received'}}
+
+
+
+
+
+
+ {{> footer}}
+ {{> body-scripts}}
+ {{> mobile-subscriber-util}}
+
+
+
diff --git a/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/index.js b/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/index.js
new file mode 100644
index 00000000..3a529210
--- /dev/null
+++ b/src/page/sm-test/subscribeStreamManagerProxyRenegotiationPolicy/index.js
@@ -0,0 +1,265 @@
+/*
+Copyright © 2015 Infrared5, Inc. All rights reserved.
+
+The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code")
+is licensed to you by Infrared5 Inc. in consideration of your agreement to the following
+license terms and conditions. Access, use, modification, or redistribution of the accompanying
+code constitutes your acceptance of the following license terms and conditions.
+
+Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation
+files (collectively, the "Software") without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end
+user license agreement (the "EULA"), which must be executed with Infrared5, Inc.
+An example of the EULA can be found on our website at: https://account.red5.net/assets/LICENSE.txt.
+
+The above copyright notice and this license shall be included in all copies or portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+;((window, document, red5prosdk) => {
+ 'use strict'
+
+ const configuration = (function () {
+ let 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
+ )
+
+ let targetSubscriber
+ let reconnectionAttempts = 0
+ const typeSelect = document.getElementById('type-select')
+ const timeoutIntervalSelect = document.getElementById(
+ 'timeout-interval-select'
+ )
+ const reconnectionAttemptsField = document.getElementById(
+ 'reconnection-attempts'
+ )
+ const subscribeButton = document.getElementById('subscribe-button')
+ typeSelect.addEventListener('change', event => {
+ timeoutIntervalSelect.disabled = event.target.value !== 'TIMEOUT'
+ })
+ timeoutIntervalSelect.disabled = typeSelect.value !== 'TIMEOUT'
+
+ const updateStatusFromEvent = window.red5proHandleSubscriberEvent // defined in src/template/partial/status-field-subscriber.hbs
+ const instanceId = Math.floor(Math.random() * 0x10000).toString(16)
+ const streamTitle = document.getElementById('stream-title')
+ const statisticsField = document.getElementById('statistics-field')
+ const bitrateField = document.getElementById('bitrate-field')
+ const packetsField = document.getElementById('packets-field')
+ const resolutionField = document.getElementById('resolution-field')
+
+ let bitrate = 0
+ let packetsReceived = 0
+ let frameWidth = 0
+ let frameHeight = 0
+
+ const updateStatistics = (b, p, w, h) => {
+ statisticsField.classList.remove('hidden')
+ bitrateField.innerText = b === 0 ? 'N/A' : Math.floor(b)
+ packetsField.innerText = p
+ resolutionField.innerText = (w || 0) + 'x' + (h || 0)
+ }
+
+ const onBitrateUpdate = (b, p) => {
+ bitrate = b
+ packetsReceived = p
+ updateStatistics(bitrate, packetsReceived, frameWidth, frameHeight)
+ }
+
+ const onResolutionUpdate = (w, h) => {
+ frameWidth = w
+ frameHeight = h
+ updateStatistics(bitrate, packetsReceived, frameWidth, frameHeight)
+ }
+
+ // Base configuration to extend in providing specific tech failover configurations.
+ let defaultConfiguration = ((useVideo, useAudio) => {
+ let c = configuration
+ if (!useVideo) {
+ c.videoEncoding = red5prosdk.PlaybackVideoEncoder.NONE
+ }
+ if (!useAudio) {
+ c.audioEncoding = red5prosdk.PlaybackAudioEncoder.NONE
+ }
+ return c
+ })(configuration.useVideo, configuration.useAudio)
+
+ // Local lifecycle notifications.
+ const onSubscriberEvent = event => {
+ const { type, target, data } = event
+ if (type !== 'Subscribe.Time.Update') {
+ console.log('[Red5ProSubscriber] ' + type + '.')
+ updateStatusFromEvent(event)
+ if (event.type === 'Subscribe.VideoDimensions.Change') {
+ onResolutionUpdate(data.width, data.height)
+ } else if (event.type === 'Reconnect.Start') {
+ reconnectionAttempts++
+ reconnectionAttemptsField.innerText = reconnectionAttempts
+ } else if (event.type === 'Subscribe.Start') {
+ onSubscribeSuccess(target ?? targetSubscriber)
+ }
+ }
+ }
+ const onSubscribeFail = message => {
+ console.error('[Red5ProSubsriber] Subscribe Error :: ' + message)
+ }
+ const onSubscribeSuccess = subscriber => {
+ console.log('[Red5ProSubsriber] Subscribe Complete.')
+ if (window.exposeSubscriberGlobally) {
+ window.exposeSubscriberGlobally(subscriber)
+ }
+ if (subscriber.getType().toLowerCase() === 'rtc') {
+ try {
+ window.untrackBitrate()
+ window.trackBitrate(
+ subscriber.getPeerConnection(),
+ onBitrateUpdate,
+ onResolutionUpdate,
+ true
+ )
+ } catch (e) {
+ //
+ }
+ }
+ }
+ const onUnsubscribeFail = message => {
+ console.error('[Red5ProSubsriber] Unsubscribe Error :: ' + message)
+ }
+ const onUnsubscribeSuccess = () => {
+ console.log('[Red5ProSubsriber] Unsubscribe Complete.')
+ }
+
+ const getRegionIfDefined = () => {
+ var region = configuration.streamManagerRegion
+ if (
+ typeof region === 'string' &&
+ region.length > 0 &&
+ region !== 'undefined'
+ ) {
+ return region
+ }
+ return undefined
+ }
+
+ const getAuthenticationParams = () => {
+ const auth = configuration.authentication
+ return auth && auth.enabled
+ ? {
+ connectionParams: {
+ username: auth.username,
+ password: auth.password,
+ token: auth.token
+ }
+ }
+ : {}
+ }
+
+ // Request to unsubscribe.
+ const unsubscribe = async () => {
+ try {
+ await targetSubscriber.unsubscribe()
+ targetSubscriber.off('*', onSubscriberEvent)
+ onUnsubscribeSuccess()
+ } catch (error) {
+ var jsonError =
+ typeof error === 'string' ? error : JSON.stringify(error, null, 2)
+ onUnsubscribeFail(jsonError)
+ } finally {
+ targetSubscriber = undefined
+ }
+ }
+ const start = async () => {
+ subscribeButton.disabled = true
+ const { stream1: streamName } = configuration
+ const { WHEPClient } = red5prosdk
+
+ const {
+ host,
+ app,
+ protocol,
+ port,
+ streamManagerAPI,
+ streamManagerNodeGroup: nodeGroup
+ } = configuration
+
+ const region = getRegionIfDefined()
+ const params = region
+ ? {
+ region,
+ strict: true
+ }
+ : undefined
+ const connectionParams = params
+ ? { ...params, ...getAuthenticationParams().connectionParams }
+ : getAuthenticationParams().connectionParams
+
+ const httpProtocol = protocol === 'ws' ? 'http' : 'https'
+ const endpoint = `${httpProtocol}://${host}:${port}/as/${streamManagerAPI}/proxy/whep/${app}/${streamName}`
+
+ let rtcConfig = {
+ ...configuration,
+ ...defaultConfiguration,
+ ...getAuthenticationParams(),
+ endpoint,
+ streamName,
+ subscriptionId: 'subscriber-' + instanceId,
+ renegotiationPolicy: {
+ type: typeSelect.value,
+ timeoutInterval: parseInt(timeoutIntervalSelect.value, 10)
+ },
+ connectionParams: {
+ ...connectionParams,
+ nodeGroup
+ }
+ }
+
+ try {
+ streamTitle.innerText = streamName
+
+ targetSubscriber = new WHEPClient()
+ targetSubscriber.on('*', onSubscriberEvent)
+ await targetSubscriber.init(rtcConfig)
+ await targetSubscriber.subscribe()
+ onSubscribeSuccess(targetSubscriber)
+ } catch (error) {
+ var jsonError =
+ typeof error === 'string' ? error : JSON.stringify(error, null, 2)
+ console.error(
+ '[Red5ProSubscriber] :: Error in subscribing - ' + jsonError
+ )
+ onSubscribeFail(jsonError)
+ subscribeButton.disabled = false
+ }
+ }
+
+ // Clean up.
+ let shuttingDown = false
+ const shutdown = async () => {
+ if (shuttingDown) return
+ shuttingDown = true
+ window.untrackBitrate()
+ await unsubscribe()
+ }
+ window.addEventListener('pagehide', shutdown)
+ window.addEventListener('beforeunload', shutdown)
+
+ subscribeButton.addEventListener('click', start)
+})(this, document, window.red5prosdk)
diff --git a/src/page/test/subscribeReconnect/README.md b/src/page/test/subscribeReconnect/README.md
index 04661ba8..2fc71298 100644
--- a/src/page/test/subscribeReconnect/README.md
+++ b/src/page/test/subscribeReconnect/README.md
@@ -1,4 +1,4 @@
-# Subscribe Failover & Reconnection using Red5 Pro
+# Subscribe Reconnection using Red5 Pro
This is an example of utilizing the failover mechanism of the Red5 Pro HTML SDK to select a subscriber based on browser support and to reconnect on close of broadcast or loss of connection.
@@ -33,7 +33,7 @@ In the occurance of a lost stream from the publisher - either from a network iss
There are 2 important events that relate to the loss of a publisher:
- `CONNECTION_CLOSED`
-- `NET_STATUS` with message of `NetStream.Play.UnpublishNotify`
+- `PLAY_UNPUBLISH`
In this example, we rely on the `CONNECTION_CLOSED` event to start that reconnect cycle again, waiting for the publisher to come back:
diff --git a/src/page/test/subscribeRenegotiationPolicy/README.md b/src/page/test/subscribeRenegotiationPolicy/README.md
new file mode 100644
index 00000000..4a1c06c4
--- /dev/null
+++ b/src/page/test/subscribeRenegotiationPolicy/README.md
@@ -0,0 +1,92 @@
+# Subscribe Renegotiation Policy
+
+This example demonstrates how to configure and test renegotiation policies for WebRTC subscribers using the Red5 HTML SDK. Renegotiation policies control how the subscriber handles network degradation and connection issues during the ICE negotiation phase of a WebRTC session.
+
+**Please refer to the [Basic Subscriber Documentation](../subscribe/README.md) to learn more about the basic setup.**
+
+## Example Code
+
+- **[index.html](index.html)**
+- **[index.js](index.js)**
+
+## Feature Overview
+
+The `renegotiationPolicy` feature of the Red5 HTML SDK allows you to configure how the WebRTC subscriber responds to network issues and connection degradation during the ICE negotiation phase. This is particularly useful for maintaining stream quality and connection stability in varying network conditions.
+
+### Available Policy Types
+
+1. **timeout** - Attempts to renegotiate the connection after a specified timeout interval when network conditions degrade. This policy allows you to set a custom timeout interval (in milliseconds).
+
+2. **disconnect** - Immediately disconnects the subscriber when network issues are detected, rather than attempting to renegotiate.
+
+3. **regression** - Uses a regression-based approach to handle network degradation, attempting to adapt the connection quality based on detected network conditions.
+
+> The `regression` policy is the most aggressive as it can be detected very early on in the negotiation phase, _however_ it does not always occur. It is recommended to go with the `timeout` policy.
+
+## Implementation
+
+The renegotiation policy is configured when initializing the WHEP subscriber:
+
+```js
+let rtcConfig = {
+ ...configuration,
+ streamName,
+ subscriptionId: 'subscriber-' + instanceId,
+ renegotiationPolicy: {
+ type: typeSelect.value, // 'timeout' | 'disconnect' | 'regression'
+ timeoutInterval: parseInt(timeoutIntervalSelect.value, 10) // Only used for TIMEOUT policy
+ }
+}
+
+targetSubscriber = new WHEPClient()
+await targetSubscriber.init(rtcConfig)
+await targetSubscriber.subscribe()
+```
+
+### Event Tracking
+
+The example tracks reconnection attempts through the `Reconnect.Start` event:
+
+```js
+if (event.type === 'Reconnect.Start') {
+ reconnectionAttempts++
+ reconnectionAttemptsField.innerText = reconnectionAttempts
+}
+```
+
+## How to Use
+
+1. **Open Chrome DevTools** - Press `F12` or right-click and select "Inspect"
+
+2. **Navigate to the Network Tab** - Click on the "Network" tab in DevTools
+
+3. **Enable Network Throttling**:
+ - Click the gear icon (⚙️) in the Network tab
+ - Select "Throttling" from the dropdown
+ - Choose "Slow 3G" or another throttling profile to simulate poor network conditions
+
+4. **Configure the Renegotiation Policy**:
+ - Select a **Policy Type** from the dropdown:
+ - `TIMEOUT` - Enables timeout interval selection
+ - `DISCONNECT` - Immediately disconnects on network issues
+ - `REGRESSION` - Uses regression-based adaptation
+ - If using `TIMEOUT`, select a **Timeout Interval** (1000-5000 milliseconds)
+
+5. **Start the Subscription**:
+ - Click the "Subscribe" button
+ - The subscriber will attempt to connect to the stream
+
+6. **Observe Behavior**:
+ - Watch the reconnection attempts counter increment as network issues are detected
+ - Monitor the subscriber status and statistics fields
+ - Observe how the selected policy handles the degraded network conditions
+
+7. **Test Recovery**:
+ - Reset the network throttling to "No throttling" or "Online"
+ - Observe how the subscriber recovers and maintains the connection
+
+## Notes
+
+- The timeout interval is only applicable when using the `TIMEOUT` policy type
+- The example uses the WHEP (WebRTC HTTP Egress Protocol) client for WebRTC-based subscriptions
+- Network throttling must be enabled in Chrome DevTools to properly test the renegotiation behavior
diff --git a/src/page/test/subscribeRenegotiationPolicy/index.html b/src/page/test/subscribeRenegotiationPolicy/index.html
new file mode 100644
index 00000000..da8ac31e
--- /dev/null
+++ b/src/page/test/subscribeRenegotiationPolicy/index.html
@@ -0,0 +1,85 @@
+
+{{> license}}
+
+
+ {{> meta title='Subscriber Renegotiation Policy Test'}}
+ {{> header-scripts}}
+ {{> header-stylesheets}}
+
+
+
+ {{> top-bar }}
+
+ {{> settings-link}}
+ {{> test-info testTitle='Subscriber Renegotiation Policy Test'}}
+
+
+
+
Use network throttling to simulate a slow network connection.
+
+ Open the Chrome DevTools
+ Navigate to the Network tab
+ Click the gear icon and select "Throttling"
+ Select "Slow 3G" from the dropdown
+ Select the Policy Type and Timeout Interval
+ Click the "Subscribe" button
+ Observe the renegotiation attempts and the status of the subscription
+ Reset the network throttling to unlimited after a few reconnection attempts
+
+
+
+
+ Select a Renegotiation Policy Type:
+
+ Timeout
+ Disconnect
+ Regression
+
+
+
+ Select a Timeout Interval (milliseconds):
+
+ 1000
+ 2000
+ 3000
+ 4000
+ 5000
+
+
+
+ Subscribe
+
+
+
+ Reconnection Attempts: 0
+
+
+ {{> status-field-subscriber}}
+ {{> statistics-field packets_field='Packets Received'}}
+
+
+
+
+
+
+ {{> footer}}
+ {{> body-scripts}}
+ {{> mobile-subscriber-util}}
+
+
+
diff --git a/src/page/test/subscribeRenegotiationPolicy/index.js b/src/page/test/subscribeRenegotiationPolicy/index.js
new file mode 100644
index 00000000..b53b8ac8
--- /dev/null
+++ b/src/page/test/subscribeRenegotiationPolicy/index.js
@@ -0,0 +1,224 @@
+/*
+Copyright © 2015 Infrared5, Inc. All rights reserved.
+
+The accompanying code comprising examples for use solely in conjunction with Red5 Pro (the "Example Code")
+is licensed to you by Infrared5 Inc. in consideration of your agreement to the following
+license terms and conditions. Access, use, modification, or redistribution of the accompanying
+code constitutes your acceptance of the following license terms and conditions.
+
+Permission is hereby granted, free of charge, to you to use the Example Code and associated documentation
+files (collectively, the "Software") without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The Software shall be used solely in conjunction with Red5 Pro. Red5 Pro is licensed under a separate end
+user license agreement (the "EULA"), which must be executed with Infrared5, Inc.
+An example of the EULA can be found on our website at: https://account.red5.net/assets/LICENSE.txt.
+
+The above copyright notice and this license shall be included in all copies or portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL INFRARED5, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+;((window, document, red5prosdk) => {
+ 'use strict'
+
+ const configuration = (function () {
+ let 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
+ )
+
+ let targetSubscriber
+ let reconnectionAttempts = 0
+ const typeSelect = document.getElementById('type-select')
+ const timeoutIntervalSelect = document.getElementById(
+ 'timeout-interval-select'
+ )
+ const reconnectionAttemptsField = document.getElementById(
+ 'reconnection-attempts'
+ )
+ const subscribeButton = document.getElementById('subscribe-button')
+ typeSelect.addEventListener('change', event => {
+ timeoutIntervalSelect.disabled = event.target.value !== 'TIMEOUT'
+ })
+ timeoutIntervalSelect.disabled = typeSelect.value !== 'TIMEOUT'
+
+ const updateStatusFromEvent = window.red5proHandleSubscriberEvent // defined in src/template/partial/status-field-subscriber.hbs
+ const instanceId = Math.floor(Math.random() * 0x10000).toString(16)
+ const streamTitle = document.getElementById('stream-title')
+ const statisticsField = document.getElementById('statistics-field')
+ const bitrateField = document.getElementById('bitrate-field')
+ const packetsField = document.getElementById('packets-field')
+ const resolutionField = document.getElementById('resolution-field')
+
+ let bitrate = 0
+ let packetsReceived = 0
+ let frameWidth = 0
+ let frameHeight = 0
+
+ const updateStatistics = (b, p, w, h) => {
+ statisticsField.classList.remove('hidden')
+ bitrateField.innerText = b === 0 ? 'N/A' : Math.floor(b)
+ packetsField.innerText = p
+ resolutionField.innerText = (w || 0) + 'x' + (h || 0)
+ }
+
+ const onBitrateUpdate = (b, p) => {
+ bitrate = b
+ packetsReceived = p
+ updateStatistics(bitrate, packetsReceived, frameWidth, frameHeight)
+ }
+
+ const onResolutionUpdate = (w, h) => {
+ frameWidth = w
+ frameHeight = h
+ updateStatistics(bitrate, packetsReceived, frameWidth, frameHeight)
+ }
+
+ // Base configuration to extend in providing specific tech failover configurations.
+ let defaultConfiguration = ((useVideo, useAudio) => {
+ let c = configuration
+ if (!useVideo) {
+ c.videoEncoding = red5prosdk.PlaybackVideoEncoder.NONE
+ }
+ if (!useAudio) {
+ c.audioEncoding = red5prosdk.PlaybackAudioEncoder.NONE
+ }
+ return c
+ })(configuration.useVideo, configuration.useAudio)
+
+ // Local lifecycle notifications.
+ const onSubscriberEvent = event => {
+ const { type, target, data } = event
+ if (type !== 'Subscribe.Time.Update') {
+ console.log('[Red5ProSubscriber] ' + type + '.')
+ updateStatusFromEvent(event)
+ if (event.type === 'Subscribe.VideoDimensions.Change') {
+ onResolutionUpdate(data.width, data.height)
+ } else if (event.type === 'Reconnect.Start') {
+ reconnectionAttempts++
+ reconnectionAttemptsField.innerText = reconnectionAttempts
+ } else if (event.type === 'Subscribe.Start') {
+ onSubscribeSuccess(target ?? targetSubscriber)
+ }
+ }
+ }
+ const onSubscribeFail = message => {
+ console.error('[Red5ProSubsriber] Subscribe Error :: ' + message)
+ }
+ const onSubscribeSuccess = subscriber => {
+ console.log('[Red5ProSubsriber] Subscribe Complete.')
+ if (window.exposeSubscriberGlobally) {
+ window.exposeSubscriberGlobally(subscriber)
+ }
+ if (subscriber.getType().toLowerCase() === 'rtc') {
+ try {
+ window.untrackBitrate()
+ window.trackBitrate(
+ subscriber.getPeerConnection(),
+ onBitrateUpdate,
+ onResolutionUpdate,
+ true
+ )
+ } catch (e) {
+ //
+ }
+ }
+ }
+ const onUnsubscribeFail = message => {
+ console.error('[Red5ProSubsriber] Unsubscribe Error :: ' + message)
+ }
+ const onUnsubscribeSuccess = () => {
+ console.log('[Red5ProSubsriber] Unsubscribe Complete.')
+ }
+
+ const getAuthenticationParams = () => {
+ const auth = configuration.authentication
+ return auth && auth.enabled
+ ? {
+ connectionParams: {
+ username: auth.username,
+ password: auth.password,
+ token: auth.token
+ }
+ }
+ : {}
+ }
+
+ // Request to unsubscribe.
+ const unsubscribe = async () => {
+ try {
+ await targetSubscriber.unsubscribe()
+ targetSubscriber.off('*', onSubscriberEvent)
+ onUnsubscribeSuccess()
+ } catch (error) {
+ var jsonError =
+ typeof error === 'string' ? error : JSON.stringify(error, null, 2)
+ onUnsubscribeFail(jsonError)
+ } finally {
+ targetSubscriber = undefined
+ }
+ }
+ const start = async () => {
+ subscribeButton.disabled = true
+ const { stream1: streamName } = configuration
+ const { WHEPClient } = red5prosdk
+ let rtcConfig = {
+ ...configuration,
+ ...defaultConfiguration,
+ ...getAuthenticationParams(),
+ streamName,
+ subscriptionId: 'subscriber-' + instanceId,
+ renegotiationPolicy: {
+ type: typeSelect.value,
+ timeoutInterval: parseInt(timeoutIntervalSelect.value, 10)
+ }
+ }
+
+ try {
+ streamTitle.innerText = streamName
+
+ targetSubscriber = new WHEPClient()
+ targetSubscriber.on('*', onSubscriberEvent)
+ await targetSubscriber.init(rtcConfig)
+ await targetSubscriber.subscribe()
+ onSubscribeSuccess(targetSubscriber)
+ } catch (error) {
+ var jsonError =
+ typeof error === 'string' ? error : JSON.stringify(error, null, 2)
+ console.error(
+ '[Red5ProSubscriber] :: Error in subscribing - ' + jsonError
+ )
+ onSubscribeFail(jsonError)
+ subscribeButton.disabled = false
+ }
+ }
+
+ // Clean up.
+ let shuttingDown = false
+ const shutdown = async () => {
+ if (shuttingDown) return
+ shuttingDown = true
+ window.untrackBitrate()
+ await unsubscribe()
+ }
+ window.addEventListener('pagehide', shutdown)
+ window.addEventListener('beforeunload', shutdown)
+
+ subscribeButton.addEventListener('click', start)
+})(this, document, window.red5prosdk)
diff --git a/src/page/testbed-menu-sm.html b/src/page/testbed-menu-sm.html
index d37193f7..5ded05e3 100644
--- a/src/page/testbed-menu-sm.html
+++ b/src/page/testbed-menu-sm.html
@@ -54,6 +54,7 @@ Red5 Pro HTML Stream Manager Testbed
Subscribe - Stream Manager Proxy Interstitial Media Insertion
Subscribe - Stream Manager Proxy Reconnect
+ Subscribe - Stream Manager Proxy Renegotiation Policy
Subscribe - Stream Manager Proxy RoundTrip Authentication
Subscribe - Stream Manager Proxy Screen Share
Subscribe - Stream Manager Proxy Stream Switch
diff --git a/src/page/testbed-menu.html b/src/page/testbed-menu.html
index e1ba0103..8733f608 100644
--- a/src/page/testbed-menu.html
+++ b/src/page/testbed-menu.html
@@ -67,6 +67,7 @@ Red5 Pro HTML Testbed
Subscribe - RoundTrip Authentication
Subscribe - Remote Call
Subscribe - Reconnect
+ Subscribe - Renegotiation Policy
Subscribe - Retry On Connection
Subscribe - ScreenShare
Subscribe - Server Call
diff --git a/static/lib/red5pro/CHANGES.md b/static/lib/red5pro/CHANGES.md
index 333ef0f1..8ea84167 100644
--- a/static/lib/red5pro/CHANGES.md
+++ b/static/lib/red5pro/CHANGES.md
@@ -1,5 +1,12 @@
# Changes
+## 15.2.0
+
+- fix: ICE configuration order preference (Todd Anderson).
+- feat: Connection health monitoring for WebRTC publishers and subscribers with automatic detection of stale stats, ICE state regression, excessive RTT, and ICE negotiation timeouts (Todd Anderson)
+- feat: Added new WebRTC connection health events: `WebRTC.Connection.StaleStats`, `WebRTC.Connection.StateRegression`, `WebRTC.Connection.ExcessiveRTT`, `WebRTC.Connection.IceTimeout` (Todd Anderson)
+- feat: `renegotiationPolicy` init configuration property for defining monitor and handling of ICE negotiation failures.
+
## 15.0.0
**ALERT: Breaking Changes**
diff --git a/static/lib/red5pro/docs/api/README.md b/static/lib/red5pro/docs/api/README.md
index 817adc12..dd7af78b 100644
--- a/static/lib/red5pro/docs/api/README.md
+++ b/static/lib/red5pro/docs/api/README.md
@@ -1,4 +1,4 @@
-**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**
+**Red5 Pro WebRTC SDK v15.2.0**
***
diff --git a/static/lib/red5pro/docs/api/_media/whep-client.md b/static/lib/red5pro/docs/api/_media/whep-client.md
index 3644809b..f583a080 100644
--- a/static/lib/red5pro/docs/api/_media/whep-client.md
+++ b/static/lib/red5pro/docs/api/_media/whep-client.md
@@ -21,6 +21,7 @@ This provides a standardized - and _blazingly fast_ - way to establish and playb
* [Init Configuration](#init-configuration)
* [Events](#events)
* [Statistics](#statistics)
+* [Renegotiation Policy](#renegotiation-policy)
* [Live Seek](#live-seek)
* [Stream Manager 2.0](#stream-manager-20)
@@ -118,6 +119,7 @@ When using the `init()` call of a `WHEPClient` - or, alternatively, when using a
| `maintainStreamVariant` | [-] | `false` | Flag to instruct the server - when utilizing transcoding - to not switch subscriber stream variants when network conditions change. By setting this to `true`, when you request to playback a stream that is transcoded, the server will not deliver a variant of higher or lower quality dependending on current network conditions. |
| `stats` | [-] | *None* | Configuration object to enable stats reporting. See [Stats Reporting](#statistics) for more information. |
| `liveSeek` | [-] | *None* | Configuration object to enable live seek capability. See [Live Seek](#live-seek) for more information. |
+| `renegotiationPolicy` | [-] | *None* | Configuration object for renegotiation of ICE. See [Renegotiation Policy](#renegotiation-policy) for more information. |
# Events
@@ -155,6 +157,7 @@ You can also listen to events individually. The following describe the various e
| :--- | :--- | :--- |
| `CONNECT_SUCCESS` | 'Connect.Success' | When the subscriber has established a required remote connection, such as to a WebSocket server. |
| `CONNECT_FAILURE` | 'Connect.Failure' | When the subscriber has failed to establish a required remote connection for consuming a stream. |
+| `RECONNECT_START` | 'Reconnect.Start' | Signal when attempt on reconnect has begun. This is used in conjunction with the `renegotiationPolicy` of the `init()` configuration. |
| `SUBSCRIBE_START` | 'Subscribe.Start' | When the subscriber has started a subscribing to a stream. |
| `SUBSCRIBE_STOP` | 'Subscribe.Stop' | When the subscriber has successfully closed an active subscription to a stream. |
| `SUBSCRIBE_METADATA` | 'Subscribe.Metadata' | When metadata is received on the client from the server. |
@@ -196,7 +199,15 @@ In addition to the above events, the following events are also dispatched from a
| `LIVE_SEEK_ERROR` | 'WebRTC.LiveSeek.Error' | When `liveSeek` is used to playback Live VOD and HLS video and an error in playback has occurred. Inspect the `error` attribute on the event for more details. |
| `LIVE_SEEK_LOADING` | 'WebRTC.LiveSeek.FragmentLoading' | When `liveSeek` is used to playback Live VOD and HLS video in currently loading a fragment during seeking. |
| `LIVE_SEEK_LOADED` | 'WebRTC.LiveSeek.FragmentLoaded' | When `liveSeek` is used to playback Live VOD and HLS video has completed loading a fragment during seeking. |
-| `LIVE_SEEK_CHANGE` | 'WebRTC.LiveSeek.Change | When `liveSeek` is used, this event notifies on a change of state going from "live" to "vod" and vice versa.
+| `LIVE_SEEK_CHANGE` | 'WebRTC.LiveSeek.Change' | When `liveSeek` is used, this event notifies on a change of state going from "live" to "vod" and vice versa. |
+
+Additionally, the following events are related to ICE connection monitoring when integrating with Statistics:
+| Access | Event Type | Meaning |
+| :--- | :--- | :--- |
+| `CONNECTION_HEALTH_STALE_STATS` | 'WebRTC.Connection.StaleStats' | When monitored statistics for ice connection do not seem to be changing through intervals. |
+| `CONNECTION_HEALTH_STATE_REGRESSION` | 'WebRTC.Connection.StateRegression' | When monitored statistics for ice connection and the status reverts from previously being `success`. |
+| `CONNECTION_HEALTH_EXCESSIVE_RTT` | 'WebRTC.Connection.ExcessiveRTT' | When monitored statistics for ice connection and the Round-Trip-Time being report does not change or rises between intervals. |
+| `CONNECTION_HEALTH_ICE_TIMEOUT` | 'WebRTC.Connection.IceTimeout' | When monitored statistics for ice connection and the timeout of ICE Connection has been reached. Can be defined in the `renegotiationPolicy` attribute of the `init()` configuration. |
# Statistics
@@ -314,6 +325,33 @@ The following is an example of a statistics metadata that is emitted in a `WebRT
}
```
+# Renegotiation Policy
+
+The `renegotiationPolicy` attribute of the `init()` configuration object is used during monitoring - in conjunction with (Statistics)(#statistics), to determine the health lifecycle of the ICE negotiation process and act accodingly.
+
+The policy has the following type structure:
+
+```typescript
+type RenegotiationPolicyType = {
+ type: 'regression' | 'timeout' | 'disconnect'
+ iceTimeoutInterval: number
+}
+```
+
+The following `type` values are:
+
+| Name | Meaning |
+| :--- | :--- |
+| `regression` | When the ICE status has changed from a previously designated `success`. This will not always occur during ICE negotiation failures. |
+| `timeout` | When it has been determined (in conjunction with the `iceTimeoutInterval`), that too much time has elapsed since the start of the negotiation process in order for it to conclude successfully. |
+| `disconnect` | When the peer connection has decided to disconnect after a failure of ICE negotiation. |
+
+Typically, these will be executed in the order defined in the table above, however it should be noted that sometimes a `regression` may not occur in poor connection scenarios. If the process were to fail, both `timeout` and `disconnect` will occur.
+
+The `iceTimeoutInterval` value will be used in conjunction with the `timeout` policy type to take reconnect action. _The default is 5 seconds._
+
+> By default, the `renegotiationPolicy` is not set and will not take action unless defined in the `init()` configuration.
+
# Live Seek
Included in the SDK is the ability to subscribe to a live stream and provide capabilities to seek and playback to previous segments of the stream.
diff --git a/static/lib/red5pro/docs/api/classes/Event.md b/static/lib/red5pro/docs/api/classes/Event.md
index c1219e91..fb492269 100644
--- a/static/lib/red5pro/docs/api/classes/Event.md
+++ b/static/lib/red5pro/docs/api/classes/Event.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/classes/EventEmitter.md b/static/lib/red5pro/docs/api/classes/EventEmitter.md
index 6b7a7936..6e72607c 100644
--- a/static/lib/red5pro/docs/api/classes/EventEmitter.md
+++ b/static/lib/red5pro/docs/api/classes/EventEmitter.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/classes/HLSSubscriber.md b/static/lib/red5pro/docs/api/classes/HLSSubscriber.md
index 1fa2f8bb..bcd3c579 100644
--- a/static/lib/red5pro/docs/api/classes/HLSSubscriber.md
+++ b/static/lib/red5pro/docs/api/classes/HLSSubscriber.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
@@ -32,13 +32,13 @@ HLS Subscriber. Supports playback of HLS streams using the native HLS player in
#### Get Signature
-> **get** **fileURL**(): `string` \| `undefined`
+> **get** **fileURL**(): `undefined` \| `string`
Get the file URL of the HLS stream.
##### Returns
-`string` \| `undefined`
+`undefined` \| `string`
***
@@ -46,49 +46,49 @@ Get the file URL of the HLS stream.
#### Get Signature
-> **get** **options**(): [`HLSSubscriberConfigType`](../type-aliases/HLSSubscriberConfigType.md) \| `undefined`
+> **get** **options**(): `undefined` \| [`HLSSubscriberConfigType`](../type-aliases/HLSSubscriberConfigType.md)
Get the options of the HLS stream.
##### Returns
-[`HLSSubscriberConfigType`](../type-aliases/HLSSubscriberConfigType.md) \| `undefined`
+`undefined` \| [`HLSSubscriberConfigType`](../type-aliases/HLSSubscriberConfigType.md)
## Methods
### getFileURL()
-> **getFileURL**(): `string` \| `undefined`
+> **getFileURL**(): `undefined` \| `string`
Get the file URL of the HLS stream.
#### Returns
-`string` \| `undefined`
+`undefined` \| `string`
***
### getOptions()
-> **getOptions**(): [`HLSSubscriberConfigType`](../type-aliases/HLSSubscriberConfigType.md) \| `undefined`
+> **getOptions**(): `undefined` \| [`HLSSubscriberConfigType`](../type-aliases/HLSSubscriberConfigType.md)
Get the options of the HLS stream.
#### Returns
-[`HLSSubscriberConfigType`](../type-aliases/HLSSubscriberConfigType.md) \| `undefined`
+`undefined` \| [`HLSSubscriberConfigType`](../type-aliases/HLSSubscriberConfigType.md)
***
### getPlayer()
-> **getPlayer**(): `HTMLMediaElement` \| `undefined`
+> **getPlayer**(): `undefined` \| `HTMLMediaElement`
Get the playback element of the HLS stream.
#### Returns
-`HTMLMediaElement` \| `undefined`
+`undefined` \| `HTMLMediaElement`
***
diff --git a/static/lib/red5pro/docs/api/classes/LiveSeekClient.md b/static/lib/red5pro/docs/api/classes/LiveSeekClient.md
index e5aca7f8..fc290e89 100644
--- a/static/lib/red5pro/docs/api/classes/LiveSeekClient.md
+++ b/static/lib/red5pro/docs/api/classes/LiveSeekClient.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
@@ -54,13 +54,13 @@ Optional LiveSeekConfigType to use for configuration.
#### Get Signature
-> **get** **options**(): [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md) \| `undefined`
+> **get** **options**(): `undefined` \| [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md)
Get the options for the WHEP-based Subscriber.
##### Returns
-[`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md) \| `undefined`
+`undefined` \| [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md)
#### Inherited from
@@ -114,6 +114,36 @@ Disable standby mode for the WHEP-based Subscriber. This will signal to the serv
***
+### emit()
+
+> **emit**(`type`, `data`): `void`
+
+Emit an event on the WHEP-based Subscriber.
+
+#### Parameters
+
+##### type
+
+`string`
+
+The type of event to emit.
+
+##### data
+
+`any`
+
+The data to emit.
+
+#### Returns
+
+`void`
+
+#### Inherited from
+
+[`WHEPClient`](WHEPClient.md).[`emit`](WHEPClient.md#emit)
+
+***
+
### enableStandby()
> **enableStandby**(): `void`
@@ -132,13 +162,13 @@ Enable standby mode for the WHEP-based Subscriber. This will signal to the serve
### getDataChannel()
-> **getDataChannel**(): `RTCDataChannel` \| `undefined`
+> **getDataChannel**(): `undefined` \| `RTCDataChannel`
Get the data channel for the WHEP-based Subscriber.
#### Returns
-`RTCDataChannel` \| `undefined`
+`undefined` \| `RTCDataChannel`
#### Inherited from
@@ -148,13 +178,13 @@ Get the data channel for the WHEP-based Subscriber.
### getMediaStream()
-> **getMediaStream**(): `MediaStream` \| `undefined`
+> **getMediaStream**(): `undefined` \| `MediaStream`
Get the media stream being played back by the subscriber.
#### Returns
-`MediaStream` \| `undefined`
+`undefined` \| `MediaStream`
#### Inherited from
@@ -164,13 +194,13 @@ Get the media stream being played back by the subscriber.
### getMessageTransport()
-> **getMessageTransport**(): `MessageTransport` \| `undefined`
+> **getMessageTransport**(): `undefined` \| `MessageTransport`
Get the message transport for the WHEP-based Subscriber.
#### Returns
-`MessageTransport` \| `undefined`
+`undefined` \| `MessageTransport`
#### Inherited from
@@ -180,13 +210,13 @@ Get the message transport for the WHEP-based Subscriber.
### getOptions()
-> **getOptions**(): [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md) \| `undefined`
+> **getOptions**(): `undefined` \| [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md)
Get the options for the WHEP-based Subscriber.
#### Returns
-[`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md) \| `undefined`
+`undefined` \| [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md)
#### Inherited from
@@ -196,13 +226,13 @@ Get the options for the WHEP-based Subscriber.
### getPeerConnection()
-> **getPeerConnection**(): `RTCPeerConnection` \| `undefined`
+> **getPeerConnection**(): `undefined` \| `RTCPeerConnection`
Get the peer connection for the WHEP-based Subscriber.
#### Returns
-`RTCPeerConnection` \| `undefined`
+`undefined` \| `RTCPeerConnection`
#### Inherited from
@@ -212,13 +242,13 @@ Get the peer connection for the WHEP-based Subscriber.
### getPlayer()
-> **getPlayer**(): `HTMLMediaElement` \| `undefined`
+> **getPlayer**(): `undefined` \| `HTMLMediaElement`
Get the media element for the WHEP-based Subscriber.
#### Returns
-`HTMLMediaElement` \| `undefined`
+`undefined` \| `HTMLMediaElement`
#### Inherited from
@@ -284,7 +314,7 @@ LiveSeekConfigType to use for configuration.
### monitorStats()
-> **monitorStats**(`stats?`): [`WHEPClient`](WHEPClient.md)
+> **monitorStats**(`stats?`, `renegotiationPolicy?`): [`WHEPClient`](WHEPClient.md)
Monitor the statistics of the media being delivered to the subscriber over the underlying RTCPeerConnection.
@@ -296,6 +326,12 @@ Monitor the statistics of the media being delivered to the subscriber over the u
The statistics configuration.
+##### renegotiationPolicy?
+
+`RenegotiationPolicyType`
+
+The renegotiation policy configuration.
+
#### Returns
[`WHEPClient`](WHEPClient.md)
@@ -488,7 +524,7 @@ The time to seek to.
### send()
-> **send**(`methodName`, `data`): `Promise`\<`boolean`\> \| `undefined`
+> **send**(`methodName`, `data`): `undefined` \| `Promise`\<`boolean`\>
Send a message to the Red5 Pro Server over the message transport (DataChannel).
@@ -508,7 +544,7 @@ The data to send.
#### Returns
-`Promise`\<`boolean`\> \| `undefined`
+`undefined` \| `Promise`\<`boolean`\>
#### Inherited from
diff --git a/static/lib/red5pro/docs/api/classes/MessageTransportStateEvent.md b/static/lib/red5pro/docs/api/classes/MessageTransportStateEvent.md
index d4af09b6..e1a8e1d8 100644
--- a/static/lib/red5pro/docs/api/classes/MessageTransportStateEvent.md
+++ b/static/lib/red5pro/docs/api/classes/MessageTransportStateEvent.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/classes/PlaybackController.md b/static/lib/red5pro/docs/api/classes/PlaybackController.md
index 51c3197f..59facc2b 100644
--- a/static/lib/red5pro/docs/api/classes/PlaybackController.md
+++ b/static/lib/red5pro/docs/api/classes/PlaybackController.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/classes/PlaybackControls.md b/static/lib/red5pro/docs/api/classes/PlaybackControls.md
index 50c72f04..b0dda0c6 100644
--- a/static/lib/red5pro/docs/api/classes/PlaybackControls.md
+++ b/static/lib/red5pro/docs/api/classes/PlaybackControls.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/classes/PublisherEvent.md b/static/lib/red5pro/docs/api/classes/PublisherEvent.md
index 8008bd71..ab087443 100644
--- a/static/lib/red5pro/docs/api/classes/PublisherEvent.md
+++ b/static/lib/red5pro/docs/api/classes/PublisherEvent.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/classes/SourceHandler.md b/static/lib/red5pro/docs/api/classes/SourceHandler.md
index bbc2a617..713d1af3 100644
--- a/static/lib/red5pro/docs/api/classes/SourceHandler.md
+++ b/static/lib/red5pro/docs/api/classes/SourceHandler.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
@@ -67,13 +67,13 @@ Disconnect the media element.
### getControls()
-> `abstract` **getControls**(): [`PlaybackControls`](PlaybackControls.md) \| `undefined`
+> `abstract` **getControls**(): `undefined` \| [`PlaybackControls`](PlaybackControls.md)
Get the controls for the media element.
#### Returns
-[`PlaybackControls`](PlaybackControls.md) \| `undefined`
+`undefined` \| [`PlaybackControls`](PlaybackControls.md)
***
diff --git a/static/lib/red5pro/docs/api/classes/SourceHandlerImpl.md b/static/lib/red5pro/docs/api/classes/SourceHandlerImpl.md
index 0d02ea3f..7e3b38ed 100644
--- a/static/lib/red5pro/docs/api/classes/SourceHandlerImpl.md
+++ b/static/lib/red5pro/docs/api/classes/SourceHandlerImpl.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
@@ -86,13 +86,13 @@ Disconnect the media element.
### getControls()
-> **getControls**(): [`PlaybackControls`](PlaybackControls.md) \| `undefined`
+> **getControls**(): `undefined` \| [`PlaybackControls`](PlaybackControls.md)
Get the controls for the media element.
#### Returns
-[`PlaybackControls`](PlaybackControls.md) \| `undefined`
+`undefined` \| [`PlaybackControls`](PlaybackControls.md)
#### Overrides
diff --git a/static/lib/red5pro/docs/api/classes/SubscriberEvent.md b/static/lib/red5pro/docs/api/classes/SubscriberEvent.md
index 350efce5..b9a85f87 100644
--- a/static/lib/red5pro/docs/api/classes/SubscriberEvent.md
+++ b/static/lib/red5pro/docs/api/classes/SubscriberEvent.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/classes/WHEPClient.md b/static/lib/red5pro/docs/api/classes/WHEPClient.md
index c0f0ef3c..e1c11581 100644
--- a/static/lib/red5pro/docs/api/classes/WHEPClient.md
+++ b/static/lib/red5pro/docs/api/classes/WHEPClient.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
@@ -61,13 +61,13 @@ Optional RTCWhepSubscriberConfigType to use for configuration.
#### Get Signature
-> **get** **options**(): [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md) \| `undefined`
+> **get** **options**(): `undefined` \| [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md)
Get the options for the WHEP-based Subscriber.
##### Returns
-[`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md) \| `undefined`
+`undefined` \| [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md)
## Methods
@@ -109,6 +109,32 @@ Disable standby mode for the WHEP-based Subscriber. This will signal to the serv
***
+### emit()
+
+> **emit**(`type`, `data`): `void`
+
+Emit an event on the WHEP-based Subscriber.
+
+#### Parameters
+
+##### type
+
+`string`
+
+The type of event to emit.
+
+##### data
+
+`any`
+
+The data to emit.
+
+#### Returns
+
+`void`
+
+***
+
### enableStandby()
> **enableStandby**(): `void`
@@ -123,73 +149,73 @@ Enable standby mode for the WHEP-based Subscriber. This will signal to the serve
### getDataChannel()
-> **getDataChannel**(): `RTCDataChannel` \| `undefined`
+> **getDataChannel**(): `undefined` \| `RTCDataChannel`
Get the data channel for the WHEP-based Subscriber.
#### Returns
-`RTCDataChannel` \| `undefined`
+`undefined` \| `RTCDataChannel`
***
### getMediaStream()
-> **getMediaStream**(): `MediaStream` \| `undefined`
+> **getMediaStream**(): `undefined` \| `MediaStream`
Get the media stream being played back by the subscriber.
#### Returns
-`MediaStream` \| `undefined`
+`undefined` \| `MediaStream`
***
### getMessageTransport()
-> **getMessageTransport**(): `MessageTransport` \| `undefined`
+> **getMessageTransport**(): `undefined` \| `MessageTransport`
Get the message transport for the WHEP-based Subscriber.
#### Returns
-`MessageTransport` \| `undefined`
+`undefined` \| `MessageTransport`
***
### getOptions()
-> **getOptions**(): [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md) \| `undefined`
+> **getOptions**(): `undefined` \| [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md)
Get the options for the WHEP-based Subscriber.
#### Returns
-[`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md) \| `undefined`
+`undefined` \| [`RTCWhepSubscriberConfigType`](../type-aliases/RTCWhepSubscriberConfigType.md)
***
### getPeerConnection()
-> **getPeerConnection**(): `RTCPeerConnection` \| `undefined`
+> **getPeerConnection**(): `undefined` \| `RTCPeerConnection`
Get the peer connection for the WHEP-based Subscriber.
#### Returns
-`RTCPeerConnection` \| `undefined`
+`undefined` \| `RTCPeerConnection`
***
### getPlayer()
-> **getPlayer**(): `HTMLMediaElement` \| `undefined`
+> **getPlayer**(): `undefined` \| `HTMLMediaElement`
Get the media element for the WHEP-based Subscriber.
#### Returns
-`HTMLMediaElement` \| `undefined`
+`undefined` \| `HTMLMediaElement`
***
@@ -243,7 +269,7 @@ RTCWhepSubscriberConfigType to use for configuration.
### monitorStats()
-> **monitorStats**(`stats?`): `WHEPClient`
+> **monitorStats**(`stats?`, `renegotiationPolicy?`): `WHEPClient`
Monitor the statistics of the media being delivered to the subscriber over the underlying RTCPeerConnection.
@@ -255,6 +281,12 @@ Monitor the statistics of the media being delivered to the subscriber over the u
The statistics configuration.
+##### renegotiationPolicy?
+
+`RenegotiationPolicyType`
+
+The renegotiation policy configuration.
+
#### Returns
`WHEPClient`
@@ -435,7 +467,7 @@ The time to seek to.
### send()
-> **send**(`methodName`, `data`): `Promise`\<`boolean`\> \| `undefined`
+> **send**(`methodName`, `data`): `undefined` \| `Promise`\<`boolean`\>
Send a message to the Red5 Pro Server over the message transport (DataChannel).
@@ -455,7 +487,7 @@ The data to send.
#### Returns
-`Promise`\<`boolean`\> \| `undefined`
+`undefined` \| `Promise`\<`boolean`\>
***
diff --git a/static/lib/red5pro/docs/api/classes/WHIPClient.md b/static/lib/red5pro/docs/api/classes/WHIPClient.md
index b774c8d6..09012ff8 100644
--- a/static/lib/red5pro/docs/api/classes/WHIPClient.md
+++ b/static/lib/red5pro/docs/api/classes/WHIPClient.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
@@ -58,13 +58,13 @@ Optional additional options to override defaults.
#### Get Signature
-> **get** **options**(): [`RTCWhipPublisherConfigType`](../type-aliases/RTCWhipPublisherConfigType.md) \| `undefined`
+> **get** **options**(): `undefined` \| [`RTCWhipPublisherConfigType`](../type-aliases/RTCWhipPublisherConfigType.md)
Get the options for the WHIPClient.
##### Returns
-[`RTCWhipPublisherConfigType`](../type-aliases/RTCWhipPublisherConfigType.md) \| `undefined`
+`undefined` \| [`RTCWhipPublisherConfigType`](../type-aliases/RTCWhipPublisherConfigType.md)
## Methods
@@ -94,63 +94,89 @@ The arguments to call the method with.
***
+### emit()
+
+> **emit**(`type`, `data`): `void`
+
+Emit an event on the WHIPClient.
+
+#### Parameters
+
+##### type
+
+`string`
+
+The type of event to emit.
+
+##### data
+
+`any`
+
+The data to emit.
+
+#### Returns
+
+`void`
+
+***
+
### getDataChannel()
-> **getDataChannel**(): `RTCDataChannel` \| `undefined`
+> **getDataChannel**(): `undefined` \| `RTCDataChannel`
Get the DataChannel for the WHIPClient.
#### Returns
-`RTCDataChannel` \| `undefined`
+`undefined` \| `RTCDataChannel`
***
### getMediaStream()
-> **getMediaStream**(): `MediaStream` \| `undefined`
+> **getMediaStream**(): `undefined` \| `MediaStream`
Get the MediaStream generated for the WHIPClient.
#### Returns
-`MediaStream` \| `undefined`
+`undefined` \| `MediaStream`
***
### getMessageTransport()
-> **getMessageTransport**(): `MessageTransport` \| `undefined`
+> **getMessageTransport**(): `undefined` \| `MessageTransport`
Get the MessageTransport for the WHIPClient.
#### Returns
-`MessageTransport` \| `undefined`
+`undefined` \| `MessageTransport`
***
### getOptions()
-> **getOptions**(): [`RTCWhipPublisherConfigType`](../type-aliases/RTCWhipPublisherConfigType.md) \| `undefined`
+> **getOptions**(): `undefined` \| [`RTCWhipPublisherConfigType`](../type-aliases/RTCWhipPublisherConfigType.md)
Get the options for the WHIPClient.
#### Returns
-[`RTCWhipPublisherConfigType`](../type-aliases/RTCWhipPublisherConfigType.md) \| `undefined`
+`undefined` \| [`RTCWhipPublisherConfigType`](../type-aliases/RTCWhipPublisherConfigType.md)
***
### getPeerConnection()
-> **getPeerConnection**(): `RTCPeerConnection` \| `undefined`
+> **getPeerConnection**(): `undefined` \| `RTCPeerConnection`
Get the PeerConnection for the WHIPClient.
#### Returns
-`RTCPeerConnection` \| `undefined`
+`undefined` \| `RTCPeerConnection`
***
@@ -338,7 +364,7 @@ The name of the stream to publish.
### send()
-> **send**(`methodName`, `data`): `Promise`\<`boolean`\> \| `undefined`
+> **send**(`methodName`, `data`): `undefined` \| `Promise`\<`boolean`\>
Send a message to the server.
@@ -358,7 +384,7 @@ The data to send.
#### Returns
-`Promise`\<`boolean`\> \| `undefined`
+`undefined` \| `Promise`\<`boolean`\>
***
diff --git a/static/lib/red5pro/docs/api/enumerations/MessageTransportStateEventTypes.md b/static/lib/red5pro/docs/api/enumerations/MessageTransportStateEventTypes.md
index 2001dceb..579dddaf 100644
--- a/static/lib/red5pro/docs/api/enumerations/MessageTransportStateEventTypes.md
+++ b/static/lib/red5pro/docs/api/enumerations/MessageTransportStateEventTypes.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/PlaybackAudioEncoder.md b/static/lib/red5pro/docs/api/enumerations/PlaybackAudioEncoder.md
index 9010e59c..a8c3b08e 100644
--- a/static/lib/red5pro/docs/api/enumerations/PlaybackAudioEncoder.md
+++ b/static/lib/red5pro/docs/api/enumerations/PlaybackAudioEncoder.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/PlaybackState.md b/static/lib/red5pro/docs/api/enumerations/PlaybackState.md
index 60bcaa5d..7d2454d5 100644
--- a/static/lib/red5pro/docs/api/enumerations/PlaybackState.md
+++ b/static/lib/red5pro/docs/api/enumerations/PlaybackState.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/PlaybackVideoEncoder.md b/static/lib/red5pro/docs/api/enumerations/PlaybackVideoEncoder.md
index 39786e0a..3dd40424 100644
--- a/static/lib/red5pro/docs/api/enumerations/PlaybackVideoEncoder.md
+++ b/static/lib/red5pro/docs/api/enumerations/PlaybackVideoEncoder.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/PublishAudioEncoder.md b/static/lib/red5pro/docs/api/enumerations/PublishAudioEncoder.md
index b2eb2772..983e3fb6 100644
--- a/static/lib/red5pro/docs/api/enumerations/PublishAudioEncoder.md
+++ b/static/lib/red5pro/docs/api/enumerations/PublishAudioEncoder.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/PublishVideoEncoder.md b/static/lib/red5pro/docs/api/enumerations/PublishVideoEncoder.md
index 9c3215de..e4c0833e 100644
--- a/static/lib/red5pro/docs/api/enumerations/PublishVideoEncoder.md
+++ b/static/lib/red5pro/docs/api/enumerations/PublishVideoEncoder.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/PublisherEventTypes.md b/static/lib/red5pro/docs/api/enumerations/PublisherEventTypes.md
index 14e5c506..e8c7c0b4 100644
--- a/static/lib/red5pro/docs/api/enumerations/PublisherEventTypes.md
+++ b/static/lib/red5pro/docs/api/enumerations/PublisherEventTypes.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/RTCPublisherEventTypes.md b/static/lib/red5pro/docs/api/enumerations/RTCPublisherEventTypes.md
index 5f01effe..bac86223 100644
--- a/static/lib/red5pro/docs/api/enumerations/RTCPublisherEventTypes.md
+++ b/static/lib/red5pro/docs/api/enumerations/RTCPublisherEventTypes.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/RTCSubscriberEventTypes.md b/static/lib/red5pro/docs/api/enumerations/RTCSubscriberEventTypes.md
index b0a30c7e..6e5a6cf2 100644
--- a/static/lib/red5pro/docs/api/enumerations/RTCSubscriberEventTypes.md
+++ b/static/lib/red5pro/docs/api/enumerations/RTCSubscriberEventTypes.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/enumerations/SubscriberEventTypes.md b/static/lib/red5pro/docs/api/enumerations/SubscriberEventTypes.md
index 3d7bddf6..5edff0b1 100644
--- a/static/lib/red5pro/docs/api/enumerations/SubscriberEventTypes.md
+++ b/static/lib/red5pro/docs/api/enumerations/SubscriberEventTypes.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
@@ -74,6 +74,12 @@
***
+### RECONNECT\_START
+
+> **RECONNECT\_START**: `"Reconnect.Start"`
+
+***
+
### SEEK\_CHANGE
> **SEEK\_CHANGE**: `"Subscribe.Seek.Change"`
diff --git a/static/lib/red5pro/docs/api/functions/getRecordedLogs.md b/static/lib/red5pro/docs/api/functions/getRecordedLogs.md
index d94ea898..762a2896 100644
--- a/static/lib/red5pro/docs/api/functions/getRecordedLogs.md
+++ b/static/lib/red5pro/docs/api/functions/getRecordedLogs.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/functions/getVersion.md b/static/lib/red5pro/docs/api/functions/getVersion.md
index e09fbd5f..915d5ff8 100644
--- a/static/lib/red5pro/docs/api/functions/getVersion.md
+++ b/static/lib/red5pro/docs/api/functions/getVersion.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/functions/setLogLevel.md b/static/lib/red5pro/docs/api/functions/setLogLevel.md
index b0396b51..687c2c7a 100644
--- a/static/lib/red5pro/docs/api/functions/setLogLevel.md
+++ b/static/lib/red5pro/docs/api/functions/setLogLevel.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/globals.md b/static/lib/red5pro/docs/api/globals.md
index ae954a86..3c7f9af9 100644
--- a/static/lib/red5pro/docs/api/globals.md
+++ b/static/lib/red5pro/docs/api/globals.md
@@ -1,8 +1,8 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](README.md)
***
-# Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189
+# Red5 Pro WebRTC SDK v15.2.0
Red5 Pro WebRTC SDK
diff --git a/static/lib/red5pro/docs/api/interfaces/EventEmitterInterface.md b/static/lib/red5pro/docs/api/interfaces/EventEmitterInterface.md
index 5a1450b1..3a14c528 100644
--- a/static/lib/red5pro/docs/api/interfaces/EventEmitterInterface.md
+++ b/static/lib/red5pro/docs/api/interfaces/EventEmitterInterface.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/BandwidthConfig.md b/static/lib/red5pro/docs/api/type-aliases/BandwidthConfig.md
index 81545888..1abed477 100644
--- a/static/lib/red5pro/docs/api/type-aliases/BandwidthConfig.md
+++ b/static/lib/red5pro/docs/api/type-aliases/BandwidthConfig.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/HLSSubscriberConfigType.md b/static/lib/red5pro/docs/api/type-aliases/HLSSubscriberConfigType.md
index 44cf96c6..0bfea2f7 100644
--- a/static/lib/red5pro/docs/api/type-aliases/HLSSubscriberConfigType.md
+++ b/static/lib/red5pro/docs/api/type-aliases/HLSSubscriberConfigType.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/LiveSeekConfigType.md b/static/lib/red5pro/docs/api/type-aliases/LiveSeekConfigType.md
index 13359b28..b8390ebd 100644
--- a/static/lib/red5pro/docs/api/type-aliases/LiveSeekConfigType.md
+++ b/static/lib/red5pro/docs/api/type-aliases/LiveSeekConfigType.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/LiveSeekOptions.md b/static/lib/red5pro/docs/api/type-aliases/LiveSeekOptions.md
index b2cbab0a..afce9216 100644
--- a/static/lib/red5pro/docs/api/type-aliases/LiveSeekOptions.md
+++ b/static/lib/red5pro/docs/api/type-aliases/LiveSeekOptions.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/MediaConstraintRange.md b/static/lib/red5pro/docs/api/type-aliases/MediaConstraintRange.md
index 8ae0035e..bfab138e 100644
--- a/static/lib/red5pro/docs/api/type-aliases/MediaConstraintRange.md
+++ b/static/lib/red5pro/docs/api/type-aliases/MediaConstraintRange.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/MediaConstraints.md b/static/lib/red5pro/docs/api/type-aliases/MediaConstraints.md
index 7d41963e..333fef12 100644
--- a/static/lib/red5pro/docs/api/type-aliases/MediaConstraints.md
+++ b/static/lib/red5pro/docs/api/type-aliases/MediaConstraints.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/RTCPublisherConfigType.md b/static/lib/red5pro/docs/api/type-aliases/RTCPublisherConfigType.md
index 245a4176..ac9617e9 100644
--- a/static/lib/red5pro/docs/api/type-aliases/RTCPublisherConfigType.md
+++ b/static/lib/red5pro/docs/api/type-aliases/RTCPublisherConfigType.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/RTCSubscriberConfigType.md b/static/lib/red5pro/docs/api/type-aliases/RTCSubscriberConfigType.md
index 8b07ace8..eff0c725 100644
--- a/static/lib/red5pro/docs/api/type-aliases/RTCSubscriberConfigType.md
+++ b/static/lib/red5pro/docs/api/type-aliases/RTCSubscriberConfigType.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
@@ -124,6 +124,12 @@
***
+### renegotiationPolicy?
+
+> `optional` **renegotiationPolicy**: `RenegotiationPolicyType`
+
+***
+
### rtcConfiguration
> **rtcConfiguration**: `RTCConfiguration`
diff --git a/static/lib/red5pro/docs/api/type-aliases/RTCWhepSubscriberConfigType.md b/static/lib/red5pro/docs/api/type-aliases/RTCWhepSubscriberConfigType.md
index d344ef4c..f01410d6 100644
--- a/static/lib/red5pro/docs/api/type-aliases/RTCWhepSubscriberConfigType.md
+++ b/static/lib/red5pro/docs/api/type-aliases/RTCWhepSubscriberConfigType.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/RTCWhipPublisherConfigType.md b/static/lib/red5pro/docs/api/type-aliases/RTCWhipPublisherConfigType.md
index d1538bd2..4845ca4c 100644
--- a/static/lib/red5pro/docs/api/type-aliases/RTCWhipPublisherConfigType.md
+++ b/static/lib/red5pro/docs/api/type-aliases/RTCWhipPublisherConfigType.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/StatsConfig.md b/static/lib/red5pro/docs/api/type-aliases/StatsConfig.md
index e6e71960..73cf3734 100644
--- a/static/lib/red5pro/docs/api/type-aliases/StatsConfig.md
+++ b/static/lib/red5pro/docs/api/type-aliases/StatsConfig.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/type-aliases/VideoConstraints.md b/static/lib/red5pro/docs/api/type-aliases/VideoConstraints.md
index 44487a8a..fb6f39d0 100644
--- a/static/lib/red5pro/docs/api/type-aliases/VideoConstraints.md
+++ b/static/lib/red5pro/docs/api/type-aliases/VideoConstraints.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/variables/LOG_LEVELS.md b/static/lib/red5pro/docs/api/variables/LOG_LEVELS.md
index dcb79c1f..b2b83744 100644
--- a/static/lib/red5pro/docs/api/variables/LOG_LEVELS.md
+++ b/static/lib/red5pro/docs/api/variables/LOG_LEVELS.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/variables/PlaybackStateReadableMap.md b/static/lib/red5pro/docs/api/variables/PlaybackStateReadableMap.md
index 2aa92a8d..ee043b40 100644
--- a/static/lib/red5pro/docs/api/variables/PlaybackStateReadableMap.md
+++ b/static/lib/red5pro/docs/api/variables/PlaybackStateReadableMap.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/variables/default.md b/static/lib/red5pro/docs/api/variables/default.md
index 824dcbf6..883c8bae 100644
--- a/static/lib/red5pro/docs/api/variables/default.md
+++ b/static/lib/red5pro/docs/api/variables/default.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/variables/defaultHLSSubscriberConfig.md b/static/lib/red5pro/docs/api/variables/defaultHLSSubscriberConfig.md
index adfe5d15..e52e10a0 100644
--- a/static/lib/red5pro/docs/api/variables/defaultHLSSubscriberConfig.md
+++ b/static/lib/red5pro/docs/api/variables/defaultHLSSubscriberConfig.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/variables/defaultLiveSeekConfig.md b/static/lib/red5pro/docs/api/variables/defaultLiveSeekConfig.md
index 5234f1c9..e247db57 100644
--- a/static/lib/red5pro/docs/api/variables/defaultLiveSeekConfig.md
+++ b/static/lib/red5pro/docs/api/variables/defaultLiveSeekConfig.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/variables/defaultStatsConfig.md b/static/lib/red5pro/docs/api/variables/defaultStatsConfig.md
index 3d39ae49..cd33dabe 100644
--- a/static/lib/red5pro/docs/api/variables/defaultStatsConfig.md
+++ b/static/lib/red5pro/docs/api/variables/defaultStatsConfig.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/variables/defaultWhepSubscriberConfig.md b/static/lib/red5pro/docs/api/variables/defaultWhepSubscriberConfig.md
index 4d63fca6..6070df32 100644
--- a/static/lib/red5pro/docs/api/variables/defaultWhepSubscriberConfig.md
+++ b/static/lib/red5pro/docs/api/variables/defaultWhepSubscriberConfig.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/docs/api/variables/defaultWhipPublisherConfig.md b/static/lib/red5pro/docs/api/variables/defaultWhipPublisherConfig.md
index 8d24b8f6..aff1884b 100644
--- a/static/lib/red5pro/docs/api/variables/defaultWhipPublisherConfig.md
+++ b/static/lib/red5pro/docs/api/variables/defaultWhipPublisherConfig.md
@@ -1,4 +1,4 @@
-[**Red5 Pro WebRTC SDK vNEW-15.0.0.11-release.b189**](../README.md)
+[**Red5 Pro WebRTC SDK v15.2.0**](../README.md)
***
diff --git a/static/lib/red5pro/hls-subscriber.md b/static/lib/red5pro/docs/hls-subscriber.md
similarity index 100%
rename from static/lib/red5pro/hls-subscriber.md
rename to static/lib/red5pro/docs/hls-subscriber.md
diff --git a/static/lib/red5pro/whep-client.md b/static/lib/red5pro/docs/whep-client.md
similarity index 89%
rename from static/lib/red5pro/whep-client.md
rename to static/lib/red5pro/docs/whep-client.md
index 3644809b..f583a080 100644
--- a/static/lib/red5pro/whep-client.md
+++ b/static/lib/red5pro/docs/whep-client.md
@@ -21,6 +21,7 @@ This provides a standardized - and _blazingly fast_ - way to establish and playb
* [Init Configuration](#init-configuration)
* [Events](#events)
* [Statistics](#statistics)
+* [Renegotiation Policy](#renegotiation-policy)
* [Live Seek](#live-seek)
* [Stream Manager 2.0](#stream-manager-20)
@@ -118,6 +119,7 @@ When using the `init()` call of a `WHEPClient` - or, alternatively, when using a
| `maintainStreamVariant` | [-] | `false` | Flag to instruct the server - when utilizing transcoding - to not switch subscriber stream variants when network conditions change. By setting this to `true`, when you request to playback a stream that is transcoded, the server will not deliver a variant of higher or lower quality dependending on current network conditions. |
| `stats` | [-] | *None* | Configuration object to enable stats reporting. See [Stats Reporting](#statistics) for more information. |
| `liveSeek` | [-] | *None* | Configuration object to enable live seek capability. See [Live Seek](#live-seek) for more information. |
+| `renegotiationPolicy` | [-] | *None* | Configuration object for renegotiation of ICE. See [Renegotiation Policy](#renegotiation-policy) for more information. |
# Events
@@ -155,6 +157,7 @@ You can also listen to events individually. The following describe the various e
| :--- | :--- | :--- |
| `CONNECT_SUCCESS` | 'Connect.Success' | When the subscriber has established a required remote connection, such as to a WebSocket server. |
| `CONNECT_FAILURE` | 'Connect.Failure' | When the subscriber has failed to establish a required remote connection for consuming a stream. |
+| `RECONNECT_START` | 'Reconnect.Start' | Signal when attempt on reconnect has begun. This is used in conjunction with the `renegotiationPolicy` of the `init()` configuration. |
| `SUBSCRIBE_START` | 'Subscribe.Start' | When the subscriber has started a subscribing to a stream. |
| `SUBSCRIBE_STOP` | 'Subscribe.Stop' | When the subscriber has successfully closed an active subscription to a stream. |
| `SUBSCRIBE_METADATA` | 'Subscribe.Metadata' | When metadata is received on the client from the server. |
@@ -196,7 +199,15 @@ In addition to the above events, the following events are also dispatched from a
| `LIVE_SEEK_ERROR` | 'WebRTC.LiveSeek.Error' | When `liveSeek` is used to playback Live VOD and HLS video and an error in playback has occurred. Inspect the `error` attribute on the event for more details. |
| `LIVE_SEEK_LOADING` | 'WebRTC.LiveSeek.FragmentLoading' | When `liveSeek` is used to playback Live VOD and HLS video in currently loading a fragment during seeking. |
| `LIVE_SEEK_LOADED` | 'WebRTC.LiveSeek.FragmentLoaded' | When `liveSeek` is used to playback Live VOD and HLS video has completed loading a fragment during seeking. |
-| `LIVE_SEEK_CHANGE` | 'WebRTC.LiveSeek.Change | When `liveSeek` is used, this event notifies on a change of state going from "live" to "vod" and vice versa.
+| `LIVE_SEEK_CHANGE` | 'WebRTC.LiveSeek.Change' | When `liveSeek` is used, this event notifies on a change of state going from "live" to "vod" and vice versa. |
+
+Additionally, the following events are related to ICE connection monitoring when integrating with Statistics:
+| Access | Event Type | Meaning |
+| :--- | :--- | :--- |
+| `CONNECTION_HEALTH_STALE_STATS` | 'WebRTC.Connection.StaleStats' | When monitored statistics for ice connection do not seem to be changing through intervals. |
+| `CONNECTION_HEALTH_STATE_REGRESSION` | 'WebRTC.Connection.StateRegression' | When monitored statistics for ice connection and the status reverts from previously being `success`. |
+| `CONNECTION_HEALTH_EXCESSIVE_RTT` | 'WebRTC.Connection.ExcessiveRTT' | When monitored statistics for ice connection and the Round-Trip-Time being report does not change or rises between intervals. |
+| `CONNECTION_HEALTH_ICE_TIMEOUT` | 'WebRTC.Connection.IceTimeout' | When monitored statistics for ice connection and the timeout of ICE Connection has been reached. Can be defined in the `renegotiationPolicy` attribute of the `init()` configuration. |
# Statistics
@@ -314,6 +325,33 @@ The following is an example of a statistics metadata that is emitted in a `WebRT
}
```
+# Renegotiation Policy
+
+The `renegotiationPolicy` attribute of the `init()` configuration object is used during monitoring - in conjunction with (Statistics)(#statistics), to determine the health lifecycle of the ICE negotiation process and act accodingly.
+
+The policy has the following type structure:
+
+```typescript
+type RenegotiationPolicyType = {
+ type: 'regression' | 'timeout' | 'disconnect'
+ iceTimeoutInterval: number
+}
+```
+
+The following `type` values are:
+
+| Name | Meaning |
+| :--- | :--- |
+| `regression` | When the ICE status has changed from a previously designated `success`. This will not always occur during ICE negotiation failures. |
+| `timeout` | When it has been determined (in conjunction with the `iceTimeoutInterval`), that too much time has elapsed since the start of the negotiation process in order for it to conclude successfully. |
+| `disconnect` | When the peer connection has decided to disconnect after a failure of ICE negotiation. |
+
+Typically, these will be executed in the order defined in the table above, however it should be noted that sometimes a `regression` may not occur in poor connection scenarios. If the process were to fail, both `timeout` and `disconnect` will occur.
+
+The `iceTimeoutInterval` value will be used in conjunction with the `timeout` policy type to take reconnect action. _The default is 5 seconds._
+
+> By default, the `renegotiationPolicy` is not set and will not take action unless defined in the `init()` configuration.
+
# Live Seek
Included in the SDK is the ability to subscribe to a live stream and provide capabilities to seek and playback to previous segments of the stream.
diff --git a/static/lib/red5pro/whip-client.md b/static/lib/red5pro/docs/whip-client.md
similarity index 100%
rename from static/lib/red5pro/whip-client.md
rename to static/lib/red5pro/docs/whip-client.md
diff --git a/static/lib/red5pro/index.d.ts b/static/lib/red5pro/index.d.ts
index 6c7032ff..f842416f 100644
--- a/static/lib/red5pro/index.d.ts
+++ b/static/lib/red5pro/index.d.ts
@@ -19,6 +19,7 @@ import WhipWhepSignalingHelper from 'helper/wish-signal-helper';
import { PlaybackView } from 'view/playback';
import RTCPeerConnectionSubscriber from 'helper/peer-connection-sub';
import RTCSubscriberStats from 'stats/subscriber-stats';
+import { RenegotiationPolicyType } from 'configuration';
import { LiveSeekConfigType } from 'configuration/liveseek';
export { LiveSeekConfigType, LiveSeekOptions, defaultLiveSeekConfig } from 'configuration/liveseek';
import { PublisherEventTypes, SubscriberEventTypes, RTCPublisherEventTypes, RTCSubscriberEventTypes, MessageTransportStateEventTypes } from 'event/event-types';
@@ -256,6 +257,13 @@ declare class WHIPClient extends EventEmitter$1 {
* @param {Event} event - The event to trigger.
*/
trigger(event: Event$1): void;
+ /**
+ * Emit an event on the WHIPClient.
+ *
+ * @param {string} type - The type of event to emit.
+ * @param {any} data - The data to emit.
+ */
+ emit(type: string, data: any): void;
/**
* Get the type of the WHIPClient (RTC).
*
@@ -539,6 +547,8 @@ declare class WHEPClient extends PlaybackController {
private requestAnswer;
private sendAnswer;
private postCandidateFragments;
+ private _evaluateRenegotiationPolicy;
+ private _reconnect;
/**
* Initialize the WHEP-based Subscriber.
*
@@ -724,9 +734,10 @@ declare class WHEPClient extends PlaybackController {
* Monitor the statistics of the media being delivered to the subscriber over the underlying RTCPeerConnection.
*
* @param {StatsConfig | undefined} stats - The statistics configuration.
+ * @param {RenegotiationPolicyType | undefined} renegotiationPolicy - The renegotiation policy configuration.
* @returns {WHEPClient}
*/
- monitorStats(stats?: StatsConfig | undefined): WHEPClient;
+ monitorStats(stats?: StatsConfig | undefined, renegotiationPolicy?: RenegotiationPolicyType | undefined): WHEPClient;
/**
* Unmonitor the statistics of the media being delivered to the subscriber over the underlying RTCPeerConnection.
*
@@ -773,6 +784,13 @@ declare class WHEPClient extends PlaybackController {
* @param {Event} event - The event to trigger.
*/
trigger(event: Event$1): void;
+ /**
+ * Emit an event on the WHEP-based Subscriber.
+ *
+ * @param {string} type - The type of event to emit.
+ * @param {any} data - The data to emit.
+ */
+ emit(type: string, data: any): void;
/**
* Get the type of the WHEP-based Subscriber (RTC).
*
diff --git a/static/lib/red5pro/red5pro-media.css b/static/lib/red5pro/red5pro-media.css
index a58700e2..f102f34b 100644
--- a/static/lib/red5pro/red5pro-media.css
+++ b/static/lib/red5pro/red5pro-media.css
@@ -47,8 +47,8 @@
}
input[type=range][orient=vertical] {
- writing-mode: bt-lr; /* IE */
- -webkit-appearance: slider-vertical; /* WebKit */
+ writing-mode: vertical-lr;
+ direction: rtl;
width: 8px;
height: 175px;
padding: 0 5px;
diff --git a/static/lib/red5pro/red5pro-sdk.esm.min.js b/static/lib/red5pro/red5pro-sdk.esm.min.js
index 992b092b..df3a7327 100644
--- a/static/lib/red5pro/red5pro-sdk.esm.min.js
+++ b/static/lib/red5pro/red5pro-sdk.esm.min.js
@@ -1,8 +1,8 @@
/**
*
- * red5pro-html-sdk-ts - Red5 Pro HTML SDK - TypeScript Edition
+ * red5pro-html-sdk - Red5 Pro HTML SDK
* Author: Infrared5 Inc.
- * Version: NEW-15.0.0.11-release.b189
+ * Version: 15.2.0
* Url: https://www.red5.net
*
* Copyright © 2015 Infrared5, Inc. All rights reserved.
@@ -31,4 +31,4 @@
*
*/
-var e,t,i,n;!function(e){e.OPUS="OPUS",e.NONE="NONE"}(e||(e={})),function(e){e.VP8="VP8",e.H264="H264",e.H265="H265",e.NONE="NONE"}(t||(t={})),function(e){e[e.UNAVAILABLE=1e3]="UNAVAILABLE",e[e.AVAILABLE=0]="AVAILABLE",e[e.IDLE=1]="IDLE",e[e.PLAYING=2]="PLAYING",e[e.PAUSED=3]="PAUSED"}(i||(i={})),function(e){e.UNAVAILABLE="Playback.UNAVAILABLE",e.AVAILABLE="Playback.AVAILABLE",e.IDLE="Playback.IDLE",e.PLAYING="Playback.PLAYING",e.PAUSED="Playback.PAUSED"}(n||(n={}));const s={[i.UNAVAILABLE]:n.UNAVAILABLE,[i.AVAILABLE]:n.AVAILABLE,[i.IDLE]:n.IDLE,[i.PLAYING]:n.PLAYING,[i.PAUSED]:n.PAUSED};var o,a,r,l;!function(e){e.RTMP="rtmp",e.RTC="rtc"}(o||(o={})),function(e){e.LIVE="live",e.RECORD="record",e.APPEND="append"}(a||(a={})),function(e){e.OPUS="OPUS"}(r||(r={})),function(e){e.VP8="VP8",e.H264="H264",e.H265="H265"}(l||(l={}));var d={trace:10,debug:20,info:30,warn:40,error:50,fatal:60},h={};function c(e){return"string"==typeof e?d[e.toLowerCase()]:e}function u(e,t){return u=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},u(e,t)}function p(e,t,i){return p=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct:function(e,t,i){var n=[null];n.push.apply(n,t);var s=new(Function.bind.apply(e,n));return i&&u(s,i.prototype),s},p.apply(null,arguments)}function _(e){if(null==e)return e;if(Array.isArray(e))return e.slice();if("object"==typeof e){var t={};return Object.keys(e).forEach(function(i){t[i]=e[i]}),t}return e}function m(e){return void 0===e?"undefined":null===e?"null":Array.isArray(e)?"[ "+e.map(function(e){return m(e)}).join(", ")+" ]":"object"==typeof e?JSON.stringify(e):"function"==typeof e?"[Function: "+e.name+"]":"boolean"==typeof e||"number"==typeof e?e:"'"+e.toString()+"'"}function g(e){if("string"!=typeof e){for(var t=new Array(arguments.length),i=0;i=o)return e;switch(e){case"%s":return String(s[n++]);case"%d":return Number(s[n++]);case"%j":try{return JSON.stringify(s[n++])}catch(e){return"[Circular]"}default:return e}}),r=s[n];ne||(s=function(s){var o;s[0]instanceof Error?(i={err:t.serializers&&t.serializers.err?t.serializers.err(s[0]):w.err(s[0])},o={err:!0},n=1===s.length?[i.err.message]:Array.prototype.slice.call(s,1)):"object"!=typeof s[0]&&null!==s[0]||Array.isArray(s[0])?(i=null,n=Array.prototype.slice.call(s)):(i=s[0],n=1===s.length&&i.err&&i.err instanceof Error?[i.err.message]:Array.prototype.slice.call(s,1));var a=_(t.fields);a.level=e;var r=i?_(i):null;if(r&&(t.serializers&&t._applySerializers(r,o),Object.keys(r).forEach(function(e){a[e]=r[e]})),a.levelName=h[e],a.msg=n.length?g.apply(t,n):"",a.time||(a.time=new Date),t.src&&!a.src)try{throw new Error("call-stack-error")}catch(e){var l=e.stack?function(e,t){var i=e.split("\n");i[0]&&i[0].indexOf("call-stack-error")>=0&&i.shift();var n=i[t],s=null;if(n){var o=/^\s*(at|.*@)\s*(.+)?$/.exec(n);s=Array.isArray(o)&&o[2]?o[2]:n}return s}(e.stack,2):"";l||function(e){return v[e]}("src")||S("Unable to determine src line info","src"),a.src=l||""}return a.v=1,a}(n),this._emit(s))}}function b(e){var t=e.stack||e.toString();if(e.cause&&"function"==typeof e.cause){var i=e.cause();i&&(t+="\nCaused by: "+b(i))}return t}C.prototype.trace=f(10),C.prototype.debug=f(20),C.prototype.info=f(30),C.prototype.warn=f(40),C.prototype.error=f(50),C.prototype.fatal=f(60);var w={err:function(e){return e&&e.stack?{message:e.message,name:e.name,stack:b(e),code:e.code,signal:e.signal}:e}};const A={10:"TRACE",20:"DEBUG",30:"INFO",40:"WARN",50:"ERROR",60:"FATAL"};class y{write(e){console.log("%s - [%s] %s: %s",e.time.toISOString(),e.name,A[e.level]||"UNKNOWN",e.msg)}}let T,L;const P=e=>(t,i)=>{var n;T&&"function"==typeof T[e]&&T[e]((n=t,e=>`(${n}) ${e}`)(i))},N={TRACE:"trace",INFO:"info",DEBUG:"debug",WARN:"warn",ERROR:"error",FATAL:"fatal"},D=(e,t=!1,i)=>{const n=[{level:e,stream:new y,type:"raw"}];if(i){const t=i.map(t=>({...t,level:e}));n.push(...t)}t&&(L=[],n.push({level:e,stream:{write:t=>{const i=`[${t.time.toISOString()}] ${e.toUpperCase()}: ${t.msg}`;null==L||L.push(i)}},type:"raw"}));T=function(){return p(C,[].slice.call(arguments))}({level:e,name:"red5pro-sdk",streams:n})},R=()=>(T||D(N.INFO),T),H=()=>L||[];P(N.TRACE),P(N.INFO);const I=P(N.DEBUG),O=P(N.WARN),k=P(N.ERROR);P(N.FATAL);const M="RED5PRO";class U{constructor(){this._callbacks={},this._callbacks[M]=[]}_notify(e,t){let i;const n=e.length;for(i=0;i1&&(s=V.exec(e),n[1]===t&&s&&s.length>1)?s[1]:void 0}}function W(e){const t=G(e,"orientation");if(t)return{orientation:parseInt(t)}}function x(e){const t=G(e,"streamingMode");if(t)return{streamingMode:t}}const j=e=>F.get(e),K=e=>{const t=e.textTracks;t&&(e.addTextTrack("metadata"),t.addEventListener("addtrack",t=>{const i=t.track;i.mode="hidden",i.addEventListener("cuechange",t=>{let n,s;for(t&&t.currentTarget?n=t.currentTarget.cues:(n=i.cues,n=n&&n.length>0?n:i.activeCues),n=n||[],s=0;s{e(n)}),s&&o&&o.streamingMode&&o.streamingMode.forEach(e=>{e(s)})}}})}))},z="BrowserEnvironment",J=e=>I(z,e),Y=e=>O(z,e);let q=[];const Q=()=>{const e=screen.orientation?screen.orientation.angle:void 0,t=void 0===e?window.matchMedia("(orientation: portrait)").matches?0:90:e,i=q.length;J(`[window:onorientationchange]: orientation(${t}).`);for(let e=0;e{const e=document.createElement("video");return e.canPlayType("application/vnd.apple.mpegURL").length>0||e.canPlayType("application/x-mpegURL").length>0||e.canPlayType("audio/mpegurl").length>0||e.canPlayType("audio/x-mpegurl").length>0},te="undefined"!=typeof window&&window.adapter;var ie={gUM:async e=>navigator.mediaDevices.getUserMedia(e),createElement:e=>document.createElement(e),resolveElement:e=>document.getElementById(e),getElementId:e=>e.id,setVideoSource:(e,t,i)=>{if(e.srcObject=t,i)try{const t=e.play();t&&t.then(()=>J("[setVideoSource:action]: play (START)")).catch(t=>{Y(`[setVideoSource:action]: play (CATCH::FAULT) ${t.message}`);try{e.setAttribute("autoplay","false"),e.pause()}catch(e){Y(`[setVideoSource:action]: pause (CATCH::FAULT) ${e.message}`)}})}catch(e){Y(`[setVideoSource:action]: play (CATCH::FAULT) ${e.message}`)}},hasAttributeDefined:(e,t)=>e.hasAttribute(t),addOrientationChangeHandler:(e,t=!0)=>{"onorientationchange"in window&&(J("[window:orientation:addOrientationChangeHandler]: add"),q.push(e),t&&Q()),1===q.length&&(J("[window:orientation:addOrientationChangeHandler]: add"),window.addEventListener("orientationchange",Q))},removeOrientationChangeHandler:e=>{q=q.filter(t=>t!==e),0===q.length&&window.removeEventListener("orientationchange",Q)},toggleFullScreen:e=>{window.screenfull&&window.screenfull.enabled?window.screenfull.toggle(e):document.fullscreenEnabled&&(document.fullscreenElement&&document.fullscreenElement===e?document.exitFullscreen():e.requestFullscreen())},onFullScreenStateChange:e=>{var t;Z.push(e),t=window.screenfull,X||(X=!0,window.screenfull?window.screenfull.on("change",()=>{Z.forEach(e=>e(t.isFullscreen))}):document.fullscreenEnabled&&document.addEventListener("fullscreenchange",()=>{Z.forEach(e=>e(null!==document.fullscreenElement))}))},getOrGenerateFingerprint:()=>{const e=window.localStorage;if(e&&e.getItem("red5_fingerprint"))return e.getItem("red5_fingerprint");let t;try{t=window.crypto.randomUUID()}catch(e){t="10000000-1000-4000-8000-100000000000".replace(/[018]/g,e=>(Number(e)^crypto.getRandomValues(new Uint8Array(1))[0]&15>>Number(e)/4).toString(16))}return e.setItem("red5_fingerprint",t),t},getBrowserDetails:()=>{const e=void 0!==window.adapter,{navigator:t,adapter:i}=window,{appVersion:n,platform:s,userAgent:o,vendor:a}=t,r={appVersion:n,platform:s,userAgent:o,vendor:a};return e?{...i.browserDetails,...r}:r},supportsHLS:ee,onOrientationMetadata:(e,t)=>{const i=F.get(e);F.has(e)?Object.prototype.hasOwnProperty.call(i,"orientation")||(F.get(e).orientation=[]):(K(e),F.set(e,{orientation:[]})),F.get(e).orientation.push(t)},onStreamingModeMetadata:(e,t)=>{const i=F.get(e);F.has(e)?Object.prototype.hasOwnProperty.call(i,"streamingMode")||(F.get(e).streamingMode=[]):(K(e),F.set(e,{streamingMode:[]})),F.get(e).streamingMode.push(t)},isTouchEnabled:()=>"ontouchstart"in window,isPossiblySafari:()=>te?"safari"===window.adapter.browserDetails.browser.toLowerCase():ee(),findByQuerySelector:e=>document.querySelector(e),addGlobalEventListener:(e,t,i=document)=>{i.addEventListener(e,t)},removeGlobalEventListener:(e,t,i=document)=>{i.removeEventListener(e,t)},supportsNonNativeHLS:e=>{if(e)try{return e.isSupported()}catch(e){return Y("Could not access Hls.js."),!1}return!!window.Hls&&window.Hls.isSupported()},createHLSClient:(e={})=>new window.Hls(e),getHLSClientEventEnum:()=>window.Hls.Events,globalAssign:(e,t)=>{window[e]=t},globalUnassign:e=>{delete window[e]},getAssignedValue:e=>window[e]};const ne=(e,t,i)=>{const{liveSeek:{baseURL:n,fullURL:s}}=e,{host:o,protocol:a,port:r,app:l,streamName:d}=e;if(i||s)return i||s;const h=o,c="ws"===a?"http":"https",u=5080===r?5080:443,p=l,_=t||n;if(_){const e=_.length-1;return`${"/"===_.charAt(e)?_.substring(0,e):_}/${p}/${d}.m3u8`}return`${c}://${h}:${u}/${p}/${d}.m3u8`},se=e=>{const t=new URL(e),i=t.pathname.split("/").filter(e=>e.length>0),n="https:"===t.protocol?"https":"http",s=t.hostname;return{protocol:n,port:t.port.length>0?t.port:443,app:i[0],host:s,streamName:i[i.length-1]}},oe=(e,t="whip")=>{var i;const{endpoint:n,proxy:s}=e;if(n)return n;{const{protocol:n,host:o,port:a,app:r,streamName:l}=e,d=n.match(/^http/)?n:"ws"===n?"http":"https";return(null==s?void 0:s.enabled)?`${d}://${o}:${a}/as/${null!==(i=s.version)&&void 0!==i?i:"v1"}/proxy/${t}/${r}/${l}`:`${d}://${o}:${a}/${r}/${t}/endpoint/${l}`}},ae=e=>{const t={audio:!1,video:!1},i={audio:!1,video:!1};return e.getTracks().forEach(e=>{"video"===e.kind?(i.video=e.getSettings(),t.video=e.getConstraints()):"audio"===e.kind&&(i.audio=e.getSettings(),t.audio=e.getConstraints())}),{requested:t,accepted:i}},re=e=>{const t=e.length;return function i(...n){return n.length>=t?e(...n):function(...e){return i(...n,...e)}}},le=re((e,t)=>{let i=0;const n=t.length,s=[];for(;i{this._responder.onDataChannelError(e,t.error.message)},e.onmessage=e=>{this._onDataChannelMessage(e)},e.onopen=()=>{this._responder.onDataChannelOpen(e)},e.onclose=t=>{this._responder.onDataChannelClose(e),this.trigger(new Se(we.CLOSE,this._name,{socket:this,event:t}))}}_isErrorMessage(e){return!("error"!==(null==e?void 0:e.type)||!(null==e?void 0:e.message)&&!(null==e?void 0:e.code))}_isStatusMessage(e){return!("status"!==(null==e?void 0:e.type))}_onDataChannelMessage(e){if(this.handleMessageResponse(e))return!0;const t=this.getJsonFromSocketMessage(e);return t?(I(this._name,`[datachannel-response]: ${JSON.stringify(t,null,2)}`),this._handleMessageContent(t)):(O(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0)}_handleMessageContent(e){const{async:t,data:i,method:n,send:s,type:o,id:a}=e;if(this._isErrorMessage(i)){const e=(null==i?void 0:i.message)||(null==i?void 0:i.code);if(e)return this._responder.onDataChannelError(this._dataChannel,e),!0}if(n)return this._responder.onSendReceived(n,i),!0;if(s){const{senderName:t,dcLabel:i}=e,{data:n,method:o}=s,a={...n,senderName:t,dcLabel:i};return this._responder.onSendReceived(o,a),!0}return"metadata"===o&&i?(this._responder.onMetaData(i),!0):this._isStatusMessage(i)&&"NetConnection.Connect.Closed"===(null==i?void 0:i.code)?(this._responder.onConnectionClosed(),!0):!(!t||!a)&&this._handleAsyncResponse(a,e)}_handleAsyncResponse(e,t){const i=this._asyncTickets.find(t=>t.id===e);if(!i)return!1;const{promise:n}=i,{data:s}=t;if("error"===(null==s?void 0:s.type)){const e=s.message||s.code||"Unknown error";n.reject(new Error(e))}else n.resolve(s);return this._asyncTickets=this._asyncTickets.filter(t=>t.id!==e),!0}async setUpWithPeerConfiguration(e,t){this.tearDown();try{I(this._name,`[peerconnection:setUpWithPeerConfiguration]: ${JSON.stringify(e,null,2)}`);const i=new RTCPeerConnection(e);return t&&(this._dataChannel=i.createDataChannel(t.name,{ordered:!0}),this._addDataChannelHandlers(this._dataChannel)),this._addConnectionHandlers(i),this._peerConnection=i,i}catch(e){throw O(this._name,`Could not establish a PeerConnection. ${e.message}`),new Error(e.message)}}tearDown(){if(this._dataChannel){I(this._name,"[teardown:datachannel]"),this._removeDataChannelHandlers(this._dataChannel);try{this._dataChannel.close()}catch(e){O(this._name,`[datachannel.close] error: ${e.message}`)}finally{this._dataChannel=void 0}}if(this._peerConnection){I(this._name,"[teardown:peerconnection]"),this._removeConnectionHandlers(this._peerConnection);try{this._peerConnection.close()}catch(e){O(this._name,`[peerconnection.close] error: ${e.message}`)}finally{this._peerConnection=void 0}}}async setLocalDescription(e){var t;return I(this._name,"[setlocaldescription]"),null===(t=this._peerConnection)||void 0===t?void 0:t.setLocalDescription(e)}async setRemoteDescription(e){var t;return I(this._name,"[setremotedescription]"),null===(t=this._peerConnection)||void 0===t?void 0:t.setRemoteDescription(new RTCSessionDescription(e))}async addIceCandidate(e){var t;return I(this._name,"[addcandidate]"),null===(t=this._peerConnection)||void 0===t?void 0:t.addIceCandidate(e)}async waitToGatherIce(e=5e3){const t=this._peerConnection;return I(this._name,"[waittogatherice]"),new Promise(i=>{if("complete"===t.iceGatheringState)I(this._name,"[waittogatherice] ice gathering state complete."),t.addIceCandidate(null).then(()=>{i(t.localDescription)}).catch(e=>{O(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)});else{I(this._name,"[waittogatherice] waiting...");const n=setTimeout(()=>{clearTimeout(n),t.addIceCandidate(null).then(()=>{i(t.localDescription)}).catch(e=>{O(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)})},e);t.onicegatheringstatechange=()=>{clearTimeout(n),I(this._name,"[waittogatherice] ice gathering state complete."),"complete"===t.iceGatheringState&&t.addIceCandidate(null).then(()=>{i(t.localDescription)}).catch(e=>{O(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)})}}})}post(e){if(this._dataChannel){const t="string"==typeof e?e:JSON.stringify(e,null,2);I(this._name,`[datachannel.send] message: ${t}`);try{return this._dataChannel.send(t),Promise.resolve(!0)}catch(e){k(this._name,e.message)}}return Promise.resolve(!1)}get connection(){return this._peerConnection}get dataChannel(){return this._dataChannel}}const ye=[{label:"4K(UHD)",width:3840,height:2160},{label:"1080p(FHD)",width:1920,height:1080},{label:"UXGA",width:1600,height:1200},{label:"720p(HD)",width:1280,height:720},{label:"SVGA",width:800,height:600},{label:"VGA",width:640,height:480},{label:"360p(nHD)",width:640,height:360},{label:"CIF",width:352,height:288},{label:"QVGA",width:320,height:240},{label:"QCIF",width:176,height:144},{label:"QQVGA",width:160,height:120}],Te=e=>"number"==typeof e?e:e.exact||e.ideal||e.max||e.min||e,Le=re((e,t)=>{var i,n;if("boolean"==typeof e.video)return!0;const s=(null===(i=e.video)||void 0===i?void 0:i.width)?Te(e.video.width):0,o=(null===(n=e.video)||void 0===n?void 0:n.height)?Te(e.video.height):0,a=s===t.width&&o===t.height;return a&&I("[gum:isExact]",`Found matching resolution for ${t.width}, ${t.height}.`),a}),Pe=re((e,t)=>{const i=le(Le(t))(e);return I("[gum:hasMatchingFormat]","Filtered list: "+JSON.stringify(i,null,2)),i.length>0}),Ne=re((e,t)=>{var i,n;if("boolean"==typeof e.video)return!0;const s=((null===(i=e.video)||void 0===i?void 0:i.width)?Te(e.video.width):0)*((null===(n=e.video)||void 0===n?void 0:n.height)?Te(e.video.height):0);return t.width*t.height{const i=Ne(t);return le(i)(e)}),Re=async e=>{I("[gum:determineSupportedResolution]","Determine next neighbor based on constraints: "+JSON.stringify(e,null,2));const t=De(ye)(e),i={...e};return await(async(e,t)=>{let i={...e};if(0==t.length)i.video;else{const n=t.shift();i={...e,video:{...e.video,width:{exact:n.width},height:{exact:n.height}}}}return{media:await ie.gUM(i),constraints:i}})(i,t)},He=async e=>{let t;const i=Pe(ye),n=async t=>{if(t){const e="string"==typeof t?t:[t.name,t.message].join(": ");I("[gum:getUserMedia]",`Failure in getUserMedia: ${e}. Attempting other resolution tests...`)}return await Re(e)};if((e=>e.video&&"object"==typeof e.video&&(e.video.width||e.video.height))(e)){if(!i(e))return await n(void 0);{I("[gum:getUserMedia]","Found constraints in list. Checking quick support for faster setup with: "+JSON.stringify(e,null,2));const i=(e=>{var t,i;const n={...e};return"boolean"==typeof e.video||(n.video={...n.video},(null===(t=e.video)||void 0===t?void 0:t.width)&&(n.video.width={exact:Te(e.video.width)}),(null===(i=e.video)||void 0===i?void 0:i.height)&&(n.video.height={exact:Te(e.video.height)})),n})(e);try{return t=await ie.gUM(i),{media:t,constraints:i}}catch(e){return await n(e)}}}else try{return t=await ie.gUM(e),{media:t,constraints:e}}catch(e){return await n(e)}},Ie=(e,t,i)=>{const n="a=end-of-candidates",s=/^a=candidate:/,o=/^a=ice-ufrag:/,a=/^a=ice-pwd:/,r=/^m=(audio|video|application)\ /,l=e.split("\r\n");let d,h="",c="";const u=[];l.forEach(e=>{!d&&r.exec(e)?d=e:o.exec(e)?h=e:a.exec(e)?c=e:s.exec(e)&&(t&&-1!=e.indexOf(t)?u.push(e):t||u.push(e))}),i&&u[u.length-1]!==n&&u.push(n);return[h,c,d,"a=mid:0"].concat(u).join("\r\n")},Oe="RTCPeerConnectionPublisher";class ke extends Ae{constructor(e){super(e,Oe)}_removeConnectionHandlers(e){e.onconnectionstatechange=null,e.oniceconnectionstatechange=null,e.onsignalingstatechange=null,e.onicecandidate=null,e.ontrack=null}_addConnectionHandlers(e){let t;e.onsignalingstatechange=()=>{const t=e.signalingState;I(Oe,`[peer.onsignalingstatechange] - State: ${t}`)},e.onconnectionstatechange=()=>{const{connectionState:t}=e;"connected"===t?(I(this._name,"[peerconnection:open]"),this._responder.onPeerConnectionOpen()):"failed"!==t&&"disconnected"!==t||(O(this._name,"[peerconnection:error]"),"failed"===t&&this._responder.onPeerConnectionFail())},e.oniceconnectionstatechange=i=>{const{iceConnectionState:n}=e;I(this._name,`[peer.oniceconnectionstatechange] - State: ${n}`),"failed"===n?(t&&clearTimeout(t),this._responder.onPeerConnectionClose(i)):"disconnected"===n?t=setTimeout(()=>{I(this._name,"[peer.oniceconnectionstatechange] - Reconnect timeout reached. Closing PeerConnection."),clearTimeout(t),this._responder.onPeerConnectionClose(i)},3e3):t&&(I(this._name,"[peer.oniceconnectionstatechange] - Clearing timeout for reconnect."),clearTimeout(t))},e.onicecandidate=e=>{const{candidate:t}=e;I(this._name,`[peer.onicecandidate] - Peer Candidate: ${null==t?void 0:t.candidate}`),t&&this._responder.onIceCandidate(t)},e.ontrack=e=>{I(this._name,"[peer:ontrack]"),this._responder.onPeerConnectionTrackAdd(e.track)}}_onDataChannelMessage(e){const t=e;if(super._onDataChannelMessage(e))return!0;const i=this.getJsonFromSocketMessage(t);if(null===i)return O(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0;I(this._name,"[datachannel-response]: "+JSON.stringify(i,null,2));const{data:n}=i;return n&&"status"===n.type?"NetStream.Play.UnpublishNotify"===n.code?(this._responder.onUnpublish(),!0):"NetConnection.Publish.InsufficientBW"===n.code?(this._responder.onInsufficientBandwidth(n),!0):"NetConnection.Publish.SufficientBW"===n.code?(this._responder.onSufficientBandwidth(n),!0):"NetConnection.Publish.RecoveringBW"===n.code?(this._responder.onRecoveringBandwidth(n),!0):"Application.Statistics.Endpoint"===n.code?(this._responder.onStatisticsEndpointChange(n.statistics),!0):(I(Oe,`[datachannel.message] status :: ${n.code}`),this._responder.onPublisherStatus(n),!0):(this._responder.onDataChannelMessage(this._dataChannel,t),!1)}addTrack(e){this._peerConnection?this._peerConnection.addTrack(e):O(Oe,"PeerConnection not initialized. Cannot add track.")}async postUnpublish(e){const t=this.post({unpublish:e});return I(Oe,`[peerconnection:unpublish] complete: ${t}`),t}async createOfferWithoutSetLocal(e=null){var t;I(Oe,`[createoffer:withoutlocal]:: bandwidth request: ${JSON.stringify(e,null,2)}`);try{const i=await(null===(t=this._peerConnection)||void 0===t?void 0:t.createOffer());if(e){const t=((e,t)=>{const i=t.indexOf("m=audio");let n,s,o,a=t.indexOf("m=video"),r=t.indexOf("m=application");return i>-1&&e.audio&&(n=t.indexOf("\r\n",i),s=t.slice(0,n),o=t.slice(n+2,t.length),a=(t=[s,"b=AS:"+e.audio,o].join("\r\n")).indexOf("m=video"),r=t.indexOf("m=application")),a>-1&&e.video&&(n=t.indexOf("\r\n",a),s=t.slice(0,n),o=t.slice(n+2,t.length),r=(t=[s,"b=AS:"+e.video,o].join("\r\n")).indexOf("m=application")),r>-1&&e.dataChannel&&(n=t.indexOf("\r\n",r),s=t.slice(0,n),o=t.slice(n+2,t.length),t=[s,"b=AS:"+e.dataChannel,o].join("\r\n")),t})(e,i.sdp);i.sdp=t}return this._responder.onSDPSuccess(),i}catch(e){throw I(Oe,"[createoffer:error]"),this._responder.onSDPError(e),e}}async updateBandwidthRequest(e=null){var t;I(Oe,`[updatebandwidthrequest]:: bandwidth request: ${JSON.stringify(e,null,2)}`);try{const i=null===(t=this._peerConnection)||void 0===t?void 0:t.getSenders();if(e&&(null==i?void 0:i.length)&&i.length>0){const t=(e,t,i)=>new Promise((n,s)=>{try{I(Oe,`[updatebandwidthrequest:${i}]:: bandwidth(${t.encodings[0].maxBitrate})`),e.setParameters(t).then(n).catch(s)}catch(e){s(e)}}),n=[];null==i||i.forEach(async i=>{var s,o;if("video"===(null===(s=i.track)||void 0===s?void 0:s.kind)&&e.video){const e=i.getParameters();e.encodings||(e.encodings=[{}]),e.encodings[0].maxBitrate=75e4,e.encodings[0].maxFramerate=60,e.encodings[0].priority="high",n.push(t(i,e,"video"))}else if("audio"===(null===(o=i.track)||void 0===o?void 0:o.kind)&&e.audio){const e=i.getParameters();e.encodings||(e.encodings=[{}]),e.encodings[0].maxBitrate=128e3,n.push(t(i,e,"audio"))}}),await Promise.all(n).catch(e=>{k(Oe,`[updatebandwidthrequest:error]:: ${e.message}`)})}return!0}catch(e){k(Oe,`[updatebandwidthrequest:error]:: ${e.message}`)}return!1}}class Me extends Error{constructor(e){super(e),this.name="InvalidNameError"}}const Ue="WhipWhepSignalingHelper",Be=new Map;Be.set(400,"Invalid offer SDP."),Be.set(401,"Not authorized."),Be.set(404,"Scope resolver failed for the publish name and / or scope."),Be.set(405,"Remember to update the URL passed into the WHIP or WHEP client."),Be.set(406,"Scope connection rejected."),Be.set(409,"Session already initialized."),Be.set(412,"Invalid request body."),Be.set(417,"Session lookup or creation failure.");const Ve=new Map;Ve.set(400,"Offer already sent, double POST assumed."),Ve.set(401,"Not authorized."),Ve.set(404,"Scope resolver failed for the playback name and / or scope."),Ve.set(406,"Playback failed due to an exception during creation."),Ve.set(409,"Stream is not available to playback.");const Fe=["transcode"];var $e;!function(e){e.ICE_SERVER="ice-server",e.STATISTICS="statistics"}($e||($e={}));const Ge=e=>e&&(e=>{const t=/[?&](.*)=([^]*)/.exec(e);return t&&t.length>0})(e)?"&":"?",We=e=>e.split(";").map(e=>e.trim()).map(e=>"<"===e.charAt(0)?["url",e.substring(1,e.length-1)]:e.split("=")).reduce((e,t)=>e.set(t[0].replaceAll('"',""),t[1].replaceAll('"',"")),new Map);class xe{constructor(e,t=!1,i=!0){I(Ue,`[whipwhep] ${e}`),this._url=e,this._origin=void 0,this._forceHost=i,this._resource=void 0,this._enableSignalingChannel=t}async getOptions(e={}){let t=`${this._url}${Ge(this._url)}signal=${this._enableSignalingChannel}`;e&&Object.keys(e).forEach(i=>{t+=`&${i}=${e[i]}`}),I(Ue,`[whipwhep-options] ${t}`);try{const e=await fetch(t,{method:"OPTIONS",mode:"cors"}),{status:i,headers:n}=e;if(200===i||204===i){const e=/^(L|l)ink/,t=/^(S|s)ession-(H|h)ost/,i=[];let s;return n.forEach((n,o)=>{if(t.exec(o)&&(this._origin=n),e.exec(o))if(n.indexOf(`rel="${$e.ICE_SERVER}"`)>-1){const e=We(n),t=e.get("url"),{protocol:s,host:o}=(e=>{const t=e.split(":");return t.length>1?{protocol:t[0],host:t[1]}:{protocol:void 0,host:e}})(t),a=e.get("username"),r=e.get("credential");s&&o&&a&&r?i.push({username:a,credential:r,urls:t}):t&&i.push({urls:t})}else if(n.indexOf(`rel="${$e.STATISTICS}"`)>-1){const e=We(n).get("url");e&&(s=e)}}),I(Ue,`[whipwhep-links]: ${JSON.stringify(i)}`),I(Ue,`[whipwhep-origin]: ${this._origin}`),{links:i.length>0?i:void 0,origin:this._origin,statisticsEndpoint:s}}throw new Error(`Failed to get options: ${i}`)}catch(e){throw k(Ue,e.message),e}}async postSDPOffer(e,t={},i=!0){let n=`${this._url}${Ge(this._url)}signal=${this._enableSignalingChannel}`;t&&Object.keys(t).forEach(e=>{-1===Fe.indexOf(e)&&(n+=`&${e}=${t[e]}`)}),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n+=`&host=${this._origin}`),I(Ue,`[whipwhep:post-offer] ${n}: `+JSON.stringify(e,null,2));try{const t={method:"POST",mode:"cors",headers:{"Content-Type":"application/sdp"}};e&&e.length>0&&(t.body=e);const s=await fetch(n,t),{status:o,headers:a}=s;if(a&&a.forEach((e,t)=>{I(Ue,`[header] ${t}: ${e}`)}),o>=200&&o<300){const e=await s.text(),t=a.get("Location")||a.get("location");if(t){if(t.match(/^(http|https)/))this._resource=t;else{I(Ue,`[whipwhep-response] Location provided as relative path: ${t}`);const e=new URL(this._url);e.pathname=t.split("?")[0],this._resource=e.toString().replace(/\/endpoint\//,"/resource/")}return I(Ue,`[whipwhep-response] ${this._resource}: ${e}`),{sdp:e,location:this._resource}}return O(Ue,"Location not provided in header response to Offer."),this._resource=new URL(this._url).toString().replace(/\/endpoint\//,"/resource/"),{sdp:e,location:this._resource}}if(i&&Be.get(o)){if(I(Ue,Be.get(o)),404===o||409===o)throw new Me(Be.get(o));throw new Error(Be.get(o))}if(!i&&Ve.get(o)){if(I(Ue,Ve.get(o)),404===o||409===o)throw new Me(Ve.get(o));throw new Error(Ve.get(o))}{const e=await s.text();throw Error(e)}}catch(e){throw k(Ue,e.message),e}}async postSDPAnswer(e,t={}){I(Ue,`[whipwhep:post-answer] ${this._resource}: `+JSON.stringify(e,null,2));let i=this._resource,n=Ge(i);t&&Object.keys(t).forEach(e=>{-1===Fe.indexOf(e)&&(n=Ge(i),i+=`${n}${e}=${t[e]}`)}),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n=i.indexOf("?")>-1?"&":"?",i+=`${n}host=${this._origin}`);try{const t=await fetch(i,{method:"PATCH",mode:"cors",headers:{"Content-Type":"application/sdp"},body:e}),{status:n}=t;if(n>=200&&n<300)return{success:!0,code:n};if(Ve.get(n))throw I(Ue,Ve.get(n)),new Error(Ve.get(n));{const e=await t.text();throw Error(e)}}catch(e){throw k(Ue,e.message),e}}async trickle(e,t={}){I(Ue,`[whipwhep-trickle] ${this._resource}: `+JSON.stringify(e,null,2));let i=this._resource,n=Ge(i);t&&Object.keys(t).forEach(e=>{-1===Fe.indexOf(e)&&(n=Ge(i),i+=`${n}${e}=${t[e]}`)}),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n=Ge(i),i+=`${n}host=${this._origin}`);try{const t=await fetch(i,{method:"PATCH",mode:"cors",headers:{"Content-Type":"application/trickle-ice-sdpfrag"},body:e}),{status:n}=t;if(n>=200&&n<300){const e=await t.text();return I(Ue,`[whipwhep-response] ${this._resource}: ${e}`),{candidate:e}}if(405===n)throw I(Ue,"Remember to update the URL passed into the WHIP or WHEP client"),new Error("Remember to update the URL passed into the WHIP or WHEP client");{const e=await t.text();throw Error(e)}}catch(e){throw k(Ue,e.message),e}}async tearDown(e={},t=!1){if(!this._resource)return;let i=this._resource,n=Ge(i);e&&Object.keys(e).forEach(t=>{-1===Fe.indexOf(t)&&(n=Ge(i),i+=`${n}${t}=${e[t]}`)}),this._forceHost&&this._origin&&!(null==e?void 0:e.host)&&(n=Ge(i),i+=`${n}host=${this._origin}`),I(Ue,"[whipwhep-teardown]");try{await fetch(i,{method:"DELETE",mode:"cors"})}catch(e){if(k(Ue,e.message),!t)throw e}this._url=void 0,this._origin=void 0,this._resource=void 0,this._forceHost=!1,this._enableSignalingChannel=!1}async post(){return I(Ue,"[whipwhep:post] transport called."),Promise.resolve(!1)}async postAsync(){return I(Ue,"[whipwhep:postAsync] transport called."),Promise.resolve(null)}getUrl(){return this._url}}const je="R5ProPublishView";class Ke{constructor(e="red5pro-publisher"){try{this._targetElement=ie.resolveElement(e)}catch(e){throw k(je,`Could not instantiate a new instance of PublishView. Reason: ${e.message}`),e}}preview(e){const t=this.isAutoplay;I(je,`[preview]: autoplay(${t})`),ie.setVideoSource(this._targetElement,e,t)}unpreview(){ie.setVideoSource(this._targetElement,null,this.isAutoplay)}get isAutoplay(){return ie.hasAttributeDefined(this._targetElement,"autoplay")}get view(){return this._targetElement}}const ze={endpoint:null,interval:5e3,include:[]};var Je;!function(e){e.INBOUND="inbound-rtp",e.OUTBOUND="outbound-rtp",e.CODEC="codec",e.MEDIA_SOURCE="media-source",e.CANDIDATE_PAIR="candidate-pair",e.CERTIFICATE="certificate",e.DATA_CHANNEL="data-channel",e.LOCAL_CANDIDATE="local-candidate",e.REMOTE_CANDIDATE="remote-candidate",e.PEER_CONNECTION="peer-connection",e.REMOTE_INBOUND="remote-inbound-rtp",e.REMOTE_OUTBOUND="remote-outbound-rtp",e.TRANSPORT="transport"}(Je||(Je={}));class Ye{constructor(e,t,i){this._name="RTCStatsMonitor",this._queue=[],this._startTime=0,this._stopped=!1,this._interval=0,this._name=e,this._config={...ze,...t},this._client=i,this._identifier={name:this._name,created:(new Date).getTime(),fingerprint:ie.getOrGenerateFingerprint(),device:ie.getBrowserDetails(),client:t}}_emptyStatsReportQueue(){for(;this._queue.length>0;){const e=this._client.getMessageTransport();if(e){const t=this._queue.shift();e.post(t)}else O(this._name,"Failed to post stats data to message transport. Message transport is not available.")}}_getStats(){const{_connection:e}=this;if(e&&"connected"===e.connectionState)try{e.getStats(null).then(e=>{e.forEach(e=>{this._handleStatsReport(e)})}).catch(e=>{k(this._name,`Failed to get stats report. ${e.message||e}`)})}catch(e){k(this._name,`Failed to get stats report. ${e.message||e}`)}}_handleStatsReport(e){console.log(`[${this._name}]: ${JSON.stringify(e,null,2)}`)}_appendClientDetails(e){this._identifier.client={...this._identifier.client,...e}}async start(e){this._startTime=(new Date).getTime(),this._stopped=!1,this._connection=e,this.postAction("started"),this._getStats(),this._interval=setInterval(()=>{this._stopped||this._getStats()},this._config.interval)}stop(){this._stopped=!0,clearInterval(this._interval),this.postAction("ended")}async post(e){const t={...this._identifier,type:"stats-report",timestamp:(new Date).getTime(),data:e},{endpoint:i,additionalHeaders:n}=this._config;if(this._client&&this._client.onStatsReport&&null===i)return void this._client.onStatsReport(this._connection,t);let s={"Content-Type":"application/json"};if(n&&(s={...s,...n}),i)try{const e=await fetch(i,{method:"POST",headers:s,body:JSON.stringify(t)});e.status>=200&&e.status<300?I(this._name,`Posted stats data to endpoint: ${i}.`):k(this._name,`Failed to post stats data to endpoint: ${i}. ${e.status}`)}catch(e){k(this._name,`Failed to post stats data to endpoint: ${i}. ${e.message||e}`)}else if(this._client&&this._client.getMessageTransport())try{let e=!1;const i=this._client.getMessageTransport();i&&(e=await i.post(t)),e||(this._queue.push(t),this._client.on(we.CHANGE,()=>{this._client.off(we.CHANGE),this._emptyStatsReportQueue()}),O(this._name,"Failed to post stats data to message transport. Message transport is not available. Pushed to Queue."))}catch(e){k(this._name,`Failed to post stats data to message transport. ${e.message||e}`)}}async postAction(e,t=void 0){return this.post({action:{type:e,data:t,timestamp:(new Date).getTime()}})}async postEvent(e,t){return this.post({event:{type:e,data:t||void 0,timestamp:(new Date).getTime()}})}updateEndpoint(e,t=!0){const{endpoint:i}=this._config;t?this._config.endpoint=e:t||i||(this._config.endpoint=e)}dispose(){this.stop(),this._connection=void 0,this._client=void 0}}const qe=/(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b) \d+ typ srflx/,Qe=e=>{const t=e.match(qe);return t&&t.length>1?t[1]:null},Xe=[Ee.PUBLISH_START,Ee.PUBLISH_FAIL,Ee.PUBLISH_INSUFFICIENT_BANDWIDTH,Ee.PUBLISH_SUFFICIENT_BANDWIDTH,Ee.PUBLISH_RECOVERING_BANDWIDTH,Ee.STATISTICS_ENDPOINT_CHANGE];class Ze extends Ye{constructor(e,t){if(super("RTCPublisherStats",e,t),this.estimatedAudioBitrate=0,this.estimatedVideoBitrate=0,this.lastAudioReport=null,this.lastVideoReport=null,this._eventHandler=e=>{const{type:t,data:i}=e;if(Xe.indexOf(t)>-1){if(t===Ee.STATISTICS_ENDPOINT_CHANGE){const{statisticsEndpoint:e}=i;this.updateEndpoint(e,!1)}this.postEvent(t)}},this._candidateCreateHandler=({data:{candidate:e}})=>{const{candidate:t}=e,i=Qe(t);i&&(this._identifier.publicIP=i)},this._hostEndpointChangedHandler=({data:{endpoint:e,iceServers:t}})=>{this._appendClientDetails({node:e,iceServers:t})},this._client.on("*",this._eventHandler),this._client.on(Ce.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.on(Ce.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),this._client.getPeerConnection())this.start(this._client.getPeerConnection());else{const e=({data:t})=>{this._client.off(Ce.PEER_CONNECTION_AVAILABLE,e),this.start(t)};this._client.on(Ce.PEER_CONNECTION_AVAILABLE,e)}}_handleStatsReport(e){const{type:t}=e,{include:i}=this._config,n=i&&i.length>0;if(n&&i.indexOf(t)>=-1)this.post(e);else if(!n)if(t===Je.CODEC){const{id:i,clockRate:n,mimeType:s,payloadType:o}=e;this.post({id:i,type:t,clockRate:n,mimeType:s,payloadType:o})}else if(t===Je.CANDIDATE_PAIR){const{availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o}=e;this.post({type:t,availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o})}else if(t===Je.MEDIA_SOURCE){const{kind:i}=e;if("audio"===i)this.post({type:t,kind:i});else if("video"===i){const{framesPerSecond:n,height:s,width:o}=e;this.post({type:t,kind:i,framesPerSecond:n,height:s,width:o})}}else if([Je.OUTBOUND,"outboundrtp"].indexOf(t)>-1){const{timestamp:i,kind:n,codecId:s,mediaType:o,active:a,bytesSent:r,packetsSent:l,totalPacketsSendDelay:d}=e,h={type:t,kind:n,codecId:s,mediaType:o,active:a,bytesSent:r,packetsSent:l,totalPacketsSendDelay:d};if("audio"===n){if(this.lastAudioReport){const{bytesSent:e,timestamp:t}=this.lastAudioReport,n=8*(r-e)/(i-t);this.estimatedAudioBitrate=n}this.post({...h,estimatedBitrate:Math.floor(this.estimatedAudioBitrate)}),this.lastAudioReport=e}else if("video"===n){const{firCount:t,pliCount:n,frameWidth:s,frameHeight:o,framesEncoded:a,framesPerSecond:l,framesSent:d,keyFramesEncoded:c,qualityLimitationReason:u,qualityLimitationDurations:p}=e;let _={...h,firCount:t,pliCount:n,frameWidth:s,frameHeight:o,framesEncoded:a,framesPerSecond:l,framesSent:d,keyFramesEncoded:c,qualityLimitationReason:"none"!==u?u:void 0,qualityLimitationDurations:"none"!==u?p:void 0};if(this.lastVideoReport){const{bytesSent:e,timestamp:t}=this.lastVideoReport,n=8*(r-e)/(i-t);this.estimatedVideoBitrate=n}this.post({..._,estimatedBitrate:Math.floor(this.estimatedVideoBitrate)}),this.lastVideoReport=e}}}dispose(){this._client.off("*",this._eventHandler),this._client.off(Ce.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.off(Ce.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),super.dispose()}}const et="WHIPClient",tt=pe,it=e=>I(et,e),nt=e=>k(et,e),st=e=>O(et,e);class ot extends U{constructor(e,t,i){super();const n=e?se(e):tt,s=i||tt,o={...s,...n,endpoint:e,mediaElementId:t?t.id:s.mediaElementId};e&&this.internalInit(o),this._onOrientationChange=this._onOrientationChange.bind(this)}async internalInit(e){await this.init(e),await this.publish()}async generateMediaStream(e){var t,i;const{onGetUserMedia:n}=e;if(n){it("Requesting gUM from user-defined configuration:onGetUserMedia.");const e=await n();return this.trigger(new ge(Ce.CONSTRAINTS_ACCEPTED,this,ae(e))),e}{const{mediaConstraints:n}=e;let s;it(`Requesting gUM using mediaConstraints: ${JSON.stringify(n,null,2)}`);let o=n;const a=await He(o);return a&&a.media||(s=await ie.gUM(o)),s=null!==(t=null==a?void 0:a.media)&&void 0!==t?t:s,o=null!==(i=null==a?void 0:a.constraints)&&void 0!==i?i:n,it(`Constraints accepted: ${JSON.stringify(o,null,2)}`),this.trigger(new ge(Ce.CONSTRAINTS_ACCEPTED,this,{constraints:o,...ae(s)})),s}}async getAndPreviewStreamIfAvailable(){var e;let t=this._mediaStream;if(!t){try{t=null!=t?t:await this.generateMediaStream(this._options)}catch(t){const i=null!==(e=t.message)&&void 0!==e?e:"Could not generate media stream.";throw this.trigger(new ge(Ce.CONSTRAINTS_REJECTED,this,{constraints:this._options.mediaConstraints})),new Error(i)}if(!t)throw new Error("Could not generate media stream.")}return this.trigger(new ge(Ce.MEDIA_STREAM_AVAILABLE,this,t)),this.preview(t),t}reorderCodecPreferences(e,t,i){e.getTransceivers().forEach(e=>{if(e.sender&&e.sender.track){const{kind:n}=e.sender.track;if(t&&"video"===n&&e.setCodecPreferences)try{const{codecs:i}=RTCRtpSender.getCapabilities("video"),n=i.findIndex(e=>e.mimeType===`video/${t}`);if(n>-1){const t=i.slice(0),s=i[n];t.splice(n,1),t.unshift(s),e.setCodecPreferences(t)}}catch(e){st(`[videoEncoding] Could not set codec preferences for ${t}. ${e.message||e}`)}else if(i&&"audio"===n&&e.setCodecPreferences)try{const{codecs:t}=RTCRtpSender.getCapabilities("audio"),n=t.findIndex(e=>e.mimeType===`audio/${i}`);if(n>-1){const i=t[n];t.splice(n,1),t.unshift(i),e.setCodecPreferences(t)}}catch(e){st(`[audioEncoding] Could not set codec preferences for ${i}. ${e.message||e}`)}}})}async postOffer(e){var t;try{const{sdp:i}=e;let{videoEncoding:n}=this._options;const{mungeOffer:s,streamMode:o,keyFramerate:a,iceTransport:r,connectionParams:d,mediaConstraints:h,forceVP8:c,audioEncoding:u,offerSDPResolution:p}=this._options;c&&!n&&(n=l.VP8);let _=i;s&&(it(`[MUNGE:before] offer: ${_}`),_=s(_),it(`[MUNGE:after] offer: ${_}`)),p&&(it(`[MUNGE] Setting resolution on offer: ${_}`),_=((e,t)=>{if(!t)return e;const{width:i,height:n}=t;if(!i||!n)return e;const s=`a=framesize:${i}-${n}`,o=e.split("\r\n");let a=o.length;const r=/^m=video/;for(;--a>-1;)if(r.exec(o[a])){for(;++a-1){o.splice(a+1,0,s);break}break}return o.join("\r\n")})(_,((e,t)=>{let i;if(e)try{const t=e.getVideoTracks()&&e.getVideoTracks()[0];if(t){const e=t.getSettings();i={width:e.width,height:e.height}}}catch(e){O("[determineMediaResolution]",`Could not determine resolution from MediaStream. ${e.message||e}`)}if(!i)try{const e=t.video,{width:n,height:s}=e;if(n&&s)if("number"==typeof n&&"number"==typeof s)i={width:n,height:s};else{i={width:n.exact||n.min||n.max||n.ideal||640,height:s.exact||s.min||s.max||s.ideal||480}}}catch(e){O("[determineMediaResolution]",`Could not determine resolution from MediaConstraints. ${e.message||e}`)}return i&&I("[determineMediaResolution]",`constraints: ${JSON.stringify(i,null,2)}`),i})(this._mediaStream,h)),it(`[MUNGE:after] offer: ${_}`));const m={...d,mode:o,transport:r,keyFramerate:a};return n&&(m.videoEncoding=n),u&&(m.audioEncoding=u),await(null===(t=this._whipWhepService)||void 0===t?void 0:t.postSDPOffer(_,m))}catch(e){throw nt(e.message||e),e instanceof Me?this.trigger(new ge(Ee.PUBLISH_INVALID_NAME,this)):(this.trigger(new ge(Ee.CONNECT_FAILURE,this,e)),this.unpublish()),e}}async postCandidateFragments(e){var t;const{connectionParams:i}=this._options,n=Ie(e,void 0,!0);return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.trickle(n,i))}async init(e){var t;this._options={...tt,...e};const i=oe(this._options),{includeDataChannel:n,disableProxy:s}=this._options;return this._whipWhepService=new xe(i,n,s),this._messageTransport=this._whipWhepService,(null===(t=this._options)||void 0===t?void 0:t.stats)&&this.monitorStats(this._options.stats),this._mediaStream=await this.getAndPreviewStreamIfAvailable(),this}async initWithStream(e,t){return this._mediaStream=t,this.init(e)}async publish(e){var t,i,n,s;e&&(this._options.streamName=e);const{forceVP8:o,audioEncoding:a,rtcConfiguration:r,dataChannelConfiguration:d,includeDataChannel:h,signalingSocketOnly:c,enableChannelSignaling:u,connectionParams:p,bandwidth:_,mungeAnswer:m}=this._options;let{videoEncoding:g}=this._options;o&&(g=l.VP8,this._options.videoEncoding=g),this._mediaStream||(this._mediaStream=await this.getAndPreviewStreamIfAvailable());try{const e=null!=p?p:{};if(p){const{transcode:t}=p;t&&(e.transcode=t)}const s=await(null===(t=this._whipWhepService)||void 0===t?void 0:t.getOptions(e));(null==s?void 0:s.links)&&(this._options.rtcConfiguration={...r,iceServers:s.links}),(null==s?void 0:s.origin)&&this.trigger(new ge(Ce.HOST_ENDPOINT_CHANGED,this,{endpoint:s.origin})),(null==s?void 0:s.statisticsEndpoint)&&this._onStatisticsEndpointChange(s.statisticsEndpoint);const o=h||u||c?d:void 0;this._peerConnectionHelper=new ke({onDataChannelError:this._onDataChannelError.bind(this),onSendReceived:this._onSendReceived.bind(this),onMetaData:this._onMetaData.bind(this),onConnectionClosed:this._onConnectionClosed.bind(this),onDataChannelOpen:this._onDataChannelOpen.bind(this),onDataChannelClose:this._onDataChannelClose.bind(this),onDataChannelMessage:this._onDataChannelMessage.bind(this),onPeerConnectionOpen:this._onPeerConnectionOpen.bind(this),onPeerConnectionFail:this._onPeerConnectionFail.bind(this),onPeerConnectionClose:this._onPeerConnectionClose.bind(this),onIceCandidate:this._onIceCandidate.bind(this),onSDPSuccess:this._onSDPSuccess.bind(this),onSDPError:this._onSDPError.bind(this),onStatisticsEndpointChange:this._onStatisticsEndpointChange.bind(this),onPublisherStatus:this._onPublisherStatus.bind(this),onPeerConnectionTrackAdd:this._onPeerConnectionTrackAdd.bind(this),onInsufficientBandwidth:this._onInsufficientBandwidth.bind(this),onSufficientBandwidth:this._onSufficientBandwidth.bind(this),onRecoveringBandwidth:this._onRecoveringBandwidth.bind(this),onUnpublish:this._onUnpublish.bind(this)}),await this._peerConnectionHelper.setUpWithPeerConfiguration(this._options.rtcConfiguration,o),this.trigger(new ge(Ce.PEER_CONNECTION_AVAILABLE,this,this.getPeerConnection())),this._mediaStream.getTracks().forEach(e=>{var t;null===(t=this.getPeerConnection())||void 0===t||t.addTransceiver(e,{direction:"sendonly"})}),this.reorderCodecPreferences(this.getPeerConnection(),g,a);const l=await(null===(i=this._peerConnectionHelper)||void 0===i?void 0:i.createOfferWithoutSetLocal(_));await this._peerConnectionHelper.setLocalDescription(l),this.trigger(new ge(Ce.OFFER_START,this,l));const{sdp:v}=await this.postOffer(l);let S=v;m&&(it(`[MUNGE:before] answer: ${S}`),S=m(S),it(`[MUNGE:after] answer: ${S}`)),await this._peerConnectionHelper.setRemoteDescription({type:"answer",sdp:S}),this.trigger(new ge(Ce.OFFER_END,this,S));const E=await this._peerConnectionHelper.waitToGatherIce(),{sdp:C}=E;return await this.postCandidateFragments(C),this.trigger(new ge(Ce.ICE_TRICKLE_COMPLETE,this)),ie.addOrientationChangeHandler(this._onOrientationChange),(null===(n=this._options)||void 0===n?void 0:n.includeDataChannel)||this.trigger(new ge(Ee.PUBLISH_START,this)),this}catch(e){throw nt(null!==(s=e.message)&&void 0!==s?s:"Could not publish."),this.trigger(new ge(Ee.CONNECT_FAILURE,this,e)),this.unpublish(!0),e}}async unpublish(e=!1){var t;it("[unpublish]"),this._peerConnectionHelper&&await this._peerConnectionHelper.tearDown(),this._whipWhepService&&await this._whipWhepService.tearDown(null,e),(null===(t=this._options)||void 0===t?void 0:t.clearMediaOnUnpublish)&&this.unpreview(),this._mediaStream=void 0,this._peerConnectionHelper=void 0,this._whipWhepService=void 0,this._messageTransport=void 0,this._publishView=void 0,this.trigger(new ge(Ee.UNPUBLISH_SUCCESS,this)),ie.removeOrientationChangeHandler(this._onOrientationChange)}preview(e){it("[preview]");const{mediaElementId:t}=this._options;t&&(this._publishView=new Ke(t),this._publishView.preview(e))}unpreview(){it("[unpreview]"),this._mediaStream&&this._mediaStream.getTracks().forEach(e=>{e.stop()}),this._publishView&&this._publishView.unpreview(),this._publishView=void 0}monitorStats(e){it("[monitorStats]");const{host:t,endpoint:i,app:n,streamName:s,connectionParams:o}=this._options,a=null!=e?e:ze;return this._statisticsConfiguration={...a,host:t,hostEndpoint:i,app:n,streamName:s,connectionParams:o},this._statsMonitor?st("Cannot monitor stats without a Peer Connection. Please call `init` before calling `monitorStats`."):this._statsMonitor=new Ze(this._statisticsConfiguration,{onStatsReport:this._onStatsReport.bind(this),getPeerConnection:this.getPeerConnection.bind(this),getMessageTransport:this.getMessageTransport.bind(this),on:this.on.bind(this),off:this.off.bind(this),trigger:this.trigger.bind(this)}),this}unmonitorStats(){return this._statsMonitor&&this._statsMonitor.dispose(),this._statsMonitor=void 0,this._statisticsConfiguration=void 0,this}muteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0}})}unmuteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1}})}muteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!0}})}unmuteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!1}})}send(e,t){var i;return null===(i=this.getMessageTransport())||void 0===i?void 0:i.post({send:{method:e,data:"string"==typeof t?JSON.parse(t):t}})}async callServer(e,t){var i;try{if(!this.getMessageTransport())throw new Error("Message transport not available");return null===(i=this.getMessageTransport())||void 0===i?void 0:i.postAsync({callAdapter:{method:e,arguments:t}})}catch(e){nt(e.message||e)}}sendLog(e,t){var i;try{const n=Object.keys(N).find(t=>t.toLowerCase()===e.toLowerCase())?e:N.DEBUG,s="string"==typeof t?t:JSON.stringify(t);null===(i=this.getMessageTransport())||void 0===i||i.post({log:n.toUpperCase(),message:s})}catch(e){const t=e.message||e;nt("Could not send log to server. Message parameter expected to be String or JSON-serializable object."),nt(t)}}get options(){return this._options}getOptions(){return this._options}getPeerConnection(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.connection}getDataChannel(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.dataChannel}getMediaStream(){return this._mediaStream}getMessageTransport(){return this._messageTransport}_onDataChannelError(e,t){nt(`Data channel error: ${t}`),this.trigger(new ge(Ce.DATA_CHANNEL_ERROR,this,{dataChannel:e,error:t}))}_onSendReceived(e,t){it(`Send received: ${e} ${JSON.stringify(t)}`),"onMetaData"===e?this._onMetaData(t):this.trigger(new ge(Ee.PUBLISH_SEND_INVOKE,this,{methodName:e,data:t}))}_onMetaData(e){it(`Metadata received: ${JSON.stringify(e)}`),this.trigger(new ge(Ee.PUBLISH_METADATA,this,e))}_onConnectionClosed(){it("Connection closed"),this.unpublish(),this.trigger(new ge(Ee.CONNECTION_CLOSED,this))}_onDataChannelOpen(e){it(`Data channel opened: ${e.label}`),this.trigger(new ge(Ce.DATA_CHANNEL_OPEN,this,{dataChannel:e})),this.trigger(new ge(Ce.DATA_CHANNEL_AVAILABLE,this,{name:e.label,dataChannel:e})),this._messageTransport=this._peerConnectionHelper,this.trigger(new Se(we.CHANGE,this,{controller:this,transport:this._messageTransport})),this.trigger(new ge(Ee.PUBLISH_START,this))}_onDataChannelClose(e){it(`Data channel closed: ${e.label}`),this.trigger(new ge(Ce.DATA_CHANNEL_CLOSE,this,{dataChannel:e}))}_onDataChannelMessage(e,t){it(`Data channel message: ${t.data}`),this.trigger(new ge(Ce.DATA_CHANNEL_MESSAGE,this,{dataChannel:e,message:t}))}_onPeerConnectionTrackAdd(e){it(`Peer connection track added: ${e.id}`),this.trigger(new ge(Ce.TRACK_ADDED,this,{track:e}))}_onPeerConnectionOpen(){it("Peer connection opened"),this.trigger(new ge(Ce.PEER_CONNECTION_OPEN,this,this.getPeerConnection()))}_onPeerConnectionFail(){nt("Peer connection failed"),this.trigger(new ge(Ee.PUBLISH_FAIL,this))}_onPeerConnectionClose(e){it(`Peer connection closed: ${e.type}`),this._peerConnectionHelper&&this._peerConnectionHelper.tearDown(),this.trigger(new ge(Ee.CONNECTION_CLOSED,this,e))}_onIceCandidate(e){it(`ICE candidate: ${JSON.stringify(e,null,2)}`),this.trigger(new ge(Ce.CANDIDATE_CREATE,this,{candidate:e}))}_onUnpublish(){it("Unpublish received")}_onPublisherStatus(e){it("[publisherstatus] - "+JSON.stringify(e,null,2)),e.code&&"NetStream.Publish.IsAvailable"===e.code?this.trigger(new ge(Ee.PUBLISH_AVAILABLE,this,e)):this.trigger(new ge(Ee.PUBLISH_STATUS,this,e))}_onInsufficientBandwidth(e){this.trigger(new ge(Ee.PUBLISH_INSUFFICIENT_BANDWIDTH,this,e))}_onSufficientBandwidth(e){this.trigger(new ge(Ee.PUBLISH_SUFFICIENT_BANDWIDTH,this,e))}_onRecoveringBandwidth(e){this.trigger(new ge(Ee.PUBLISH_RECOVERING_BANDWIDTH,this,e))}_onSDPSuccess(e=void 0){const t=e?": "+JSON.stringify(e,null,2):"";it(`[onsdpsuccess]:: ${t}`)}_onSDPError(e=void 0){this.trigger(new ge(Ee.PUBLISH_FAIL,this));const t=e?": "+JSON.stringify(e,null,2):"";nt(`[onsdperror]:: ${t}`)}_onOrientationChange(e){const t=this.getMessageTransport();t&&t.post({send:{method:"onMetaData",data:{deviceOrientation:e}}})}_onStatisticsEndpointChange(e){it(`Statistics endpoint changed: ${e}`),this._statsMonitor&&this._statsMonitor.updateEndpoint(e),this.trigger(new ge(Ee.STATISTICS_ENDPOINT_CHANGE,this,{statisticsEndpoint:e}))}_onStatsReport(e,t){this.trigger(new ge(Ce.STATS_REPORT,this,{connection:e,report:t}))}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}trigger(e){super.trigger(e)}getType(){return"RTC"}}const at={...{protocol:"https",port:443,app:"live",autoLayoutOrientation:!0,mediaElementId:"red5pro-subscriber",rtcConfiguration:{iceServers:[{urls:"stun:stun2.l.google.com:19302"}],iceCandidatePoolSize:2,bundlePolicy:"max-bundle"},iceTransport:de.UDP,muteOnAutoplayRestriction:!0,maintainConnectionOnSubscribeErrors:!1,dataChannelConfiguration:{name:"red5pro"},signalingSocketOnly:!1,includeDataChannel:!0,maintainStreamVariant:!1,buffer:0,stats:void 0},signalingSocketOnly:!1,enableChannelSignaling:!1,includeDataChannel:!0,disableProxy:!0,trickleIce:!0,postEmptyOffer:!1,mungeOffer:void 0,mungeAnswer:void 0},rt={protocol:"https",port:443,app:"live",mediaElementId:"red5pro-subscriber",muteOnAutoplayRestriction:!0},lt="R5ProPlaybackView";class dt{constructor(e="red5pro-subscriber"){try{this._targetElement=ie.resolveElement(e)}catch(e){throw k(lt,`Could not instantiate a new instance of Red5ProSubscriber. Reason: ${e.message||e}`),e}}attachStream(e){const t=this.isAutoplay;I(lt,"[attachstream]"),ie.setVideoSource(this._targetElement,e,t)}detachStream(){I(lt,"[detachstream]"),ie.setVideoSource(this._targetElement,null,this.isAutoplay)}get isAutoplay(){return ie.hasAttributeDefined(this._targetElement,"autoplay")}get view(){return this._targetElement}}const ht="RTCPeerConnectionSubscriber";class ct extends Ae{constructor(e){super(e,ht)}_removeConnectionHandlers(e){e.onconnectionstatechange=null,e.oniceconnectionstatechange=null,e.onsignalingstatechange=null,e.onicecandidate=null,e.ontrack=null}_addConnectionHandlers(e){let t;e.onsignalingstatechange=()=>{const t=e.signalingState;I(ht,`[peer.onsignalingstatechange] - State: ${t}`)},e.onconnectionstatechange=()=>{const{connectionState:t}=e;"connected"===t?(I(this._name,"[peerconnection:open]"),this._responder.onPeerConnectionOpen()):"failed"!==t&&"disconnected"!==t||(O(this._name,"[peerconnection:error]"),"failed"===t&&this._responder.onPeerConnectionFail())},e.oniceconnectionstatechange=i=>{const{iceConnectionState:n}=e;I(this._name,`[peer.oniceconnectionstatechange] - State: ${n}`),"failed"===n?(t&&clearTimeout(t),this._responder.onPeerConnectionFail(),this._responder.onPeerConnectionClose(i)):"disconnected"===n?t=setTimeout(()=>{I(this._name,"[peer.oniceconnectionstatechange] - Reconnect timeout reached. Closing PeerConnection."),clearTimeout(t),this._responder.onPeerConnectionClose(i)},3e3):t&&(I(this._name,"[peer.oniceconnectionstatechange] - Clearing timeout for reconnect."),clearTimeout(t))},e.onicecandidate=e=>{const{candidate:t}=e;I(this._name,`[peer.onicecandidate] - Peer Candidate: ${null==t?void 0:t.candidate}`),t&&this._responder.onIceCandidate(t)}}_onDataChannelMessage(e){const t=e;if(super._onDataChannelMessage(e))return!0;const i=this.getJsonFromSocketMessage(t);if(null===i)return O(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0;I(this._name,"[datachannel-response]: "+JSON.stringify(i,null,2));const{data:n}=i;if(n&&"status"===n.type)return"NetStream.Play.UnpublishNotify"===n.code?(this._responder.onUnpublish(),this._responder.onConnectionClosed(),!0):"Application.Statistics.Endpoint"===n.code?(this._responder.onStatisticsEndpointChange(n.statistics),!0):(I(ht,`[datachannel.message] status :: ${n.code}`),this._responder.onSubscriberStatus(n),!0);if(n&&n.status&&"NetStream.Play.UnpublishNotify"===n.status)return this._responder.onUnpublish(),this._responder.onConnectionClosed(),!0;if(n&&"result"===n.type){const{message:e}=n;if("Stream switch: Success"===e)try{return this._responder.onStreamSwitchComplete(),!0}catch(e){}}return this._responder.onDataChannelMessage(this._dataChannel,t),!1}}var ut;!function(e){e.EMPTY="Empty",e.VIDEO="Video",e.AUDIO="Audio",e.FULL="Video/Audio"}(ut||(ut={}));class pt extends U{trigger(e){super.trigger(e)}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}}class _t extends pt{}const mt=[fe.SUBSCRIBE_START,fe.SUBSCRIBE_STOP,fe.SUBSCRIBE_FAIL,fe.SUBSCRIBE_PUBLISHER_CONGESTION,fe.SUBSCRIBE_PUBLISHER_RECOVERY,fe.PLAY_UNPUBLISH,fe.STREAMING_MODE_CHANGE,fe.PLAYBACK_STATE_CHANGE,fe.STATISTICS_ENDPOINT_CHANGE];class gt extends Ye{constructor(e,t){if(super("RTCSubscriberStats",e,t),this.estimatedAudioBitrate=0,this.estimatedVideoBitrate=0,this.lastAudioReport=null,this.lastVideoReport=null,this._eventHandler=e=>{const{type:t,data:n}=e;if(mt.indexOf(t)>-1)if(t===fe.STREAMING_MODE_CHANGE){const{streamingMode:e,previousStreamingMode:i}=n;this.postEvent(t,{data:{streamingMode:e,previousStreamingMode:i}})}else if(t===fe.PLAYBACK_STATE_CHANGE){const{code:e}=n;let t;e===i.AVAILABLE&&(t={timeToFirstFrameMS:(new Date).getTime()-this._startTime}),this.postEvent(s[e],t)}else{if(t===fe.STATISTICS_ENDPOINT_CHANGE){const{statisticsEndpoint:e}=n;this.updateEndpoint(e,!1)}this.postEvent(t)}},this._candidateCreateHandler=({data:{candidate:e}})=>{const{candidate:t}=e,i=Qe(t);i&&(this._identifier.publicIP=i)},this._hostEndpointChangedHandler=({data:{endpoint:e,iceServers:t}})=>{this._appendClientDetails({node:e,iceServers:t})},this._client.on("*",this._eventHandler),this._client.on(be.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.on(be.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),this._client.getPeerConnection())this.start(this._client.getPeerConnection());else{const e=({data:t})=>{this._client.off(be.PEER_CONNECTION_AVAILABLE,e),this.start(t)};this._client.on(be.PEER_CONNECTION_AVAILABLE,e)}}_handleStatsReport(e){const{type:t}=e,{include:i}=this._config,n=i&&i.length>0;if(n&&i.indexOf(t)>=-1)this.post(e);else if(!n)if(t===Je.CODEC){const{id:i,clockRate:n,mimeType:s,payloadType:o}=e;this.post({id:i,type:t,clockRate:n,mimeType:s,payloadType:o})}else if(t===Je.CANDIDATE_PAIR){const{availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o}=e;this.post({type:t,availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o})}else if([Je.INBOUND,"inboundrtp"].indexOf(t)>-1){const{timestamp:i,kind:n,codecId:s,jitter:o,packetsLost:a,packetsReceived:r,bytesReceived:l}=e,d={type:t,kind:n,codecId:s,jitter:o,packetsLost:a,packetsReceived:r,bytesReceived:l};if("audio"===n){const{packetsDiscarded:t}=e;if(this.lastAudioReport){const{bytesReceived:e,timestamp:t}=this.lastAudioReport,n=8*(l-e)/(i-t);this.estimatedAudioBitrate=n}this.post({...d,packetsDiscarded:t,estimatedBitrate:Math.floor(this.estimatedAudioBitrate)}),this.lastAudioReport=e}else if("video"===n){const{firCount:t,frameWidth:n,frameHeight:s,framesDecoded:o,framesDropped:a,framesPerSecond:r,framesReceived:h,freezeCount:c,keyFramesDecoded:u,nackCount:p,pauseCount:_,pliCount:m,totalFreezesDuration:g,totalPausesDuration:v}=e,S={...d,firCount:t,frameWidth:n,frameHeight:s,framesDecoded:o,framesDropped:a,framesPerSecond:r,framesReceived:h,freezeCount:c,keyFramesDecoded:u,nackCount:p,pauseCount:_,pliCount:m,totalFreezesDuration:g,totalPausesDuration:v};if(this.lastVideoReport){const{bytesReceived:e,timestamp:t}=this.lastVideoReport,n=8*(l-e)/(i-t);this.estimatedVideoBitrate=n}this.post({...S,estimatedBitrate:Math.floor(this.estimatedVideoBitrate)}),this.lastVideoReport=e}}}dispose(){this._client.off("*",this._eventHandler),this._client.off(be.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.off(be.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),super.dispose()}}class vt extends _t{constructor(e,t){super(),this._isVOD=!1,this._name=`SourceHandler-${t}`,this._view=e,this._playbackNotificationCenter=this._view,this.onCanPlay=this._onCanPlay.bind(this),this.onDurationChange=this._onDurationChange.bind(this),this.onEnded=this._onEnded.bind(this),this.onTimeUpdate=this._onTimeUpdate.bind(this),this.onPlay=this._onPlay.bind(this),this.onPause=this._onPause.bind(this),this.onVolumeChange=this._onVolumeChange.bind(this),this.onLoadedData=this._onLoadedData.bind(this),this.onLoadedMetadata=this._onLoadedMetadata.bind(this),this.onResize=this._onResize.bind(this),this.onLoadStart=this._onLoadStart.bind(this),this.onSuspend=this._onSuspend.bind(this),this.onStalled=this._onStalled.bind(this),this.onWaiting=this._onWaiting.bind(this),this.onError=this._onError.bind(this),this.onEncrypted=this._onEncrypted.bind(this),this._addPlaybackNotificationCenterHandlers(this._playbackNotificationCenter),ie.onFullScreenStateChange(this._handleFullScreenChange.bind(this))}_addPlaybackNotificationCenterHandlers(e){e.addEventListener("canplay",this.onCanPlay),e.addEventListener("durationchange",this.onDurationChange),e.addEventListener("ended",this.onEnded),e.addEventListener("timeupdate",this.onTimeUpdate),e.addEventListener("play",this.onPlay),e.addEventListener("pause",this.onPause),e.addEventListener("volumechange",this.onVolumeChange),e.addEventListener("loadeddata",this.onLoadedData),e.addEventListener("loadedmetadata",this.onLoadedMetadata),e.addEventListener("resize",this.onResize),e.addEventListener("loadstart",this.onLoadStart),e.addEventListener("suspend",this.onSuspend),e.addEventListener("stalled",this.onStalled),e.addEventListener("waiting",this.onWaiting),e.addEventListener("error",this.onError),e.addEventListener("encrypted",this.onEncrypted)}_removePlaybackNotificationCenterHandlers(e){e.removeEventListener("canplay",this.onCanPlay),e.removeEventListener("durationchange",this.onDurationChange),e.removeEventListener("ended",this.onEnded),e.removeEventListener("timeupdate",this.onTimeUpdate),e.removeEventListener("play",this.onPlay),e.removeEventListener("pause",this.onPause),e.removeEventListener("volumechange",this.onVolumeChange),e.removeEventListener("loadeddata",this.onLoadedData),e.removeEventListener("loadedmetadata",this.onLoadedMetadata),e.removeEventListener("resize",this.onResize),e.removeEventListener("loadstart",this.onLoadStart),e.removeEventListener("suspend",this.onSuspend),e.removeEventListener("stalled",this.onStalled),e.removeEventListener("waiting",this.onWaiting),e.removeEventListener("error",this.onError)}_handleFullScreenChange(e){var t,i;e?null===(t=this._view)||void 0===t||t.classList.add("red5pro-media-container-full-screen"):null===(i=this._view)||void 0===i||i.classList.remove("red5pro-media-container-full-screen"),this.trigger(new ve(fe.FULL_SCREEN_STATE_CHANGE,void 0,e))}_cleanup(){this._playbackNotificationCenter&&this._removePlaybackNotificationCenterHandlers(this._playbackNotificationCenter),this._playbackNotificationCenter=void 0,this._view=void 0}_onCanPlay(e){var t;I(this._name,"[videoelement:event] canplay");const s=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,o=this.getControls();o&&o.enable(!0),this.trigger(new ve(fe.PLAYBACK_STATE_CHANGE,void 0,{code:i.AVAILABLE,state:n.AVAILABLE})),this.trigger(new ve(fe.VOLUME_CHANGE,void 0,{volume:s.volume}))}_onDurationChange(e){var t;I(this._name,"[videoelement:event] durationchange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();n&&n.setPlaybackDuration(i.duration),!isNaN(i.duration)&&Number.isFinite(i.duration)&&(this._isVOD=!0)}_onEnded(){I(this._name,"[videoelement:event] ended");const e=this.getControls();e&&e.setState(i.IDLE),this.trigger(new ve(fe.PLAYBACK_STATE_CHANGE,void 0,{code:i.IDLE,state:n.IDLE}))}_onTimeUpdate(e){var t;const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();n&&n.setSeekTime(i.currentTime,this.isVOD()?i.duration:void 0),this.trigger(new ve(fe.PLAYBACK_TIME_UPDATE,void 0,{time:i.currentTime,duration:i.duration}))}_onPlay(){I(this._name,"[videoelement:event] play");const e=this.getControls();e&&e.setState(i.PLAYING),this.trigger(new ve(fe.PLAYBACK_STATE_CHANGE,void 0,{code:i.PLAYING,state:n.PLAYING}))}_onPause(){I(this._name,"[videoelement:event] pause");const e=this.getControls();e&&e.setState(i.PAUSED),this.trigger(new ve(fe.PLAYBACK_STATE_CHANGE,void 0,{code:i.PAUSED,state:n.PAUSED}))}_onVolumeChange(e){var t;I(this._name,"[videoelement:event] volumechange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();n&&n.getVolume()!==i.volume&&n.setVolume(i.volume),this.trigger(new ve(fe.VOLUME_CHANGE,void 0,{volume:i.volume}))}_onLoadedData(e){var t,i,n;I(this._name,"[videoelement:event] loadeddata");const s=null!==(t=this._view)&&void 0!==t?t:e.target;this.trigger(new ve(fe.VIDEO_DIMENSIONS_CHANGE,void 0,{width:null!==(i=s.videoWidth)&&void 0!==i?i:0,height:null!==(n=s.videoHeight)&&void 0!==n?n:0}))}_onLoadedMetadata(e){var t,i;I(this._name,"[videoelement:event] loadedmetadata");const n=null!==(t=this._view)&&void 0!==t?t:e.target;this.trigger(new ve(fe.LOADED_METADATA,void 0,{duration:null!==(i=n.duration)&&void 0!==i?i:0}))}_onResize(e){var t,i,n;I(this._name,"[videoelement:event] resize");const s=null!==(t=this._view)&&void 0!==t?t:e.target;this.trigger(new ve(fe.VIDEO_DIMENSIONS_CHANGE,void 0,{width:null!==(i=s.videoWidth)&&void 0!==i?i:0,height:null!==(n=s.videoHeight)&&void 0!==n?n:0}))}_onLoadStart(){I(this._name,"[videoelement:event] loadstart")}_onSuspend(){I(this._name,"[videoelement:event] suspend")}_onStalled(){I(this._name,"[videoelement:event] stalled")}_onWaiting(){I(this._name,"[videoelement:event] waiting")}_onEncrypted(){I(this._name,"[videoelement:event] encrypted")}_onError(e){I(this._name,"[videoelement:event] error"),this.trigger(new ve(fe.CONNECT_FAILURE,void 0,{error:e.message}))}async attemptAutoplay(e=!1){try{await this.play(),this.isMuted()&&this.trigger(new ve(fe.AUTO_PLAYBACK_MUTED,void 0,{element:this._view}))}catch(t){e?(this.mute(),this.attemptAutoplay(e)):this.trigger(new ve(fe.AUTO_PLAYBACK_FAILURE,void 0,{error:t.message?t.message:t,element:this._view}))}}async play(){var e,t;if(I(this._name,"[videoelement:action] play"),!(null===(e=this._view)||void 0===e?void 0:e.paused))return I(this._name,"[videoelement:action] play (ALREADY PLAYING)"),!0;try{return await(null===(t=this._view)||void 0===t?void 0:t.play()),!0}catch(e){throw k(this._name,"[videoelement:action] play (FAULT) - "+e.message),e}}async pause(){var e;I(this._name,"[videoelement:action] pause");try{return await(null===(e=this._view)||void 0===e?void 0:e.pause()),!0}catch(e){O(this._name,"[videoelement:action] pause (CATCH::FAULT) - "+e.message)}return!1}async resume(){var e;I(this._name,"[videoelement:action] resume");try{return await(null===(e=this._view)||void 0===e?void 0:e.play()),!0}catch(e){O(this._name,"[videoelement:action] resume (CATCH::FAULT) - "+e.message)}return!1}async stop(){var e;I(this._name,"[videoelement:action] stop");try{return await(null===(e=this._view)||void 0===e?void 0:e.pause()),!0}catch(e){O(this._name,"[videoelement:action] stop (CATCH::FAULT) - "+e.message)}return!1}mute(){this._view&&(this._view.muted=!0);const e=this.getControls();e&&e.setMutedState(!0)}unmute(){this._view&&(this._view.muted=!1);const e=this.getControls();e&&e.setMutedState(!1)}setVolume(e){this.unmute(),this._view&&(this._view.volume=e)}getVolume(){var e,t;return null!==(t=null===(e=this._view)||void 0===e?void 0:e.volume)&&void 0!==t?t:0}seekTo(e,t=void 0){this._view&&(this._view.currentTime=t?e*t:e)}toggleFullScreen(e){try{(e||this._view)&&ie.toggleFullScreen(null!=e?e:this._view)}catch(e){}}async unpublish(){var e;try{await this.stop(),null===(e=this._view)||void 0===e||e.dispatchEvent(new Event("ended"))}catch(e){}}disconnect(){this._cleanup()}isVOD(){return this._isVOD}isMuted(){var e,t;return null!==(t=null===(e=this._view)||void 0===e?void 0:e.muted)&&void 0!==t&&t}getControls(){}}const St="WHEPClient",Et=at,Ct=e=>I(St,e),ft=e=>k(St,e),bt=e=>O(St,e);class wt extends pt{constructor(e,t,i){super(),this._videoMuted=!0,this._audioMuted=!0;const n=e?se(e):Et,s=i||Et,o={...s,...n,endpoint:e,mediaElementId:t?t.id:s.mediaElementId};this._videoUnmuteHandler=this._onVideoUnmute.bind(this),this._audioUnmuteHandler=this._onAudioUnmute.bind(this),e&&this.internalInit(o)}async internalInit(e){await this.init(e),await this.subscribe()}async _runMuteCheck(){var e,t,i;if(this.getPeerConnection())try{let n=this._videoMuted,s=this._audioMuted;const o=await(null===(e=this.getPeerConnection())||void 0===e?void 0:e.getStats());if(null==o||o.forEach(e=>{const{type:t,kind:i,bytesReceived:o}=e;"inbound-rtp"!==t&&"inboundrtp"!==t||("video"===i?n=o<=0:"audio"===i&&(s=o<=0))}),n===this._videoMuted&&s===this._audioMuted)return;this._videoMuted=n,this._audioMuted=s;const a={data:{streamingMode:(t=!this._videoMuted,i=!this._audioMuted,t&&i?ut.FULL:t?ut.VIDEO:i?ut.AUDIO:ut.EMPTY),method:"onMetaData"},type:"metadata",method:"onMetaData",eventTimestamp:(new Date).getTime()};this._onMetaData(a)}catch(e){ft(e.message||e)}}_onVideoUnmute(e){const t=e.target;null==t||t.removeEventListener("unmute",this._videoUnmuteHandler);const i=setTimeout(async()=>{clearTimeout(i),this._runMuteCheck()},1e3)}_onAudioUnmute(e){const t=e.target;null==t||t.removeEventListener("unmute",this._audioUnmuteHandler);const i=setTimeout(async()=>{clearTimeout(i),this._runMuteCheck()},1e3)}_attachSourceHandler(e){this._sourceHandler=new vt(e,this.getType())}_glomTrigger(e){e.on("*",e=>{const{type:t,data:i}=e;this.trigger(new ve(t,this,i))})}_playIfAutoplaySet(e,t){var i;if(e&&t){const{muteOnAutoplayRestriction:n}=e;ie.hasAttributeDefined(t,"autoplay")&&(null===(i=this._sourceHandler)||void 0===i||i.attemptAutoplay(n))}}addMediaStreamToPlayback(e,t){var i;!this._playbackView&&e&&(this._playbackView=new dt(e)),null===(i=this._playbackView)||void 0===i||i.attachStream(t)}async requestOffer(i){var n;Ct("[requestoffer]");const{iceTransport:s,maintainStreamVariant:o,videoEncoding:a,audioEncoding:r,connectionParams:l,mungeOffer:d}=this._options;i.addTransceiver("video",{direction:"recvonly"}),i.addTransceiver("audio",{direction:"recvonly"});const h={transport:s,doNotSwitch:o};a&&a!==t.NONE&&(h.videoEncoding=a),r&&r!==e.NONE&&(h.audioEncoding=r);const c=null!=l?l:{},u=await i.createOffer(),p=await(null===(n=this._whipWhepService)||void 0===n?void 0:n.postSDPOffer(u.sdp,{...c,...h},!1));if(!p)throw ft("Failed to get offer from WHEP"),new Error("Failed to get offer from WHEP");const{sdp:_}=p;let m=_;return d&&(Ct(`[MUNGE:before] offer: ${m}`),m=d(m),Ct(`[MUNGE:after] offer: ${m}`)),m}async requestAnswer(e){const{mungeAnswer:t}=this._options;let i=(await e.createAnswer()).sdp;return t&&(Ct(`[MUNGE:before] answer: ${i}`),i=t(i),Ct(`[MUNGE:after] answer: ${i}`)),i}async sendAnswer(e){var t;const{connectionParams:i}=this._options;return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.postSDPAnswer(e,i))}async postCandidateFragments(e){var t;const{connectionParams:i}=this._options,n=Ie(e,void 0,!0);return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.trickle(n,i))}async init(e){var t;this._options={...Et,...e},this._options.subscriptionId=this._options.subscriptionId||`subscriber-${Math.floor(65536*Math.random()).toString(16)}`;const i=oe(this._options,"whep"),{includeDataChannel:n,disableProxy:s}=this._options;return this._whipWhepService=new xe(`${i}?requestId=${this._options.subscriptionId}`,n,s),this._messageTransport=this._whipWhepService,(null===(t=this._options)||void 0===t?void 0:t.stats)&&this.monitorStats(this._options.stats),this}async subscribe(){var e,t,i,n,s,o,a,r;const{connectionParams:l,rtcConfiguration:d,includeDataChannel:h,signalingSocketOnly:c,enableChannelSignaling:u,dataChannelConfiguration:p}=this._options;try{const r=l||{},m=await(null===(e=this._whipWhepService)||void 0===e?void 0:e.getOptions(r));this.trigger(new ve(fe.CONNECT_SUCCESS,this,null===(t=this._whipWhepService)||void 0===t?void 0:t.getUrl())),(null==m?void 0:m.links)&&(this._options.rtcConfiguration={...d,iceServers:m.links}),(null==m?void 0:m.origin)&&this.trigger(new ve(be.HOST_ENDPOINT_CHANGED,this,{endpoint:m.origin})),(null==m?void 0:m.statisticsEndpoint)&&this._onStatisticsEndpointChange(m.statisticsEndpoint);const g=h||u||c?p:void 0;this._peerConnectionHelper=new ct({onUnpublish:this._onUnpublish.bind(this),onStreamUnavailable:this._onStreamUnavailable.bind(this),onSubscriberStatus:this._onSubscriberStatus.bind(this),onStreamSwitchComplete:this._onStreamSwitchComplete.bind(this),onDataChannelError:this._onDataChannelError.bind(this),onSendReceived:this._onSendReceived.bind(this),onMetaData:this._onMetaData.bind(this),onConnectionClosed:this._onConnectionClosed.bind(this),onDataChannelOpen:this._onDataChannelOpen.bind(this),onDataChannelClose:this._onDataChannelClose.bind(this),onDataChannelMessage:this._onDataChannelMessage.bind(this),onPeerConnectionOpen:this._onPeerConnectionOpen.bind(this),onPeerConnectionFail:this._onPeerConnectionFail.bind(this),onPeerConnectionClose:this._onPeerConnectionClose.bind(this),onIceCandidate:this._onIceCandidate.bind(this),onSDPSuccess:this._onSDPSuccess.bind(this),onSDPError:this._onSDPError.bind(this),onStatisticsEndpointChange:this._onStatisticsEndpointChange.bind(this)}),await this._peerConnectionHelper.setUpWithPeerConfiguration(this._options.rtcConfiguration,g),null===(i=this.getPeerConnection())||void 0===i||i.addEventListener("track",e=>{const{buffer:t}=this._options;Ct("[peerconnection.ontrack]");const{streams:i,track:n,receiver:s,transceiver:o}=e;s.playoutDelayHint=t,s.jitterBufferDelayHint=t,this.trigger(new ve(be.TRACK_ADDED,this,{streams:i,track:n,receiver:s,transceiver:o})),this._mediaStream=i&&i.length>0?i[0]:void 0,"video"===n.kind?(this._videoMuted=n.muted,n.muted&&n.addEventListener("unmute",this._videoUnmuteHandler)):"audio"===n.kind&&(this._audioMuted=n.muted,n.muted&&n.addEventListener("unmute",this._audioUnmuteHandler)),this._runMuteCheck()}),this.trigger(new ve(be.PEER_CONNECTION_AVAILABLE,this,this.getPeerConnection())),this.trigger(new ve(be.OFFER_START,this));const v=await this.requestOffer(this.getPeerConnection()),S=new RTCSessionDescription({type:"offer",sdp:v});await(null===(n=this.getPeerConnection())||void 0===n?void 0:n.setRemoteDescription(S)),this.trigger(new ve(be.OFFER_END,this)),this.trigger(new ve(be.ANSWER_START,this));const E=await this.requestAnswer(this.getPeerConnection()),C=(_=E).includes("stereo=1")?_:_.replace("useinbandfec=1","useinbandfec=1;stereo=1;sprop-stereo=1"),f=new RTCSessionDescription({type:"answer",sdp:C});await(null===(s=this.getPeerConnection())||void 0===s?void 0:s.setLocalDescription(f)),await this.sendAnswer(C),this.trigger(new ve(be.ANSWER_END,this));const b=await this._peerConnectionHelper.waitToGatherIce(),{sdp:w}=b;return await this.postCandidateFragments(w),this.trigger(new ve(be.ICE_TRICKLE_COMPLETE,this)),this._mediaStream&&(this.trigger(new ve(be.ON_ADD_STREAM,this,this._mediaStream)),this.addMediaStreamToPlayback(this._options.mediaElementId,this._mediaStream)),(null===(o=this._playbackView)||void 0===o?void 0:o.view)&&this._attachSourceHandler(this._playbackView.view),this._sourceHandler&&this._glomTrigger(this._sourceHandler),this._playIfAutoplaySet(this._options,null===(a=this._playbackView)||void 0===a?void 0:a.view),this}catch(e){throw ft(null!==(r=e.message)&&void 0!==r?r:"Could not subscribe."),e instanceof Me?this._onStreamUnavailable(e):this.trigger(new ve(fe.CONNECT_FAILURE,this,e)),this._options.maintainConnectionOnSubscribeErrors||this.unsubscribe(!0),e}var _}async unsubscribe(e=!1){var t;Ct("[unsubscribe]"),this._peerConnectionHelper&&await this._peerConnectionHelper.tearDown(),this._whipWhepService&&await this._whipWhepService.tearDown(null,e),this._sourceHandler&&this._sourceHandler.disconnect(),this.unmonitorStats(),null===(t=this._playbackView)||void 0===t||t.detachStream(),this._playbackView=void 0,this._whipWhepService=void 0,this._messageTransport=void 0,this._peerConnectionHelper=void 0,this._sourceHandler=void 0,this._mediaStream=void 0,this.trigger(new ve(fe.SUBSCRIBE_STOP,this))}send(e,t){var i;return null===(i=this.getMessageTransport())||void 0===i?void 0:i.post({send:{method:e,data:"string"==typeof t?JSON.parse(t):t}})}async callServer(e,t){var i;const n="switchStreams"===e,{app:s,streamName:o}=this._options;if(n){const{path:i}=t[0];this._requestedStreamSwitch=i,Ct(`[callServer:switch]:: ${e}, ${s}/${o} -> ${i}`)}return null===(i=this.getMessageTransport())||void 0===i?void 0:i.postAsync({callAdapter:{method:e,arguments:t}})}sendLog(e,t){var i;try{const n=Object.keys(N).find(t=>t.toLowerCase()===e.toLowerCase())?e:N.DEBUG,s="string"==typeof t?t:JSON.stringify(t);null===(i=this.getMessageTransport())||void 0===i||i.post({log:n.toUpperCase(),message:s})}catch(e){const t=e.message||e;ft("Could not send log to server. Message parameter expected to be String or JSON-serializable object."),ft(t)}}enableStandby(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0,muteVideo:!0}})}disableStandby(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1,muteVideo:!1}})}muteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0}})}unmuteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1}})}muteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!0}})}unmuteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!1}})}get options(){return this._options}getOptions(){return this._options}getPeerConnection(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.connection}getDataChannel(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.dataChannel}getMediaStream(){return this._mediaStream}getMessageTransport(){return this._messageTransport}getPlayer(){var e;return null===(e=this._playbackView)||void 0===e?void 0:e.view}play(){Ct("[play]"),this._sourceHandler?this._sourceHandler.play():bt("Cannot play without a Source Handler.")}pause(){Ct("[pause]"),this._sourceHandler?this._sourceHandler.pause():bt("Cannot pause without a Source Handler.")}resume(){Ct("[resume]"),this._sourceHandler?this._sourceHandler.resume():bt("Cannot resume without a Source Handler.")}stop(){Ct("[stop]"),this._sourceHandler?this._sourceHandler.stop():bt("Cannot stop without a Source Handler.")}setVolume(e){Ct("[setVolume]"),this._sourceHandler?this._sourceHandler.setVolume(e):bt("Cannot set volume without a Source Handler.")}getVolume(){var e,t,i;return Ct("[getVolume]"),this._sourceHandler?this._sourceHandler.getVolume():(bt("Cannot get volume without a Source Handler."),null!==(i=null===(t=null===(e=this._playbackView)||void 0===e?void 0:e.view)||void 0===t?void 0:t.volume)&&void 0!==i?i:0)}mute(){Ct("[mute]"),this._sourceHandler?this._sourceHandler.mute():bt("Cannot mute without a Source Handler.")}unmute(){Ct("[unmute]"),this._sourceHandler?this._sourceHandler.unmute():bt("Cannot unmute without a Source Handler.")}seekTo(e){Ct("[seekTo]"),this._sourceHandler?this._sourceHandler.seekTo(e):bt("Cannot seek without a Source Handler.")}toggleFullScreen(){Ct("[toggleFullScreen]"),this._sourceHandler?this._sourceHandler.toggleFullScreen():bt("Cannot toggle full screen without a Source Handler.")}monitorStats(e){Ct("[monitorStats]");const{host:t,endpoint:i,app:n,streamName:s,subscriptionId:o,connectionParams:a}=this._options,r=null!=e?e:ze;return this._statisticsConfiguration={...r,host:t,app:n,hostEndpoint:i,streamName:s,subscriptionId:o,connectionParams:a},this._statsMonitor?bt("Cannot monitor stats without a Peer Connection. Please call `init` before calling `monitorStats`."):this._statsMonitor=new gt(this._statisticsConfiguration,{onStatsReport:this._onStatsReport.bind(this),getPeerConnection:this.getPeerConnection.bind(this),getMessageTransport:this.getMessageTransport.bind(this),on:this.on.bind(this),off:this.off.bind(this),trigger:this.trigger.bind(this)}),this}unmonitorStats(){return this._statsMonitor&&this._statsMonitor.dispose(),this._statsMonitor=void 0,this._statisticsConfiguration=void 0,this}_onUnpublish(){Ct("[unpublish]"),this.trigger(new ve(fe.PLAY_UNPUBLISH,this)),this._sourceHandler&&this._sourceHandler.unpublish()}_onStreamUnavailable(e){Ct(`Stream ${this._options.streamName} does not exist.`),Ct("[onstreamunavailable]: "+JSON.stringify(e,null,2)),this.trigger(new ve(fe.SUBSCRIBE_INVALID_NAME,this))}_onDataChannelError(e,t){ft(`Data channel error: ${t}`),this.trigger(new ve(be.DATA_CHANNEL_ERROR,this,{dataChannel:e,error:t}))}_onSendReceived(e,t){Ct(`Send received: ${e} ${JSON.stringify(t)}`),"onMetaData"===e?this._onMetaData(t):this.trigger(new ve(fe.SUBSCRIBE_SEND_INVOKE,this,{methodName:e,data:t}))}_onStreamSwitchComplete(){Ct("[streamswitch::complete]");const e=this._requestedStreamSwitch;this.trigger(new ve(be.SUBSCRIBE_STREAM_SWITCH,this,{path:e})),this._requestedStreamSwitch=void 0}_onMetaData(e){const{orientation:t,streamingMode:i}=e,n=this._streamingMode;void 0!==t&&t!==this._orientation&&(this._orientation=t,this.trigger(new ve(fe.ORIENTATION_CHANGE,this,{orientation:parseInt(t,10),viewElement:this._playbackView?this._playbackView.view:void 0}))),i&&void 0!==i&&i!==n&&(this._streamingMode=i,this.trigger(new ve(fe.STREAMING_MODE_CHANGE,this,{streamingMode:i,previousStreamingMode:n,viewElement:this._playbackView?this._playbackView.view:void 0}))),this.trigger(new ve(fe.SUBSCRIBE_METADATA,this,e))}_onConnectionClosed(){Ct("Connection closed"),this.unsubscribe(!0),this.trigger(new ve(fe.CONNECTION_CLOSED,this))}_onDataChannelOpen(e){Ct(`Data channel opened: ${e.label}`),this.trigger(new ve(be.DATA_CHANNEL_OPEN,this,{dataChannel:e})),this.trigger(new ve(be.DATA_CHANNEL_AVAILABLE,this,{name:e.label,dataChannel:e})),this._messageTransport=this._peerConnectionHelper,this.trigger(new Se(we.CHANGE,this,{controller:this,transport:this._messageTransport})),this.trigger(new ve(fe.SUBSCRIBE_START,this))}_onDataChannelClose(e){Ct(`Data channel closed: ${e.label}`),this.trigger(new ve(be.DATA_CHANNEL_CLOSE,this,{dataChannel:e}))}_onDataChannelMessage(e,t){Ct(`Data channel message: ${t.data}`),this.trigger(new ve(be.DATA_CHANNEL_MESSAGE,this,{dataChannel:e,message:t}))}_onPeerConnectionOpen(){var e;Ct("Peer connection opened"),this.trigger(new ve(be.PEER_CONNECTION_OPEN,this,this.getPeerConnection())),(null===(e=this._options)||void 0===e?void 0:e.includeDataChannel)||this.trigger(new ve(fe.SUBSCRIBE_START,this))}_onPeerConnectionFail(){ft("Peer connection failed"),this.trigger(new ve(fe.SUBSCRIBE_FAIL,this))}_onPeerConnectionClose(e){Ct(`Peer connection closed: ${e.type}`)}_onIceCandidate(e){Ct(`ICE candidate: ${e.candidate}`),this.trigger(new ve(be.CANDIDATE_CREATE,this,{candidate:e}))}_onPeerConnectionTrackAdd(e){Ct(`Peer connection track added: ${e.id}`)}_onSubscriberStatus(e){Ct(`Subscriber status: ${JSON.stringify(e)}`)}_onSDPSuccess(){Ct("SDP success")}_onSDPError(e){ft(`SDP error: ${e}`)}_onStatisticsEndpointChange(e){Ct(`Statistics endpoint changed: ${e}`),this._statsMonitor&&this._statsMonitor.updateEndpoint(e),this.trigger(new ve(fe.STATISTICS_ENDPOINT_CHANGE,this,{statisticsEndpoint:e}))}_onStatsReport(e,t){this.trigger(new ve(be.STATS_REPORT,this,{connection:e,report:t}))}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}trigger(e){super.trigger(e)}getType(){return"RTC"}}class At extends vt{constructor(e,t){super(e,t),this._playingStarted=!1,this.onOrientation=this._onOrientationMetadata.bind(this),this.onStreamingMode=this._onStreamingModeMetadata.bind(this),ie.onOrientationMetadata(this._view,this.onOrientation),ie.onStreamingModeMetadata(this._view,this.onStreamingMode),this.onPlaying=this._onPlaying.bind(this),this.onSourceError=this._onSourceError.bind(this),this._view.addEventListener("playing",this.onPlaying)}addSource(e){this._source=ie.createElement("source"),this._source.type="application/x-mpegURL",this._source.src=e,this._view.firstChild?this._view.insertBefore(this._source,this._view.firstChild):this._view.appendChild(this._source),this._source.addEventListener("error",this.onSourceError)}_onPlaying(){this._playingStarted||this.trigger(new ve(fe.SUBSCRIBE_START,this._view)),this._playingStarted=!0}_onSourceError(e){I(this._name,"[source:event] error"),this.trigger(new ve(fe.CONNECT_FAILURE,void 0,e))}_onOrientationMetadata(e){const{orientation:t}=e,i=parseInt(t,10);t&&this._orientation!==i&&(I(this._name,"Metadata received: "+JSON.stringify(e,null,2)),this._orientation=i,this.trigger(new ve(fe.ORIENTATION_CHANGE,{orientation:this._orientation,viewElement:this._view})),this.trigger(new ve(fe.SUBSCRIBE_METADATA,void 0,e)))}_onStreamingModeMetadata(e){const{streamingMode:t}=e,i=this._streamingMode;t&&i!==t&&(I(this._name,"Metadata received: "+JSON.stringify(e,null,2)),this._streamingMode=t,this.trigger(new ve(fe.STREAMING_MODE_CHANGE,void 0,{streamingMode:this._streamingMode,previousStreamingMode:i,viewElement:this._view})),this.trigger(new ve(fe.SUBSCRIBE_METADATA,void 0,e)))}_cleanup(){this._view&&this._view.removeEventListener("playing",this.onPlaying),this._source&&(this._source.removeEventListener("error",this.onSourceError),this._view.removeChild(this._source),this._source=void 0),super._cleanup()}}const yt="HLSSubscriber",Tt=e=>I(yt,e),Lt=e=>O(yt,e);class Pt extends pt{constructor(){super()}_glomTrigger(e){e.on("*",e=>{const{type:t,data:i}=e;this.trigger(new ve(t,this,i))})}_playIfAutoplaySet(e,t){var i;if(e&&t){const{muteOnAutoplayRestriction:n}=e;ie.hasAttributeDefined(t,"autoplay")&&(null===(i=this._sourceHandler)||void 0===i||i.attemptAutoplay(n))}}async init(e){if(!ie.supportsHLS())throw new Error("Native HLS playback is not supported on this browser.");return this._options={...rt,...e},this}async subscribe(){var e;try{const t=/^http(|s).*\.m3u8/g,{endpoint:i,mediaElementId:n}=this._options;return this._fileURL=i&&i.match(t)?i:(e=>{const{host:t,protocol:i,port:n,app:s,streamName:o,connectionParams:a}=e,r="ws"===i||"http"===i?"http":"https",l=`${r}://${t}:${n||("http"===r?5080:443)}/${s}/${o}.m3u8`;if(a)return`${l}?${Object.entries(a).map(([e,t])=>`${e}=${t}`).join("&")}`;return l})(this._options),!this._playbackView&&n&&(this._playbackView=new dt(n),this._sourceHandler=new At(this._playbackView.view,this.getType()),this._sourceHandler.addSource(this._fileURL),this._glomTrigger(this._sourceHandler)),this.trigger(new ve(fe.CONNECT_SUCCESS,this,this._fileURL)),this._playIfAutoplaySet(this._options,null===(e=this._playbackView)||void 0===e?void 0:e.view),this}catch(e){throw e(e.message),this.trigger(new ve(fe.CONNECT_FAILURE,this,e.message)),e}}async unsubscribe(){var e;return this._sourceHandler&&this._sourceHandler.disconnect(),null===(e=this._playbackView)||void 0===e||e.detachStream(),this._playbackView=void 0,this._sourceHandler=void 0,this.trigger(new ve(fe.SUBSCRIBE_STOP,this)),this}play(){Tt("[play]"),this._sourceHandler?this._sourceHandler.play():Lt("Cannot play without a Source Handler.")}pause(){Tt("[pause]"),this._sourceHandler?this._sourceHandler.pause():Lt("Cannot pause without a Source Handler.")}resume(){Tt("[resume]"),this._sourceHandler?this._sourceHandler.resume():Lt("Cannot resume without a Source Handler.")}stop(){Tt("[stop]"),this._sourceHandler?this._sourceHandler.stop():Lt("Cannot stop without a Source Handler.")}setVolume(e){Tt("[setVolume]"),this._sourceHandler?this._sourceHandler.setVolume(e):Lt("Cannot set volume without a Source Handler.")}getVolume(){var e,t,i;return Tt("[getVolume]"),this._sourceHandler?this._sourceHandler.getVolume():(Lt("Cannot get volume without a Source Handler."),null!==(i=null===(t=null===(e=this._playbackView)||void 0===e?void 0:e.view)||void 0===t?void 0:t.volume)&&void 0!==i?i:0)}mute(){Tt("[mute]"),this._sourceHandler?this._sourceHandler.mute():Lt("Cannot mute without a Source Handler.")}unmute(){Tt("[unmute]"),this._sourceHandler?this._sourceHandler.unmute():Lt("Cannot unmute without a Source Handler.")}seekTo(e){Tt("[seekTo]"),this._sourceHandler?this._sourceHandler.seekTo(e):Lt("Cannot seek without a Source Handler.")}toggleFullScreen(){Tt("[toggleFullScreen]"),this._sourceHandler?this._sourceHandler.toggleFullScreen():Lt("Cannot toggle full screen without a Source Handler.")}getPlayer(){var e;return null===(e=this._playbackView)||void 0===e?void 0:e.view}get options(){return this._options}getOptions(){return this._options}get fileURL(){return this._fileURL}getFileURL(){return this._fileURL}getType(){return"HLS"}}const Nt={baseURL:void 0,fullURL:void 0,hlsjsRef:void 0,hlsElement:void 0,usePlaybackControlsUI:!0,options:{debug:!1,backBufferLength:0}},Dt={...at,liveSeek:Nt};class Rt extends U{trigger(e){super.trigger(e)}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}}var Ht,It;!function(e){e.SEEK_START="Seek.Start",e.SEEK_END="Seek.End"}(Ht||(Ht={})),function(e){e.CHANGE="Slider.Change",e.CHANGE_START="Slider.Change.Start",e.CHANGE_COMPLETE="Slider.Change.Complete"}(It||(It={}));class Ot extends me{constructor(e,t,i){super(e,i),this._slider=t}get slider(){return this._slider}}const{createElement:kt,addGlobalEventListener:Mt,removeGlobalEventListener:Ut,globalUnassign:Bt,getAssignedValue:Vt,globalAssign:Ft}=ie,$t="ControlSlider",Gt="r5_liveseek_event_owner";class Wt extends U{constructor(e){super(),this._value=0,this._disabled=!1,this._eventStartPosition=0,this.debug=e=>I($t,e),this.warn=e=>O($t,e),this.name=[$t,e].join("::"),this.debug("[init]"),this._container=kt("div"),this._button=this.createButton(),this._track=this.createTrack(),this._progressBar=this.createProgressBar(),this._container.appendChild(this._track),this._container.appendChild(this._progressBar),this._container.appendChild(this._button),this._layout(),this._mouseupHandler=this._mouseup.bind(this),this._mousedownHandler=this._mousedown.bind(this),this._mousemoveHandler=this._mousemove.bind(this),this._touchupHandler=this._touchproxy.bind(this),this._touchdownHandler=this._touchproxy.bind(this),this._touchmoveHandler=this._touchproxy.bind(this),this._updateHandlers(this._disabled)}_touchproxy(e){var t,i,n,s;const o=e;this.debug(`${o.type} touches: ${(null===(t=o.changedTouches)||void 0===t?void 0:t.length)||0}`);try{o.preventDefault()}catch(e){this.warn("Failed to prevent default on touch event.")}if(!o.touches||o.touches.length>1||"touchend"===o.type&&o.touches.length>0)return;let a,r="";const l=o.target||document.body;switch(o.type){case"touchstart":r="mousedown",a=null===(i=o.changedTouches)||void 0===i?void 0:i[0];break;case"touchmove":r="mousemove",a=null===(n=o.changedTouches)||void 0===n?void 0:n[0];break;case"touchend":r="mouseup",a=null===(s=o.changedTouches)||void 0===s?void 0:s[0]}if(a&&r){const e=new MouseEvent(r,{bubbles:!0,cancelable:!0,view:l.ownerDocument.defaultView,screenX:a.screenX,screenY:a.screenY,clientX:a.clientX,clientY:a.clientY,ctrlKey:o.ctrlKey,altKey:o.altKey,shiftKey:o.shiftKey,metaKey:o.metaKey,button:0,relatedTarget:null});l.dispatchEvent(e)}}_mouseup(){this._eventStartPosition=0,Bt(Gt),Ut("mousemove",this._mousemoveHandler),Ut("mouseup",this._mouseupHandler),Ut("touchmove",this._touchmoveHandler),Ut("touchend",this._touchupHandler),this.trigger(new Ot(It.CHANGE_COMPLETE,this))}_mousemove(e){if(Vt(Gt)!==this.name)return;this.debug(`[mousemove] ${this.name}`);const t=e.clientX-this._eventStartPosition,i=this._button.parentNode.getBoundingClientRect();let n=this._eventStartPosition+t-i.left;n=Math.max(0,n),n=Math.min(n,i.width);const s=n/i.width;this.trigger(new Ot(It.CHANGE,this,s))}_mousedown(e){this._eventStartPosition=e.clientX,this.trigger(new Ot(It.CHANGE_START,this)),Ft(Gt,this.name),Mt("mousemove",this._mousemoveHandler),Mt("mouseup",this._mouseupHandler),Mt("touchmove",this._touchmoveHandler),Mt("touchend",this._touchupHandler)}_updateHandlers(e){this._eventStartPosition=0,e?(this._track.removeEventListener("click",this._mousemoveHandler),this._progressBar.removeEventListener("click",this._mousemoveHandler),this._button.removeEventListener("mousedown",this._mousedownHandler),Ut("mousemove",this._mousemoveHandler),Ut("mouseup",this._mouseupHandler),Ut("touchmove",this._touchmoveHandler),Ut("touchend",this._touchupHandler),this._track.classList.add("red5pro-media-slider-disabled"),this._progressBar.classList.add("red5pro-media-slider-disabled"),this._button.classList.add("red5pro-media-slider-disabled")):(this._track.addEventListener("click",this._mousemoveHandler),this._progressBar.addEventListener("click",this._mousemoveHandler),this._button.addEventListener("mousedown",this._mousedownHandler),this._button.addEventListener("touchstart",this._touchdownHandler),this._track.classList.remove("red5pro-media-slider-disabled"),this._progressBar.classList.remove("red5pro-media-slider-disabled"),this._button.classList.remove("red5pro-media-slider-disabled"))}_layout(){const e=this._progressBar.parentNode.clientWidth*this._value;this._progressBar.style.width=e+"px",this._button.style.left=e-.5*this._button.clientWidth+"px"}createButton(){const e=kt("span");return e.classList.add("red5pro-media-slider-button"),e}createProgressBar(){const e=kt("span");return e.classList.add("red5pro-media-slider-progress"),e}createTrack(){const e=kt("span");return e.classList.add("red5pro-media-slider-track"),e}get value(){return this._value}set value(e){this._value=e,this._layout()}get disabled(){return this._disabled}set disabled(e){this._disabled=e,this._updateHandlers(e)}get view(){return this._container}}const{createElement:xt,isTouchEnabled:jt,isPossiblySafari:Kt}=ie,zt=e=>I("PlaybackControls",e);class Jt extends Rt{constructor(e,t){super(),this._state=i.IDLE,this._mutedState=!1,this._resumeAfterSeek=!1,this._playbackDuration=0,this._volumeValue=1,this._player=e,this._container=t,this._onPlayPauseClickBound=this._onPlayPauseClick.bind(this),this._decorate(this._container)}_decorate(e){if(!e)return;zt("[decorate]");const t=xt("div");let n;t.classList.add("red5pro-media-control-bar"),this._playPauseButton=this._createPlayPauseButton(),this._muteButton=this._createMuteButton(),this._volumeField=this._createVolumeControl(),this._seekTimeField=this._createSeekControl(),this._timeField=this._createPlaybackTime(),this._fullScreenButton=this._createFullScreenToggle(),t.appendChild(this._playPauseButton),t.appendChild(this._timeField),t.appendChild(this._seekTimeField.view),t.appendChild(this._muteButton),t.appendChild(this._volumeField.view),t.appendChild(this._fullScreenButton),e.appendChild(t),this._controlbar=t;const s=()=>{clearTimeout(n),n=setTimeout(()=>{t.classList.remove("red5pro-media-control-bar-show")},6e3)};jt()?(t.classList.add("red5pro-media-control-bar-show"),e.addEventListener("touchend",()=>{t.classList.toggle("red5pro-media-control-bar-show"),s()}),s()):(e.addEventListener("mouseover",()=>{t.classList.add("red5pro-media-control-bar-show")}),e.addEventListener("mouseout",()=>{t.classList.remove("red5pro-media-control-bar-show")})),this.setState(i.IDLE).onFullScreenChange(!1).setSeekTime(0).enable(!1)}_onPlayPauseClick(){return this.getState()===i.PLAYING?this._player.pause(!0):this.getState()===i.PAUSED?this._player.resume(!0):this._player.play(!0),this}_createPlayPauseButton(){const e=xt("button");return e.setAttribute("aria-label","Toggle Playback"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-playpause-button"),e}_createMuteButton(){const e=xt("button");return e.setAttribute("aria-label","Toggle Mute Audio"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-muteunmute-button"),e.addEventListener("click",()=>{this.getMutedState()?(this._player.unmute(),this.setMutedState(!1)):(this._player.mute(),this.setMutedState(!0))}),e}_createVolumeControl(){const e=new Wt("volume");return e.view.classList.add("red5pro-media-control-element"),e.view.classList.add("red5pro-media-volume-slider"),e.view.classList.add("red5pro-media-slider"),e.on(It.CHANGE,e=>{const t=Number(e.data);this._player.setVolume(t)}),e}_createSeekControl(){const e=new Wt("seek");return e.view.classList.add("red5pro-media-control-element"),e.view.classList.add("red5pro-media-seektime-slider"),e.view.classList.add("red5pro-media-slider"),e.on(It.CHANGE_START,()=>{this.getState()===i.PLAYING&&(this._resumeAfterSeek=!0,this._player.pause(!0,!0)),this.trigger(new me(Ht.SEEK_START))}),e.on(It.CHANGE,e=>{const t=Number(e.data);this._player.seekTo(t,0===this._playbackDuration?void 0:this._playbackDuration),this.setSeekTime(t*this._playbackDuration,this._playbackDuration)}),e.on(It.CHANGE_COMPLETE,()=>{this._resumeAfterSeek&&this.getState()===i.PAUSED&&(this._resumeAfterSeek=!1,this._player.resume(!0)),this.trigger(new me(Ht.SEEK_END))}),e}_createPlaybackTime(){const e=xt("span"),t=xt("text");return t.textContent="00:00",e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-time-field"),e.appendChild(t),e}_createFullScreenToggle(){const e=xt("button");return e.setAttribute("aria-label","Toggle Fullscreen"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-fullscreen-button"),e.addEventListener("click",()=>{this._player.toggleFullScreen()}),e}_formatTime(e){const t=new Date(1e3*e);return`${String(t.getUTCHours()).padStart(2,"0")}:${String(t.getUTCMinutes()).padStart(2,"0")}:${String(t.getUTCSeconds()).padStart(2,"0")}`}onStateChange(e){var t,n,s,o;return e===i.PLAYING?(null===(t=this._playPauseButton)||void 0===t||t.classList.remove("red5pro-media-play-button"),null===(n=this._playPauseButton)||void 0===n||n.classList.add("red5pro-media-pause-button")):(null===(s=this._playPauseButton)||void 0===s||s.classList.add("red5pro-media-play-button"),null===(o=this._playPauseButton)||void 0===o||o.classList.remove("red5pro-media-pause-button")),this}onMutedStateChange(e){var t,i,n,s;return e?(null===(t=this._muteButton)||void 0===t||t.classList.add("red5pro-media-mute-button"),null===(i=this._muteButton)||void 0===i||i.classList.remove("red5pro-media-unmute-button"),this._volumeField&&(this._volumeField.value=0)):(null===(n=this._muteButton)||void 0===n||n.classList.remove("red5pro-media-mute-button"),null===(s=this._muteButton)||void 0===s||s.classList.add("red5pro-media-unmute-button"),this._volumeField&&(this._volumeField.value=this._volumeValue)),this}onFullScreenChange(e){var t,i,n,s;return e?(null===(t=this._fullScreenButton)||void 0===t||t.classList.add("red5pro-media-exit-fullscreen-button"),null===(i=this._fullScreenButton)||void 0===i||i.classList.remove("red5pro-media-fullscreen-button")):(null===(n=this._fullScreenButton)||void 0===n||n.classList.remove("red5pro-media-exit-fullscreen-button"),null===(s=this._fullScreenButton)||void 0===s||s.classList.add("red5pro-media-fullscreen-button")),this}enable(e){var t,i,n,s;return e?(null===(t=this._playPauseButton)||void 0===t||t.classList.remove("red5pro-media-element-button-disabled"),null===(i=this._playPauseButton)||void 0===i||i.addEventListener("click",this._onPlayPauseClickBound)):(null===(n=this._playPauseButton)||void 0===n||n.classList.add("red5pro-media-element-button-disabled"),null===(s=this._playPauseButton)||void 0===s||s.removeEventListener("click",this._onPlayPauseClickBound)),this}getVolume(){return this._volumeValue}setVolume(e){return this._volumeField&&(this._volumeField.value=e),this._volumeValue=e,0===e?this.setMutedState(!0):this.getMutedState()&&this.setMutedState(!1),this}setSeekTime(e,t=0){return this._seekTimeField&&(this._seekTimeField.value=0===t?0:e/t,0!==this._playbackDuration&&this._playbackDuration<=e&&(this._seekTimeField.value=1)),this._timeField&&(!isFinite(this._playbackDuration)&&Kt()?this._timeField.innerText="Live Broadcast":this._timeField.innerText=this._formatTime(Math.floor(e))),this}setPlaybackDuration(e){return this._playbackDuration=e,this}getPlaybackDuration(){return this._playbackDuration}getState(){return this._state}setState(e){return zt(`[setState]: ${s[e]}`),this._state=e,this.onStateChange(this._state),this}setMutedState(e){return this._mutedState=e,this.onMutedStateChange(this._mutedState),this}getMutedState(){return"muted"in this._player?this._player.muted:this._mutedState}setAsVOD(e){return zt(`[setAsVOD]: ${e}`),this._seekTimeField&&(e?this._seekTimeField.disabled=!1:(this._seekTimeField.value=0,this._seekTimeField.disabled=!0)),this}detach(){this.enable(!1),this._controlbar&&this._controlbar.parentNode&&this._controlbar.parentNode.removeChild(this._controlbar),this._controlbar=void 0,this._container=void 0}}var Yt,qt;!function(e){e[e.LIVE=0]="LIVE",e[e.VOD=1]="VOD"}(Yt||(Yt={})),function(e){e.LIVE="LiveSeek.LIVE",e.VOD="LiveSeek.VOD"}(qt||(qt={}));const Qt={[Yt.LIVE]:qt.LIVE,[Yt.VOD]:qt.VOD};var Xt;!function(e){e.LIVE_SEEK_UNSUPPORTED="WebRTC.LiveSeek.Unsupported",e.LIVE_SEEK_ERROR="WebRTC.LiveSeek.Error",e.LIVE_SEEK_ENABLED="WebRTC.LiveSeek.Enabled",e.LIVE_SEEK_DISABLED="WebRTC.LiveSeek.Disabled",e.LIVE_SEEK_LOADING="WebRTC.LiveSeek.FragmentLoading",e.LIVE_SEEK_LOADED="WebRTC.LiveSeek.FragmentLoaded",e.LIVE_SEEK_CHANGE="WebRTC.LiveSeek.Change"}(Xt||(Xt={}));const{createElement:Zt,findByQuerySelector:ei,createHLSClient:ti,getHLSClientEventEnum:ii}=ie,ni="SourceHandlerSeekable",si=e=>I(ni,e),oi=e=>k(ni,e),ai=e=>O(ni,e);class ri extends vt{constructor(e,t,i,n,s=!0){super(e,`${t}-Seekable`),this._hlsElementGenerated=!1,this._hlsRecoverFlop=!1,this._hlsRecoverAttempts=0,this._isFragLoading=!1,this._wallOffset=NaN,this._lastDurationUpdate=0,this._averageSegmentDuration=6,this._isSeekable=!1,this._isHLSPlaybackActive=!1,this._container=s?this._determineContainer(e):void 0,this._liveSeekConfig=i,this._hlsOptions=n,this._usePlaybackControls=s,this.onHLSDurationChange=this._onHLSDurationChange.bind(this),this.onHLSTimeUpdate=this._onHLSTimeUpdate.bind(this),this.onHLSPlay=this._onHLSPlay.bind(this),this.onHLSPause=this._onHLSPause.bind(this)}_determineContainer(e){if(e.parentNode&&e.parentNode.classList.contains("red5pro-media-container"))return e.classList.add("red5pro-media"),e.parentNode;{const t=e.parentNode,i=Zt("div");return i.classList.add("red5pro-media-container"),e.classList.add("red5pro-media"),t.insertBefore(i,e),t.removeChild(e),i.appendChild(e),i}}_generateHLSLivePlayback(e,t,i){const n=`${i}-hls-vod`;let s=ei(`#${n}`);return s||(s=Zt("video"),s.id=n,s.classList.add("red5pro-hls-vod"),s.classList.add("red5pro-media-background"),s.setAttribute("playsinline","playsinline"),s.style.width="100%",s.style.height="100%",s.style.display="none",e.insertBefore(s,t),this._hlsElementGenerated=!0),s}_onDurationChange(e){var t;si("[videoelement:event] durationchange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();!this.isSeekable&&n&&n.setPlaybackDuration(i.duration)}_onTimeUpdate(e){var t;const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();if(this.isSeekable){if(!this._isHLSPlaybackActive){const e=this._hlsElement.duration,t=i.currentTime-this._lastDurationUpdate,s=isNaN(e)||0===e?i.currentTime:e+this._averageSegmentDuration+t;n&&n.setSeekTime(s,s),this.trigger(new ve(fe.PLAYBACK_TIME_UPDATE,void 0,{time:s,duration:s,action:"rtc time update (1)"}))}}else super._onTimeUpdate(e)}_onEnded(){this.isHLSPlaybackActive||super._onEnded()}_onHLSDurationChange(e){const t=e.target,i=e.duration||t.duration;isNaN(this._wallOffset)&&(this._wallOffset=i-this._view.currentTime),this._lastDurationUpdate=this._view.currentTime;const n=i+this._averageSegmentDuration;si(`[HLS:videoelement:duration] ${i}, ${this._averageSegmentDuration}`);const s=this.getControls();s&&s.setPlaybackDuration(n),this._isHLSPlaybackActive?this.trigger(new ve(fe.PLAYBACK_TIME_UPDATE,void 0,{time:t.currentTime,duration:n,action:"hls time update"})):this.trigger(new ve(fe.PLAYBACK_TIME_UPDATE,void 0,{time:n,duration:n,action:"hls time update"}))}_onHLSTimeUpdate(e){const t=e.target,i=this.getControls();i&&i.setSeekTime(t.currentTime,i.getPlaybackDuration()),t.currentTime>=t.duration?this._showHLSLivePlayback(!1,this._hlsElement,this._view,this._container):!isNaN(t.duration)&&this._isHLSPlaybackActive&&this.trigger(new ve(fe.PLAYBACK_TIME_UPDATE,void 0,{time:t.currentTime,duration:t.duration+this._averageSegmentDuration,action:"hls time update"}))}_onHLSPlay(){si("[HLS:videoelement:event] play");const e=this.getControls();e&&e.setState(i.PLAYING),this.trigger(new ve(fe.PLAYBACK_STATE_CHANGE,void 0,{code:i.PLAYING,state:s[i.PLAYING]}))}_onHLSPause(){si("[HLS:videoelement:event] pause");const e=this.getControls();e&&e.setState(i.PAUSED),this.trigger(new ve(fe.PLAYBACK_STATE_CHANGE,void 0,{code:i.PAUSED,state:s[i.PAUSED]}))}_addSeekableHandlers(e,t,i){if(t){const i=ii();t.on(i.ERROR,(i,n)=>{const{type:s,details:o,fatal:a,url:r}=n;if("networkerror"===s.toLowerCase()){if("levelemptyerror"===o.toLowerCase()){this.trigger(new ve(Xt.LIVE_SEEK_DISABLED,void 0,{hlsElement:e,hlsControl:t})),this.isSeekable=!1,t.destroy();const i=setTimeout(()=>{clearTimeout(i),this.enableLiveSeek(r,this._subscriptionId,this._hlsElement,!1)},3e3);return}this.trigger(new ve(Xt.LIVE_SEEK_ERROR,void 0,{hlsElement:e,hlsControl:t,error:n}))}else this.trigger(new ve(Xt.LIVE_SEEK_ERROR,void 0,{hlsElement:e,hlsControl:t,error:n}));"mediaerror"===s.toLowerCase()&&(this._hlsRecoverFlop&&t.swapAudioCodec(),this._hlsRecoverFlop=!this._hlsRecoverFlop,this._hlsRecoverAttempts=this._hlsRecoverAttempts+1,t.recoverMediaError()),a&&"networkerror"===s.toLowerCase()&&t.startLoad()}),t.on(i.MANIFEST_PARSED,()=>{try{e.pause()}catch(e){si(`Could not pause seekable live stream: ${e.message}`)}this.isSeekable=!0,this.trigger(new ve(Xt.LIVE_SEEK_ENABLED,void 0,{hlsElement:e,hlsControl:t}))}),t.on(i.FRAG_LOADING,(i,n)=>{const{frag:{stats:{loaded:s,total:o}}}=n;this.trigger(new ve(Xt.LIVE_SEEK_LOADING,void 0,{hlsElement:e,hlsControl:t,progress:s/o*100})),(this._isHLSPlaybackActive||this._isFragLoading)&&(this._isFragLoading=s/o>=1)}),t.on(i.FRAG_LOADED,(i,n)=>{this._isFragLoading=!1;const{frag:{endDTS:s,loader:o}}=n;if(!this._isHLSPlaybackActive&&!s)return;let a=6,r=0;if(o&&o.stats&&o.stats.segments){const e=o.stats.segments;for(let t=0;t{this._isFragLoading=!1;const{frag:{endDTS:s,loader:o}}=n;if(!this._isHLSPlaybackActive&&!s)return;let a=6,r=0;if(o&&o.stats&&o.stats.segments){const e=o.stats.segments;for(let t=0;tn.test(e));if(!a)return void ai(`Could not find last segment in manifest: ${e}`);const r=o.find(e=>i.test(e));if(!r)return void ai(`Could not find duration line in manifest: ${e}`);const l=r.match(i);if(!l)return void ai(`Could not find duration in manifest: ${e}`);const d=l[1],h=parseFloat(d),c=a.match(n);if(!c)return void ai(`Could not find segment length in manifest: ${e}`);const u=c[1];let p=parseInt(u,10);isNaN(p)&&(p=1),p=p>1?p-1:p,this._averageSegmentDuration=h,this.isSeekable=!0,this.trigger(new ve(Xt.LIVE_SEEK_ENABLED,void 0,{hlsElement:this._hlsElement,hlsControl:void 0})),this.onHLSDurationChange({target:t,duration:h*p}),this._manifestLoadTimeout=setTimeout(()=>{clearTimeout(this._manifestLoadTimeout),this._loadManifest(e,t)},1e3*h)}catch(e){oi(`Could not load manifest: ${e.message}.`),this.trigger(new ve(Xt.LIVE_SEEK_DISABLED,void 0,{hlsElement:t,hlsControl:void 0})),this.isSeekable=!1}}_cleanup(){this._removeSeekableHandlers(this._hlsElement,this._hlsjsRef),this._hlsjsRef&&(this._hlsjsRef.detachMedia(),this._hlsjsRef=void 0),this._hlsElement&&(this._hlsElement.parentNode&&this._hlsElementGenerated&&this._hlsElement.parentNode.removeChild(this._hlsElement),this._hlsElement=void 0),this._playbackControls&&(this._playbackControls.detach(),this._playbackControls=void 0),this._isVOD=!1,this._isSeekable=!1,this._isHLSPlaybackActive=!1,this._isFragLoading=!1,this._hlsRecoverFlop=!1,this._hlsRecoverAttempts=0,this._averageSegmentDuration=6,this._hlsElementGenerated=!1,this._wallOffset=NaN,this._lastDurationUpdate=0,this._manifestLoadTimeout&&(clearTimeout(this._manifestLoadTimeout),this._manifestLoadTimeout=void 0),super._cleanup()}addSource(){si("[addSource]"),this._view.controls=!0,this._view.classList.add("red5pro-media");this._view.hasAttribute("controls")&&this._view.classList.contains("red5pro-media")&&(this._container=this._determineContainer(this._view));const e=this._view.hasAttribute("muted");this._usePlaybackControls?(this._playbackControls=new Jt(this,this._container),this._view.controls=!1,this._playbackControls.setAsVOD(this.isSeekable),this._playbackControls.setMutedState(e)):this._view.controls=!1}enableLiveSeek(e,t,i,n=!1){if(this.getControls()&&this.getControls().setSeekTime(1,1),this._url=e,this._subscriptionId=t,this._hlsElement=i||this._generateHLSLivePlayback(this._container,this._view,t),this._showHLSLivePlayback(this._isHLSPlaybackActive,this._hlsElement,this._view,this._container),n){this._addSeekableHandlers(this._hlsElement,void 0,!1);const t=Zt("source");t.src=e,this._hlsElement.appendChild(t),this._loadManifest(e,this._hlsElement)}else{const t=this._hlsOptions,{liveSeek:{hlsjsRef:i}}=this._liveSeekConfig,n=i?new i(t):ti(t);this._addSeekableHandlers(this._hlsElement,n,!0),n.attachMedia(this._hlsElement,e),n.on(ii().MEDIA_ATTACHED,()=>{n.loadSource(e)}),this._hlsjsRef=n}}switchLiveSeek(e){this._hlsjsRef&&(this._hlsjsRef.destroy(),this._hlsjsRef=void 0),this.enableLiveSeek(e,this._subscriptionId,this._hlsElement),this.seekTo(1);try{this._view.play()}catch(e){ai("[videoelement:action] play (FAULT) - "+e.message)}this._url=e}async play(e=!1){si("[videoelement:action] play");try{return e&&this._hlsElement&&this._hlsElement.paused?(await this._hlsElement.play(),!0):super.play()}catch(e){ai("[videoelement:action] play (CATCH::FAULT) - "+e.message)}return!1}async pause(e=!1,t=!1){si("[videoelement:action] pause");try{return e&&t&&this._hlsElement?(this._hlsElement.pause(),super.pause()):e&&this._hlsElement&&!this._hlsElement.paused?(this._hlsElement.pause(),!0):super.pause()}catch(e){ai("[videoelement:action] pause (CATCH::FAULT) - "+e.message)}return!1}async resume(e=!1){var t,i;si("[videoelement:action] resume");try{const n=this._isHLSPlaybackActive&&this._hlsElement?this._hlsElement.play():null===(t=this._view)||void 0===t?void 0:t.play();if(e&&this._isHLSPlaybackActive)return await(null===(i=this._view)||void 0===i?void 0:i.play()),!0;n&&n.then(()=>si("[videoelement:action] play (START)")).catch(e=>ai("[videoelement:action] play (CATCH::FAULT) "+(e.message?e.message:e)))}catch(e){ai("[videoelement:action] resume (CATCH::FAULT) - "+e.message)}return!1}async stop(){si("[videoelement:action] stop");try{return this._hlsElement&&this._hlsElement.pause(),super.stop()}catch(e){ai("[videoelement:action] stop (CATCH::FAULT) - "+e.message)}return!1}mute(){this._hlsElement&&(this._hlsElement.muted=this._isHLSPlaybackActive),this._view&&(this._view.muted=!0);const e=this.getControls();e&&e.setMutedState(!0)}unmute(){this._hlsElement&&(this._hlsElement.muted=!this._isHLSPlaybackActive,this._view&&(this._view.muted=this._isHLSPlaybackActive)),this._view&&(this._view.muted=!1);const e=this.getControls();e&&e.setMutedState(!1)}setVolume(e){this.unmute(),this._hlsElement&&this._isHLSPlaybackActive?this._hlsElement.volume=e:this._view?this._view.volume=e:oi("[videoelement:action] setVolume (CATCH::FAULT) - "+e)}seekTo(e,t=void 0){if(this.isSeekable)if(this.getControls()&&this.getControls().setSeekTime(e,t),this.trigger(new ve(Xt.LIVE_SEEK_CHANGE,void 0,{seek:e,duration:t})),this._hlsElement&&e<1)try{this._hlsElement.classList.remove("hidden"),this._hlsElement.currentTime=this._hlsElement.duration*e,this._isFragLoading=!0,this._showHLSLivePlayback(!0,this._hlsElement,this._view,this._container),this._view.paused||(si("[hlsvod:action] play (START) - (seekTo)"),this.play(!0))}catch(e){ai("[hlsvod:action] play (CATCH::FAULT) - "+e.message)}else this._hlsElement&&e>=1&&(this._isFragLoading=!1,this._showHLSLivePlayback(!1,this._hlsElement,this._view,this._container));else this._view.currentTime=t?e*t:e}toggleFullScreen(e){var t;this._container&&super.toggleFullScreen(null!==(t=this._container)&&void 0!==t?t:e)}getControls(){return this._playbackControls}get isSeekable(){return this._isSeekable}set isSeekable(e){this._isSeekable=e,this.getControls()&&this.getControls().setAsVOD(e)}get isHLSPlaybackActive(){return this._isHLSPlaybackActive}get url(){return this._url}}const{supportsHLS:li,supportsNonNativeHLS:di}=ie,hi="WHEPLiveSeekClient",ci=e=>k(hi,e);class ui extends wt{constructor(e,t,i){super(e,t,i)}async init(e){const{liveSeek:t}=e;return t||(e.liveSeek=Nt),super.init(e)}_attachSourceHandler(e){var t;if((null===(t=this._playbackView)||void 0===t?void 0:t.view)&&!this._enableLiveSeek(this._playbackView.view))return O(hi,"LiveSeek is not enabled, using default source handler"),void super._attachSourceHandler(e);this._startSeekableIfSeekableEnabled(this._options)}_enableLiveSeek(e){const{liveSeek:t}=this._options;if(t){const{hlsjsRef:i,usePlaybackControlsUI:n,options:s}=t;if(li()||di(i))return this._sourceHandler=new ri(e,this.getType(),this._options,s,n),this._sourceHandler.addSource(),!0;ci("Could not utilize the 'LiveSeek' request. This feature requires either native HLS playback or hls.js as a depenency."),this.trigger(new ve(Xt.LIVE_SEEK_UNSUPPORTED,this,{feature:"Live Seek",message:"Live Seek requires integration with the HLS.JS plugin in order work properly. Most likely you are viewing this on a browser that does not support the use of HLS.JS."}))}return!1}_startSeekableIfSeekableEnabled(e){const{liveSeek:t,subscriptionId:i}=e;if(!t)return;const{hlsjsRef:n,hlsElement:s}=t;if(this._sourceHandler)try{if(!li()&&!di(n))throw new Error;{const t=ne(e);this._sourceHandler.enableLiveSeek(t,i,s,!di(n))}}catch(e){ci("Could not utilize the 'LiveSeek' request. This feature requires either native HLS playback or hls.js as a depenency.")}}_onUnpublish(){super._onUnpublish();const{liveSeek:e}=this._options;e||this.unsubscribe(!0)}_onStreamSwitchComplete(){const e=this._requestedStreamSwitch,{liveSeek:t}=this._options;if(t&&e){const{baseURL:i,fullURL:n}=t,s=e.split("/"),o=s.pop(),a=s.join("/"),r={...this._options,app:a,streamName:o};let l=n;if(n){const e=/.*\/(.*)\.m3u8/.exec(n);if(e&&e.length>1){const t=`${e[1]}.m3u8`;l=n.replace(t,`${o}.m3u8`)}}const d=ne(r,i,l);this._sourceHandler&&this._sourceHandler.switchLiveSeek(d)}super._onStreamSwitchComplete()}}const pi="NEW-15.0.0.11-release.b189";D(N.ERROR);const _i=(e,t=!1)=>{Object.prototype.hasOwnProperty.call(N,e.toUpperCase())&&(D(e,t),console&&console.log(`Red5 Pro SDK Version ${mi()}`))},mi=()=>pi;I("RED5",`Red5 Pro HTML SDK Version: ${pi}`);var gi={version:pi,LOG_LEVELS:N,getLogger:R,getRecordedLogs:H,setLogLevel:_i,getVersion:mi,PlaybackVideoEncoder:t,PlaybackAudioEncoder:e,PlaybackState:i,PlaybackStateReadableMap:s,PublishVideoEncoder:l,PublishAudioEncoder:r,SubscriberEvent:ve,PublisherEvent:ge,MessageTransportStateEvent:Se,PublisherEventTypes:Ee,SubscriberEventTypes:fe,RTCPublisherEventTypes:Ce,RTCSubscriberEventTypes:be,MessageTransportStateEventTypes:we,WHIPClient:ot,WHEPClient:wt,HLSSubscriber:Pt,LiveSeekClient:ui,defaultWhepSubscriberConfig:at,defaultWhipPublisherConfig:pe};export{me as Event,U as EventEmitter,Pt as HLSSubscriber,N as LOG_LEVELS,ui as LiveSeekClient,Se as MessageTransportStateEvent,we as MessageTransportStateEventTypes,e as PlaybackAudioEncoder,pt as PlaybackController,Rt as PlaybackControls,i as PlaybackState,s as PlaybackStateReadableMap,t as PlaybackVideoEncoder,r as PublishAudioEncoder,l as PublishVideoEncoder,ge as PublisherEvent,Ee as PublisherEventTypes,Ce as RTCPublisherEventTypes,be as RTCSubscriberEventTypes,_t as SourceHandler,vt as SourceHandlerImpl,ve as SubscriberEvent,fe as SubscriberEventTypes,wt as WHEPClient,ot as WHIPClient,gi as default,rt as defaultHLSSubscriberConfig,Dt as defaultLiveSeekConfig,ze as defaultStatsConfig,at as defaultWhepSubscriberConfig,pe as defaultWhipPublisherConfig,R as getLogger,H as getRecordedLogs,mi as getVersion,_i as setLogLevel};
+var e,t,i,n;!function(e){e.OPUS="OPUS",e.NONE="NONE"}(e||(e={})),function(e){e.VP8="VP8",e.H264="H264",e.H265="H265",e.NONE="NONE"}(t||(t={})),function(e){e[e.UNAVAILABLE=1e3]="UNAVAILABLE",e[e.AVAILABLE=0]="AVAILABLE",e[e.IDLE=1]="IDLE",e[e.PLAYING=2]="PLAYING",e[e.PAUSED=3]="PAUSED"}(i||(i={})),function(e){e.UNAVAILABLE="Playback.UNAVAILABLE",e.AVAILABLE="Playback.AVAILABLE",e.IDLE="Playback.IDLE",e.PLAYING="Playback.PLAYING",e.PAUSED="Playback.PAUSED"}(n||(n={}));const s={[i.UNAVAILABLE]:n.UNAVAILABLE,[i.AVAILABLE]:n.AVAILABLE,[i.IDLE]:n.IDLE,[i.PLAYING]:n.PLAYING,[i.PAUSED]:n.PAUSED};var o,a,r,l;!function(e){e.RTMP="rtmp",e.RTC="rtc"}(o||(o={})),function(e){e.LIVE="live",e.RECORD="record",e.APPEND="append"}(a||(a={})),function(e){e.OPUS="OPUS"}(r||(r={})),function(e){e.VP8="VP8",e.H264="H264",e.H265="H265"}(l||(l={}));var d={trace:10,debug:20,info:30,warn:40,error:50,fatal:60},h={};function c(e){return"string"==typeof e?d[e.toLowerCase()]:e}function u(e,t){return u=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},u(e,t)}function _(e,t,i){return _=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}()?Reflect.construct:function(e,t,i){var n=[null];n.push.apply(n,t);var s=new(Function.bind.apply(e,n));return i&&u(s,i.prototype),s},_.apply(null,arguments)}function p(e){if(null==e)return e;if(Array.isArray(e))return e.slice();if("object"==typeof e){var t={};return Object.keys(e).forEach((function(i){t[i]=e[i]})),t}return e}function m(e){return void 0===e?"undefined":null===e?"null":Array.isArray(e)?"[ "+e.map((function(e){return m(e)})).join(", ")+" ]":"object"==typeof e?JSON.stringify(e):"function"==typeof e?"[Function: "+e.name+"]":"boolean"==typeof e||"number"==typeof e?e:"'"+e.toString()+"'"}function g(e){if("string"!=typeof e){for(var t=new Array(arguments.length),i=0;i=o)return e;switch(e){case"%s":return String(s[n++]);case"%d":return Number(s[n++]);case"%j":try{return JSON.stringify(s[n++])}catch(e){return"[Circular]"}default:return e}})),r=s[n];ne||(s=function(s){var o;s[0]instanceof Error?(i={err:t.serializers&&t.serializers.err?t.serializers.err(s[0]):b.err(s[0])},o={err:!0},n=1===s.length?[i.err.message]:Array.prototype.slice.call(s,1)):"object"!=typeof s[0]&&null!==s[0]||Array.isArray(s[0])?(i=null,n=Array.prototype.slice.call(s)):(i=s[0],n=1===s.length&&i.err&&i.err instanceof Error?[i.err.message]:Array.prototype.slice.call(s,1));var a=p(t.fields);a.level=e;var r=i?p(i):null;if(r&&(t.serializers&&t._applySerializers(r,o),Object.keys(r).forEach((function(e){a[e]=r[e]}))),a.levelName=h[e],a.msg=n.length?g.apply(t,n):"",a.time||(a.time=new Date),t.src&&!a.src)try{throw new Error("call-stack-error")}catch(e){var l=e.stack?function(e,t){var i=e.split("\n");i[0]&&i[0].indexOf("call-stack-error")>=0&&i.shift();var n=i[t],s=null;if(n){var o=/^\s*(at|.*@)\s*(.+)?$/.exec(n);s=Array.isArray(o)&&o[2]?o[2]:n}return s}(e.stack,2):"";l||function(e){return v[e]}("src")||E("Unable to determine src line info","src"),a.src=l||""}return a.v=1,a}(n),this._emit(s))}}function T(e){var t=e.stack||e.toString();if(e.cause&&"function"==typeof e.cause){var i=e.cause();i&&(t+="\nCaused by: "+T(i))}return t}C.prototype.trace=f(10),C.prototype.debug=f(20),C.prototype.info=f(30),C.prototype.warn=f(40),C.prototype.error=f(50),C.prototype.fatal=f(60);var b={err:function(e){return e&&e.stack?{message:e.message,name:e.name,stack:T(e),code:e.code,signal:e.signal}:e}};const A={10:"TRACE",20:"DEBUG",30:"INFO",40:"WARN",50:"ERROR",60:"FATAL"};class w{write(e){console.log("%s - [%s] %s: %s",e.time.toISOString(),e.name,A[e.level]||"UNKNOWN",e.msg)}}let y,L;const N=e=>(t,i)=>{var n;y&&"function"==typeof y[e]&&y[e]((n=t,e=>`(${n}) ${e}`)(i))},P={TRACE:"trace",INFO:"info",DEBUG:"debug",WARN:"warn",ERROR:"error",FATAL:"fatal"},R=(e,t=!1,i)=>{const n=[{level:e,stream:new w,type:"raw"}];if(i){const t=i.map((t=>({...t,level:e})));n.push(...t)}t&&(L=[],n.push({level:e,stream:{write:t=>{const i=`[${t.time.toISOString()}] ${e.toUpperCase()}: ${t.msg}`;null==L||L.push(i)}},type:"raw"}));y=function(){return _(C,[].slice.call(arguments))}({level:e,name:"red5pro-sdk",streams:n})},D=()=>(y||R(P.INFO),y),I=()=>L||[];N(P.TRACE),N(P.INFO);const O=N(P.DEBUG),H=N(P.WARN),k=N(P.ERROR);N(P.FATAL);const M="RED5PRO";class U{constructor(){this._callbacks={},this._callbacks[M]=[]}_notify(e,t){let i;const n=e.length;for(i=0;i1&&(s=V.exec(e),n[1]===t&&s&&s.length>1)?s[1]:void 0}}function W(e){const t=G(e,"orientation");if(t)return{orientation:parseInt(t)}}function x(e){const t=G(e,"streamingMode");if(t)return{streamingMode:t}}const j=e=>$.get(e),K=e=>{const t=e.textTracks;t&&(e.addTextTrack("metadata"),t.addEventListener("addtrack",(t=>{const i=t.track;i.mode="hidden",i.addEventListener("cuechange",(t=>{let n,s;for(t&&t.currentTarget?n=t.currentTarget.cues:(n=i.cues,n=n&&n.length>0?n:i.activeCues),n=n||[],s=0;s{e(n)})),s&&o&&o.streamingMode&&o.streamingMode.forEach((e=>{e(s)}))}}}))})))},z="BrowserEnvironment",J=e=>O(z,e),Y=e=>H(z,e);let q=[];const X=()=>{const e=screen.orientation?screen.orientation.angle:void 0,t=void 0===e?window.matchMedia("(orientation: portrait)").matches?0:90:e,i=q.length;J(`[window:onorientationchange]: orientation(${t}).`);for(let e=0;e{const e=document.createElement("video");return e.canPlayType("application/vnd.apple.mpegURL").length>0||e.canPlayType("application/x-mpegURL").length>0||e.canPlayType("audio/mpegurl").length>0||e.canPlayType("audio/x-mpegurl").length>0},te="undefined"!=typeof window&&window.adapter;var ie={gUM:async e=>navigator.mediaDevices.getUserMedia(e),createElement:e=>document.createElement(e),resolveElement:e=>document.getElementById(e),getElementId:e=>e.id,setVideoSource:(e,t,i)=>{if(e.srcObject=t,i)try{const t=e.play();t&&t.then((()=>J("[setVideoSource:action]: play (START)"))).catch((t=>{Y(`[setVideoSource:action]: play (CATCH::FAULT) ${t.message}`);try{e.setAttribute("autoplay","false"),e.pause()}catch(e){Y(`[setVideoSource:action]: pause (CATCH::FAULT) ${e.message}`)}}))}catch(e){Y(`[setVideoSource:action]: play (CATCH::FAULT) ${e.message}`)}},hasAttributeDefined:(e,t)=>e.hasAttribute(t),addOrientationChangeHandler:(e,t=!0)=>{"onorientationchange"in window&&(J("[window:orientation:addOrientationChangeHandler]: add"),q.push(e),t&&X()),1===q.length&&(J("[window:orientation:addOrientationChangeHandler]: add"),window.addEventListener("orientationchange",X))},removeOrientationChangeHandler:e=>{q=q.filter((t=>t!==e)),0===q.length&&window.removeEventListener("orientationchange",X)},toggleFullScreen:e=>{window.screenfull&&window.screenfull.enabled?window.screenfull.toggle(e):document.fullscreenEnabled&&(document.fullscreenElement&&document.fullscreenElement===e?document.exitFullscreen():e.requestFullscreen())},onFullScreenStateChange:e=>{var t;Z.push(e),t=window.screenfull,Q||(Q=!0,window.screenfull?window.screenfull.on("change",(()=>{Z.forEach((e=>e(t.isFullscreen)))})):document.fullscreenEnabled&&document.addEventListener("fullscreenchange",(()=>{Z.forEach((e=>e(null!==document.fullscreenElement)))})))},getOrGenerateFingerprint:()=>{const e=window.localStorage;if(e&&e.getItem("red5_fingerprint"))return e.getItem("red5_fingerprint");let t;try{t=window.crypto.randomUUID()}catch(e){t="10000000-1000-4000-8000-100000000000".replace(/[018]/g,(e=>(Number(e)^crypto.getRandomValues(new Uint8Array(1))[0]&15>>Number(e)/4).toString(16)))}return e.setItem("red5_fingerprint",t),t},getBrowserDetails:()=>{const e=void 0!==window.adapter,{navigator:t,adapter:i}=window,{appVersion:n,platform:s,userAgent:o,vendor:a}=t,r={appVersion:n,platform:s,userAgent:o,vendor:a};return e?{...i.browserDetails,...r}:r},supportsHLS:ee,onOrientationMetadata:(e,t)=>{const i=$.get(e);$.has(e)?Object.prototype.hasOwnProperty.call(i,"orientation")||($.get(e).orientation=[]):(K(e),$.set(e,{orientation:[]})),$.get(e).orientation.push(t)},onStreamingModeMetadata:(e,t)=>{const i=$.get(e);$.has(e)?Object.prototype.hasOwnProperty.call(i,"streamingMode")||($.get(e).streamingMode=[]):(K(e),$.set(e,{streamingMode:[]})),$.get(e).streamingMode.push(t)},isTouchEnabled:()=>"ontouchstart"in window,isPossiblySafari:()=>te?"safari"===window.adapter.browserDetails.browser.toLowerCase():ee(),findByQuerySelector:e=>document.querySelector(e),addGlobalEventListener:(e,t,i=document)=>{i.addEventListener(e,t)},removeGlobalEventListener:(e,t,i=document)=>{i.removeEventListener(e,t)},supportsNonNativeHLS:e=>{if(e)try{return e.isSupported()}catch(e){return Y("Could not access Hls.js."),!1}return!!window.Hls&&window.Hls.isSupported()},createHLSClient:(e={})=>new window.Hls(e),getHLSClientEventEnum:()=>window.Hls.Events,globalAssign:(e,t)=>{window[e]=t},globalUnassign:e=>{delete window[e]},getAssignedValue:e=>window[e]};const ne=(e,t,i)=>{const{liveSeek:{baseURL:n,fullURL:s}}=e,{host:o,protocol:a,port:r,app:l,streamName:d}=e;if(i||s)return i||s;const h=o,c="ws"===a?"http":"https",u=5080===r?5080:443,_=l,p=t||n;if(p){const e=p.length-1;return`${"/"===p.charAt(e)?p.substring(0,e):p}/${_}/${d}.m3u8`}return`${c}://${h}:${u}/${_}/${d}.m3u8`},se=e=>{const t=new URL(e),i=t.pathname.split("/").filter((e=>e.length>0)),n="https:"===t.protocol?"https":"http",s=t.hostname;return{protocol:n,port:t.port.length>0?t.port:443,app:i[0],host:s,streamName:i[i.length-1]}},oe=(e,t="whip")=>{var i;const{endpoint:n,proxy:s}=e;if(n)return n;{const{protocol:n,host:o,port:a,app:r,streamName:l}=e,d=n.match(/^http/)?n:"ws"===n?"http":"https";return(null==s?void 0:s.enabled)?`${d}://${o}:${a}/as/${null!==(i=s.version)&&void 0!==i?i:"v1"}/proxy/${t}/${r}/${l}`:`${d}://${o}:${a}/${r}/${t}/endpoint/${l}`}},ae=e=>{const t={audio:!1,video:!1},i={audio:!1,video:!1};return e.getTracks().forEach((e=>{"video"===e.kind?(i.video=e.getSettings(),t.video=e.getConstraints()):"audio"===e.kind&&(i.audio=e.getSettings(),t.audio=e.getConstraints())})),{requested:t,accepted:i}},re=e=>{const t=e.length;return function i(...n){return n.length>=t?e(...n):function(...e){return i(...n,...e)}}},le=re(((e,t)=>{let i=0;const n=t.length,s=[];for(;i{this._responder.onDataChannelError(e,t.error.message)},e.onmessage=e=>{this._onDataChannelMessage(e)},e.onopen=()=>{this._responder.onDataChannelOpen(e)},e.onclose=t=>{this._responder.onDataChannelClose(e),this.trigger(new Ce(we.CLOSE,this._name,{socket:this,event:t}))}}_isErrorMessage(e){return!("error"!==(null==e?void 0:e.type)||!(null==e?void 0:e.message)&&!(null==e?void 0:e.code))}_isStatusMessage(e){return!("status"!==(null==e?void 0:e.type))}_onDataChannelMessage(e){if(this.handleMessageResponse(e))return!0;const t=this.getJsonFromSocketMessage(e);return t?(O(this._name,`[datachannel-response]: ${JSON.stringify(t,null,2)}`),this._handleMessageContent(t)):(H(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0)}_handleMessageContent(e){const{async:t,data:i,method:n,send:s,type:o,id:a}=e;if(this._isErrorMessage(i)){const e=(null==i?void 0:i.message)||(null==i?void 0:i.code);if(e)return this._responder.onDataChannelError(this._dataChannel,e),!0}if(n)return this._responder.onSendReceived(n,i),!0;if(s){const{senderName:t,dcLabel:i}=e,{data:n,method:o}=s,a={...n,senderName:t,dcLabel:i};return this._responder.onSendReceived(o,a),!0}return"metadata"===o&&i?(this._responder.onMetaData(i),!0):this._isStatusMessage(i)&&"NetConnection.Connect.Closed"===(null==i?void 0:i.code)?(this._responder.onConnectionClosed(),!0):!(!t||!a)&&this._handleAsyncResponse(a,e)}_handleAsyncResponse(e,t){const i=this._asyncTickets.find((t=>t.id===e));if(!i)return!1;const{promise:n}=i,{data:s}=t;if("error"===(null==s?void 0:s.type)){const e=s.message||s.code||"Unknown error";n.reject(new Error(e))}else n.resolve(s);return this._asyncTickets=this._asyncTickets.filter((t=>t.id!==e)),!0}async setUpWithPeerConfiguration(e,t){this.tearDown();(null==e?void 0:e.iceServers)&&e.iceServers.length>0||(e.iceServers=Le);try{O(this._name,`[peerconnection:setUpWithPeerConfiguration]: ${JSON.stringify(e,null,2)}`);const i=new RTCPeerConnection(e);return t&&(this._dataChannel=i.createDataChannel(t.name,{ordered:!0}),this._addDataChannelHandlers(this._dataChannel)),this._addConnectionHandlers(i),this._peerConnection=i,i}catch(e){throw H(this._name,`Could not establish a PeerConnection. ${e.message}`),new Error(e.message)}}tearDown(){if(this._dataChannel){O(this._name,"[teardown:datachannel]"),this._removeDataChannelHandlers(this._dataChannel);try{this._dataChannel.close()}catch(e){H(this._name,`[datachannel.close] error: ${e.message}`)}finally{this._dataChannel=void 0}}if(this._peerConnection){O(this._name,"[teardown:peerconnection]"),this._removeConnectionHandlers(this._peerConnection);try{this._peerConnection.close()}catch(e){H(this._name,`[peerconnection.close] error: ${e.message}`)}finally{this._peerConnection=void 0}}}async setLocalDescription(e){var t;return O(this._name,"[setlocaldescription]"),null===(t=this._peerConnection)||void 0===t?void 0:t.setLocalDescription(e)}async setRemoteDescription(e){var t;return O(this._name,"[setremotedescription]"),null===(t=this._peerConnection)||void 0===t?void 0:t.setRemoteDescription(new RTCSessionDescription(e))}async addIceCandidate(e){var t;return O(this._name,"[addcandidate]"),null===(t=this._peerConnection)||void 0===t?void 0:t.addIceCandidate(e)}async waitToGatherIce(e=5e3){const t=this._peerConnection;return O(this._name,"[waittogatherice]"),new Promise((i=>{if("complete"===t.iceGatheringState)O(this._name,"[waittogatherice] ice gathering state complete."),t.addIceCandidate(null).then((()=>{i(t.localDescription)})).catch((e=>{H(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)}));else{O(this._name,"[waittogatherice] waiting...");const n=setTimeout((()=>{clearTimeout(n),t.addIceCandidate(null).then((()=>{i(t.localDescription)})).catch((e=>{H(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)}))}),e);t.onicegatheringstatechange=()=>{clearTimeout(n),O(this._name,"[waittogatherice] ice gathering state complete."),"complete"===t.iceGatheringState&&t.addIceCandidate(null).then((()=>{i(t.localDescription)})).catch((e=>{H(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)}))}}}))}post(e){if(this._dataChannel){const t="string"==typeof e?e:JSON.stringify(e,null,2);O(this._name,`[datachannel.send] message: ${t}`);try{return this._dataChannel.send(t),Promise.resolve(!0)}catch(e){k(this._name,e.message)}}return Promise.resolve(!1)}get connection(){return this._peerConnection}get dataChannel(){return this._dataChannel}}const Pe=[{label:"4K(UHD)",width:3840,height:2160},{label:"1080p(FHD)",width:1920,height:1080},{label:"UXGA",width:1600,height:1200},{label:"720p(HD)",width:1280,height:720},{label:"SVGA",width:800,height:600},{label:"VGA",width:640,height:480},{label:"360p(nHD)",width:640,height:360},{label:"CIF",width:352,height:288},{label:"QVGA",width:320,height:240},{label:"QCIF",width:176,height:144},{label:"QQVGA",width:160,height:120}],Re=e=>"number"==typeof e?e:e.exact||e.ideal||e.max||e.min||e,De=re(((e,t)=>{var i,n;if("boolean"==typeof e.video)return!0;const s=(null===(i=e.video)||void 0===i?void 0:i.width)?Re(e.video.width):0,o=(null===(n=e.video)||void 0===n?void 0:n.height)?Re(e.video.height):0,a=s===t.width&&o===t.height;return a&&O("[gum:isExact]",`Found matching resolution for ${t.width}, ${t.height}.`),a})),Ie=re(((e,t)=>{const i=le(De(t))(e);return O("[gum:hasMatchingFormat]","Filtered list: "+JSON.stringify(i,null,2)),i.length>0})),Oe=re(((e,t)=>{var i,n;if("boolean"==typeof e.video)return!0;const s=((null===(i=e.video)||void 0===i?void 0:i.width)?Re(e.video.width):0)*((null===(n=e.video)||void 0===n?void 0:n.height)?Re(e.video.height):0);return t.width*t.height{const i=Oe(t);return le(i)(e)})),ke=async e=>{O("[gum:determineSupportedResolution]","Determine next neighbor based on constraints: "+JSON.stringify(e,null,2));const t=He(Pe)(e),i={...e};return await(async(e,t)=>{let i={...e};if(0==t.length)i.video;else{const n=t.shift();i={...e,video:{...e.video,width:{exact:n.width},height:{exact:n.height}}}}return{media:await ie.gUM(i),constraints:i}})(i,t)},Me=async e=>{let t;const i=Ie(Pe),n=async t=>{if(t){const e="string"==typeof t?t:[t.name,t.message].join(": ");O("[gum:getUserMedia]",`Failure in getUserMedia: ${e}. Attempting other resolution tests...`)}return await ke(e)};if((e=>e.video&&"object"==typeof e.video&&(e.video.width||e.video.height))(e)){if(!i(e))return await n(void 0);{O("[gum:getUserMedia]","Found constraints in list. Checking quick support for faster setup with: "+JSON.stringify(e,null,2));const i=(e=>{var t,i;const n={...e};return"boolean"==typeof e.video||(n.video={...n.video},(null===(t=e.video)||void 0===t?void 0:t.width)&&(n.video.width={exact:Re(e.video.width)}),(null===(i=e.video)||void 0===i?void 0:i.height)&&(n.video.height={exact:Re(e.video.height)})),n})(e);try{return t=await ie.gUM(i),{media:t,constraints:i}}catch(e){return await n(e)}}}else try{return t=await ie.gUM(e),{media:t,constraints:e}}catch(e){return await n(e)}},Ue=(e,t,i)=>{const n="a=end-of-candidates",s=/^a=candidate:/,o=/^a=ice-ufrag:/,a=/^a=ice-pwd:/,r=/^m=(audio|video|application)\ /,l=e.split("\r\n");let d,h="",c="";const u=[];l.forEach((e=>{!d&&r.exec(e)?d=e:o.exec(e)?h=e:a.exec(e)?c=e:s.exec(e)&&(t&&-1!=e.indexOf(t)?u.push(e):t||u.push(e))})),i&&u[u.length-1]!==n&&u.push(n);return[h,c,d,"a=mid:0"].concat(u).join("\r\n")},Be="RTCPeerConnectionPublisher";class Ve extends Ne{constructor(e){super(e,Be)}_removeConnectionHandlers(e){e.onconnectionstatechange=null,e.oniceconnectionstatechange=null,e.onsignalingstatechange=null,e.onicecandidate=null,e.ontrack=null}_addConnectionHandlers(e){let t;e.onsignalingstatechange=()=>{const t=e.signalingState;O(Be,`[peer.onsignalingstatechange] - State: ${t}`)},e.onconnectionstatechange=()=>{const{connectionState:t}=e;"connected"===t?(O(this._name,"[peerconnection:open]"),this._responder.onPeerConnectionOpen()):"failed"!==t&&"disconnected"!==t||(H(this._name,"[peerconnection:error]"),"failed"===t&&this._responder.onPeerConnectionFail())},e.oniceconnectionstatechange=i=>{const{iceConnectionState:n}=e;O(this._name,`[peer.oniceconnectionstatechange] - State: ${n}`),"failed"===n?(t&&clearTimeout(t),this._responder.onPeerConnectionClose(i)):"disconnected"===n?t=setTimeout((()=>{O(this._name,"[peer.oniceconnectionstatechange] - Reconnect timeout reached. Closing PeerConnection."),clearTimeout(t),this._responder.onPeerConnectionClose(i)}),3e3):t&&(O(this._name,"[peer.oniceconnectionstatechange] - Clearing timeout for reconnect."),clearTimeout(t))},e.onicecandidate=e=>{const{candidate:t}=e;O(this._name,`[peer.onicecandidate] - Peer Candidate: ${null==t?void 0:t.candidate}`),t&&this._responder.onIceCandidate(t)},e.ontrack=e=>{O(this._name,"[peer:ontrack]"),this._responder.onPeerConnectionTrackAdd(e.track)}}_onDataChannelMessage(e){const t=e;if(super._onDataChannelMessage(e))return!0;const i=this.getJsonFromSocketMessage(t);if(null===i)return H(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0;O(this._name,"[datachannel-response]: "+JSON.stringify(i,null,2));const{data:n}=i;return n&&"status"===n.type?"NetStream.Play.UnpublishNotify"===n.code?(this._responder.onUnpublish(),!0):"NetConnection.Publish.InsufficientBW"===n.code?(this._responder.onInsufficientBandwidth(n),!0):"NetConnection.Publish.SufficientBW"===n.code?(this._responder.onSufficientBandwidth(n),!0):"NetConnection.Publish.RecoveringBW"===n.code?(this._responder.onRecoveringBandwidth(n),!0):"Application.Statistics.Endpoint"===n.code?(this._responder.onStatisticsEndpointChange(n.statistics),!0):(O(Be,`[datachannel.message] status :: ${n.code}`),this._responder.onPublisherStatus(n),!0):(this._responder.onDataChannelMessage(this._dataChannel,t),!1)}addTrack(e){this._peerConnection?this._peerConnection.addTrack(e):H(Be,"PeerConnection not initialized. Cannot add track.")}async postUnpublish(e){const t=this.post({unpublish:e});return O(Be,`[peerconnection:unpublish] complete: ${t}`),t}async createOfferWithoutSetLocal(e=null){var t;O(Be,`[createoffer:withoutlocal]:: bandwidth request: ${JSON.stringify(e,null,2)}`);try{const i=await(null===(t=this._peerConnection)||void 0===t?void 0:t.createOffer());if(e){const t=((e,t)=>{const i=t.indexOf("m=audio");let n,s,o,a=t.indexOf("m=video"),r=t.indexOf("m=application");return i>-1&&e.audio&&(n=t.indexOf("\r\n",i),s=t.slice(0,n),o=t.slice(n+2,t.length),a=(t=[s,"b=AS:"+e.audio,o].join("\r\n")).indexOf("m=video"),r=t.indexOf("m=application")),a>-1&&e.video&&(n=t.indexOf("\r\n",a),s=t.slice(0,n),o=t.slice(n+2,t.length),r=(t=[s,"b=AS:"+e.video,o].join("\r\n")).indexOf("m=application")),r>-1&&e.dataChannel&&(n=t.indexOf("\r\n",r),s=t.slice(0,n),o=t.slice(n+2,t.length),t=[s,"b=AS:"+e.dataChannel,o].join("\r\n")),t})(e,i.sdp);i.sdp=t}return this._responder.onSDPSuccess(),i}catch(e){throw O(Be,"[createoffer:error]"),this._responder.onSDPError(e),e}}async updateBandwidthRequest(e=null){var t;O(Be,`[updatebandwidthrequest]:: bandwidth request: ${JSON.stringify(e,null,2)}`);try{const i=null===(t=this._peerConnection)||void 0===t?void 0:t.getSenders();if(e&&(null==i?void 0:i.length)&&i.length>0){const t=(e,t,i)=>new Promise(((n,s)=>{try{O(Be,`[updatebandwidthrequest:${i}]:: bandwidth(${t.encodings[0].maxBitrate})`),e.setParameters(t).then(n).catch(s)}catch(e){s(e)}})),n=[];null==i||i.forEach((async i=>{var s,o;if("video"===(null===(s=i.track)||void 0===s?void 0:s.kind)&&e.video){const e=i.getParameters();e.encodings||(e.encodings=[{}]),e.encodings[0].maxBitrate=75e4,e.encodings[0].maxFramerate=60,e.encodings[0].priority="high",n.push(t(i,e,"video"))}else if("audio"===(null===(o=i.track)||void 0===o?void 0:o.kind)&&e.audio){const e=i.getParameters();e.encodings||(e.encodings=[{}]),e.encodings[0].maxBitrate=128e3,n.push(t(i,e,"audio"))}})),await Promise.all(n).catch((e=>{k(Be,`[updatebandwidthrequest:error]:: ${e.message}`)}))}return!0}catch(e){k(Be,`[updatebandwidthrequest:error]:: ${e.message}`)}return!1}}class $e extends Error{constructor(e){super(e),this.name="InvalidNameError"}}const Fe="WhipWhepSignalingHelper",Ge=new Map;Ge.set(400,"Invalid offer SDP."),Ge.set(401,"Not authorized."),Ge.set(404,"Scope resolver failed for the publish name and / or scope."),Ge.set(405,"Remember to update the URL passed into the WHIP or WHEP client."),Ge.set(406,"Scope connection rejected."),Ge.set(409,"Session already initialized."),Ge.set(412,"Invalid request body."),Ge.set(417,"Session lookup or creation failure.");const We=new Map;We.set(400,"Offer already sent, double POST assumed."),We.set(401,"Not authorized."),We.set(404,"Scope resolver failed for the playback name and / or scope."),We.set(406,"Playback failed due to an exception during creation."),We.set(409,"Stream is not available to playback.");const xe=["transcode"];var je;!function(e){e.ICE_SERVER="ice-server",e.STATISTICS="statistics"}(je||(je={}));const Ke=e=>e&&(e=>{const t=/[?&](.*)=([^]*)/.exec(e);return t&&t.length>0})(e)?"&":"?",ze=e=>e.split(";").map((e=>e.trim())).map((e=>"<"===e.charAt(0)?["url",e.substring(1,e.length-1)]:e.split("="))).reduce(((e,t)=>e.set(t[0].replaceAll('"',""),t[1].replaceAll('"',""))),new Map);class Je{constructor(e,t=!1,i=!0){O(Fe,`[whipwhep] ${e}`),this._url=e,this._origin=void 0,this._forceHost=i,this._resource=void 0,this._enableSignalingChannel=t}async getOptions(e={}){let t=`${this._url}${Ke(this._url)}signal=${this._enableSignalingChannel}`;e&&Object.keys(e).forEach((i=>{t+=`&${i}=${e[i]}`})),O(Fe,`[whipwhep-options] ${t}`);try{const e=await fetch(t,{method:"OPTIONS",mode:"cors"}),{status:i,headers:n}=e;if(200===i||204===i){const e=/^(L|l)ink/,t=/^(S|s)ession-(H|h)ost/,i=[];let s;return n.forEach(((n,o)=>{if(t.exec(o)&&(this._origin=n),e.exec(o))if(n.indexOf(`rel="${je.ICE_SERVER}"`)>-1){const e=ze(n),t=e.get("url"),{protocol:s,host:o}=(e=>{const t=e.split(":");return t.length>1?{protocol:t[0],host:t[1]}:{protocol:void 0,host:e}})(t),a=e.get("username"),r=e.get("credential");s&&o&&a&&r?i.push({username:a,credential:r,urls:t}):t&&i.push({urls:t})}else if(n.indexOf(`rel="${je.STATISTICS}"`)>-1){const e=ze(n).get("url");e&&(s=e)}})),O(Fe,`[whipwhep-links]: ${JSON.stringify(i)}`),O(Fe,`[whipwhep-origin]: ${this._origin}`),{links:i.length>0?i:void 0,origin:this._origin,statisticsEndpoint:s}}throw new Error(`Failed to get options: ${i}`)}catch(e){throw k(Fe,e.message),e}}async postSDPOffer(e,t={},i=!0){let n=`${this._url}${Ke(this._url)}signal=${this._enableSignalingChannel}`;t&&Object.keys(t).forEach((e=>{-1===xe.indexOf(e)&&(n+=`&${e}=${t[e]}`)})),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n+=`&host=${this._origin}`),O(Fe,`[whipwhep:post-offer] ${n}: `+JSON.stringify(e,null,2));try{const t={method:"POST",mode:"cors",headers:{"Content-Type":"application/sdp"}};e&&e.length>0&&(t.body=e);const s=await fetch(n,t),{status:o,headers:a}=s;if(a&&a.forEach(((e,t)=>{O(Fe,`[header] ${t}: ${e}`)})),o>=200&&o<300){const e=await s.text(),t=a.get("Location")||a.get("location");if(t){if(t.match(/^(http|https)/))this._resource=t;else{O(Fe,`[whipwhep-response] Location provided as relative path: ${t}`);const e=new URL(this._url);e.pathname=t.split("?")[0],this._resource=e.toString().replace(/\/endpoint\//,"/resource/")}return O(Fe,`[whipwhep-response] ${this._resource}: ${e}`),{sdp:e,location:this._resource}}return H(Fe,"Location not provided in header response to Offer."),this._resource=new URL(this._url).toString().replace(/\/endpoint\//,"/resource/"),{sdp:e,location:this._resource}}if(i&&Ge.get(o)){if(O(Fe,Ge.get(o)),404===o||409===o)throw new $e(Ge.get(o));throw new Error(Ge.get(o))}if(!i&&We.get(o)){if(O(Fe,We.get(o)),404===o||409===o)throw new $e(We.get(o));throw new Error(We.get(o))}{const e=await s.text();throw Error(e)}}catch(e){throw k(Fe,e.message),e}}async postSDPAnswer(e,t={}){O(Fe,`[whipwhep:post-answer] ${this._resource}: `+JSON.stringify(e,null,2));let i=this._resource,n=Ke(i);t&&Object.keys(t).forEach((e=>{-1===xe.indexOf(e)&&(n=Ke(i),i+=`${n}${e}=${t[e]}`)})),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n=i.indexOf("?")>-1?"&":"?",i+=`${n}host=${this._origin}`);try{const t=await fetch(i,{method:"PATCH",mode:"cors",headers:{"Content-Type":"application/sdp"},body:e}),{status:n}=t;if(n>=200&&n<300)return{success:!0,code:n};if(We.get(n))throw O(Fe,We.get(n)),new Error(We.get(n));{const e=await t.text();throw Error(e)}}catch(e){throw k(Fe,e.message),e}}async trickle(e,t={}){O(Fe,`[whipwhep-trickle] ${this._resource}: `+JSON.stringify(e,null,2));let i=this._resource,n=Ke(i);t&&Object.keys(t).forEach((e=>{-1===xe.indexOf(e)&&(n=Ke(i),i+=`${n}${e}=${t[e]}`)})),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n=Ke(i),i+=`${n}host=${this._origin}`);try{const t=await fetch(i,{method:"PATCH",mode:"cors",headers:{"Content-Type":"application/trickle-ice-sdpfrag"},body:e}),{status:n}=t;if(n>=200&&n<300){const e=await t.text();return O(Fe,`[whipwhep-response] ${this._resource}: ${e}`),{candidate:e}}if(405===n)throw O(Fe,"Remember to update the URL passed into the WHIP or WHEP client"),new Error("Remember to update the URL passed into the WHIP or WHEP client");{const e=await t.text();throw Error(e)}}catch(e){throw k(Fe,e.message),e}}async tearDown(e={},t=!1){if(!this._resource)return;let i=this._resource,n=Ke(i);e&&Object.keys(e).forEach((t=>{-1===xe.indexOf(t)&&(n=Ke(i),i+=`${n}${t}=${e[t]}`)})),this._forceHost&&this._origin&&!(null==e?void 0:e.host)&&(n=Ke(i),i+=`${n}host=${this._origin}`),O(Fe,"[whipwhep-teardown]");try{await fetch(i,{method:"DELETE",mode:"cors"})}catch(e){if(k(Fe,e.message),!t)throw e}this._url=void 0,this._origin=void 0,this._resource=void 0,this._forceHost=!1,this._enableSignalingChannel=!1}async post(){return O(Fe,"[whipwhep:post] transport called."),Promise.resolve(!1)}async postAsync(){return O(Fe,"[whipwhep:postAsync] transport called."),Promise.resolve(null)}getUrl(){return this._url}}const Ye="R5ProPublishView";class qe{constructor(e="red5pro-publisher"){try{this._targetElement=ie.resolveElement(e)}catch(e){throw k(Ye,`Could not instantiate a new instance of PublishView. Reason: ${e.message}`),e}}preview(e){const t=this.isAutoplay;O(Ye,`[preview]: autoplay(${t})`),ie.setVideoSource(this._targetElement,e,t)}unpreview(){ie.setVideoSource(this._targetElement,null,this.isAutoplay)}get isAutoplay(){return ie.hasAttributeDefined(this._targetElement,"autoplay")}get view(){return this._targetElement}}var Xe,Qe;!function(e){e.INBOUND="inbound-rtp",e.OUTBOUND="outbound-rtp",e.CODEC="codec",e.MEDIA_SOURCE="media-source",e.CANDIDATE_PAIR="candidate-pair",e.CERTIFICATE="certificate",e.DATA_CHANNEL="data-channel",e.LOCAL_CANDIDATE="local-candidate",e.REMOTE_CANDIDATE="remote-candidate",e.PEER_CONNECTION="peer-connection",e.REMOTE_INBOUND="remote-inbound-rtp",e.REMOTE_OUTBOUND="remote-outbound-rtp",e.TRANSPORT="transport"}(Xe||(Xe={})),function(e){e.STALE_STATS="STALE_STATS",e.STATE_REGRESSION="STATE_REGRESSION",e.EXCESSIVE_RTT="EXCESSIVE_RTT",e.ICE_TIMEOUT="ICE_TIMEOUT"}(Qe||(Qe={}));class Ze{constructor(e,t,i,n){this._name="RTCStatsMonitor",this._queue=[],this._startTime=0,this._stopped=!1,this._interval=0,this._candidatePairHealth=new Map,this._name=e,this._renegotiationPolicy=n,this._config={..._e,...t},this._client=i,this._identifier={name:this._name,created:(new Date).getTime(),fingerprint:ie.getOrGenerateFingerprint(),device:ie.getBrowserDetails(),client:t}}_emptyStatsReportQueue(){for(;this._queue.length>0;){const e=this._client.getMessageTransport();if(e){const t=this._queue.shift();e.post(t)}else H(this._name,"Failed to post stats data to message transport. Message transport is not available.")}}_getStats(){const{_connection:e}=this;if(e)try{e.getStats(null).then((e=>{e.forEach((e=>{this._handleStatsReport(e)}))})).catch((e=>{k(this._name,`Failed to get stats report. ${e.message||e}`)}))}catch(e){k(this._name,`Failed to get stats report. ${e.message||e}`)}}_handleStatsReport(e){console.log(`[${this._name}]: ${JSON.stringify(e,null,2)}`)}_appendClientDetails(e){this._identifier.client={...this._identifier.client,...e}}async start(e){this._startTime=(new Date).getTime(),this._stopped=!1,this._connection=e,this.postAction("started"),this._getStats(),this._interval=setInterval((()=>{this._stopped||this._getStats()}),this._config.interval)}stop(){this._stopped=!0,clearInterval(this._interval),this.postAction("ended")}async post(e){const t={...this._identifier,type:"stats-report",timestamp:(new Date).getTime(),data:e},{endpoint:i,additionalHeaders:n}=this._config;if(i===pe.DEV_NULL)return;if(this._client&&this._client.onStatsReport&&null===i)return void this._client.onStatsReport(this._connection,t);let s={"Content-Type":"application/json"};if(n&&(s={...s,...n}),i)try{const e=await fetch(i,{method:"POST",headers:s,body:JSON.stringify(t)});e.status>=200&&e.status<300?O(this._name,`Posted stats data to endpoint: ${i}.`):k(this._name,`Failed to post stats data to endpoint: ${i}. ${e.status}`)}catch(e){k(this._name,`Failed to post stats data to endpoint: ${i}. ${e.message||e}`)}else if(this._client&&this._client.getMessageTransport())try{let e=!1;const i=this._client.getMessageTransport();i&&(e=await i.post(t)),e||(this._queue.push(t),this._client.on(we.CHANGE,(()=>{this._client.off(we.CHANGE),this._emptyStatsReportQueue()})),H(this._name,"Failed to post stats data to message transport. Message transport is not available. Pushed to Queue."))}catch(e){k(this._name,`Failed to post stats data to message transport. ${e.message||e}`)}}async postAction(e,t=void 0){return this.post({action:{type:e,data:t,timestamp:(new Date).getTime()}})}async postEvent(e,t){return this.post({event:{type:e,data:t||void 0,timestamp:(new Date).getTime()}})}updateEndpoint(e,t=!0){const{endpoint:i}=this._config;t?this._config.endpoint=e:t||i||(this._config.endpoint=e)}_checkCandidatePairHealth(e){var t;const{id:i,state:n,currentRoundTripTime:s,totalRoundTripTime:o}=e,a=(new Date).getTime();this._candidatePairHealth.has(i)||this._candidatePairHealth.set(i,{id:i,staleSampleCount:0,stateTransitionTime:a,inProgressStartTime:"in-progress"===n?a:void 0});const r=this._candidatePairHealth.get(i);if(void 0!==r.previousRTT&&void 0!==r.previousTotalRTT&&void 0!==s&&void 0!==o&&(s===r.previousRTT&&o===r.previousTotalRTT?(r.staleSampleCount++,r.staleSampleCount>=3&&r.lastIssueReported!==Qe.STALE_STATS&&(this._client.emit(ye.CONNECTION_HEALTH_STALE_STATS,{candidatePairId:i,frozenRTT:s,frozenTotalRTT:o,staleDurationSeconds:r.staleSampleCount,message:"RTT values frozen - connection may be dead"}),r.lastIssueReported=Qe.STALE_STATS)):(r.staleSampleCount=0,r.lastIssueReported===Qe.STALE_STATS&&(r.lastIssueReported=void 0))),"succeeded"===r.previousState&&"succeeded"!==n&&(this._client.emit(ye.CONNECTION_HEALTH_STATE_REGRESSION,{candidatePairId:i,previousState:r.previousState,currentState:n,message:`ICE candidate pair regressed from '${r.previousState}' to '${n}' - connection lost`}),r.lastIssueReported=Qe.STATE_REGRESSION,r.stateTransitionTime=a),void 0!==s&&s>1&&r.lastIssueReported!==Qe.EXCESSIVE_RTT?(this._client.emit(ye.CONNECTION_HEALTH_EXCESSIVE_RTT,{candidatePairId:i,currentRTT:s,message:`Excessive RTT detected: ${(1e3*s).toFixed(0)}ms - possible network issues`}),r.lastIssueReported=Qe.EXCESSIVE_RTT):void 0!==s&&s<=1&&r.lastIssueReported===Qe.EXCESSIVE_RTT&&(r.lastIssueReported=void 0),"in-progress"===n){r.inProgressStartTime||(r.inProgressStartTime=a);const e=a-r.inProgressStartTime;e>((null===(t=this._renegotiationPolicy)||void 0===t?void 0:t.iceTimeoutInterval)||5e3)&&r.lastIssueReported!==Qe.ICE_TIMEOUT&&(this._client.emit(ye.CONNECTION_HEALTH_ICE_TIMEOUT,{candidatePairId:i,durationSeconds:Math.floor(e/1e3),message:`ICE negotiation timeout - candidate pair stuck in 'in-progress' for ${Math.floor(e/1e3)}s`}),r.lastIssueReported=Qe.ICE_TIMEOUT)}else r.inProgressStartTime=void 0,r.lastIssueReported===Qe.ICE_TIMEOUT&&(r.lastIssueReported=void 0);r.previousState=n,r.previousRTT=s,r.previousTotalRTT=o,n!==r.previousState&&(r.stateTransitionTime=a)}dispose(){this.stop(),this._candidatePairHealth.clear(),this._connection=void 0,this._client=void 0}}const et=/(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b) \d+ typ srflx/,tt=e=>{const t=e.match(et);return t&&t.length>1?t[1]:null},it=[fe.PUBLISH_START,fe.PUBLISH_FAIL,fe.PUBLISH_INSUFFICIENT_BANDWIDTH,fe.PUBLISH_SUFFICIENT_BANDWIDTH,fe.PUBLISH_RECOVERING_BANDWIDTH,fe.STATISTICS_ENDPOINT_CHANGE];class nt extends Ze{constructor(e,t){if(super("RTCPublisherStats",e,t),this.estimatedAudioBitrate=0,this.estimatedVideoBitrate=0,this.lastAudioReport=null,this.lastVideoReport=null,this._eventHandler=e=>{const{type:t,data:i}=e;if(it.indexOf(t)>-1){if(t===fe.STATISTICS_ENDPOINT_CHANGE){const{statisticsEndpoint:e}=i;this.updateEndpoint(e,!1)}this.postEvent(t)}},this._candidateCreateHandler=({data:{candidate:e}})=>{const{candidate:t}=e,i=tt(t);i&&(this._identifier.publicIP=i)},this._hostEndpointChangedHandler=({data:{endpoint:e,iceServers:t}})=>{this._appendClientDetails({node:e,iceServers:t})},this._client.on("*",this._eventHandler),this._client.on(Te.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.on(Te.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),this._client.getPeerConnection())this.start(this._client.getPeerConnection());else{const e=({data:t})=>{this._client.off(Te.PEER_CONNECTION_AVAILABLE,e),this.start(t)};this._client.on(Te.PEER_CONNECTION_AVAILABLE,e)}}_handleStatsReport(e){const{type:t}=e,{include:i}=this._config,n=i&&i.length>0;if(n&&i.indexOf(t)>=-1)this.post(e);else if(!n)if(t===Xe.CODEC){const{id:i,clockRate:n,mimeType:s,payloadType:o}=e;this.post({id:i,type:t,clockRate:n,mimeType:s,payloadType:o})}else if(t===Xe.CANDIDATE_PAIR){const{availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o}=e;this._checkCandidatePairHealth(e),this.post({type:t,availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o})}else if(t===Xe.MEDIA_SOURCE){const{kind:i}=e;if("audio"===i)this.post({type:t,kind:i});else if("video"===i){const{framesPerSecond:n,height:s,width:o}=e;this.post({type:t,kind:i,framesPerSecond:n,height:s,width:o})}}else if([Xe.OUTBOUND,"outboundrtp"].indexOf(t)>-1){const{timestamp:i,kind:n,codecId:s,mediaType:o,active:a,bytesSent:r,packetsSent:l,totalPacketsSendDelay:d}=e,h={type:t,kind:n,codecId:s,mediaType:o,active:a,bytesSent:r,packetsSent:l,totalPacketsSendDelay:d};if("audio"===n){if(this.lastAudioReport){const{bytesSent:e,timestamp:t}=this.lastAudioReport,n=8*(r-e)/(i-t);this.estimatedAudioBitrate=n}this.post({...h,estimatedBitrate:Math.floor(this.estimatedAudioBitrate)}),this.lastAudioReport=e}else if("video"===n){const{firCount:t,pliCount:n,frameWidth:s,frameHeight:o,framesEncoded:a,framesPerSecond:l,framesSent:d,keyFramesEncoded:c,qualityLimitationReason:u,qualityLimitationDurations:_}=e;let p={...h,firCount:t,pliCount:n,frameWidth:s,frameHeight:o,framesEncoded:a,framesPerSecond:l,framesSent:d,keyFramesEncoded:c,qualityLimitationReason:"none"!==u?u:void 0,qualityLimitationDurations:"none"!==u?_:void 0};if(this.lastVideoReport){const{bytesSent:e,timestamp:t}=this.lastVideoReport,n=8*(r-e)/(i-t);this.estimatedVideoBitrate=n}this.post({...p,estimatedBitrate:Math.floor(this.estimatedVideoBitrate)}),this.lastVideoReport=e}}}dispose(){this._client.off("*",this._eventHandler),this._client.off(Te.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.off(Te.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),super.dispose()}}const st="WHIPClient",ot=me,at=e=>O(st,e),rt=e=>k(st,e),lt=e=>H(st,e);class dt extends U{constructor(e,t,i){super();const n=e?se(e):ot,s=i||ot,o={...s,...n,endpoint:e,mediaElementId:t?t.id:s.mediaElementId};e&&this.internalInit(o),this._onOrientationChange=this._onOrientationChange.bind(this)}async internalInit(e){await this.init(e),await this.publish()}async generateMediaStream(e){var t,i;const{onGetUserMedia:n}=e;if(n){at("Requesting gUM from user-defined configuration:onGetUserMedia.");const e=await n();return this.trigger(new Ee(Te.CONSTRAINTS_ACCEPTED,this,ae(e))),e}{const{mediaConstraints:n}=e;let s;at(`Requesting gUM using mediaConstraints: ${JSON.stringify(n,null,2)}`);let o=n;const a=await Me(o);return a&&a.media||(s=await ie.gUM(o)),s=null!==(t=null==a?void 0:a.media)&&void 0!==t?t:s,o=null!==(i=null==a?void 0:a.constraints)&&void 0!==i?i:n,at(`Constraints accepted: ${JSON.stringify(o,null,2)}`),this.trigger(new Ee(Te.CONSTRAINTS_ACCEPTED,this,{constraints:o,...ae(s)})),s}}async getAndPreviewStreamIfAvailable(){var e;let t=this._mediaStream;if(!t){try{t=null!=t?t:await this.generateMediaStream(this._options)}catch(t){const i=null!==(e=t.message)&&void 0!==e?e:"Could not generate media stream.";throw this.trigger(new Ee(Te.CONSTRAINTS_REJECTED,this,{constraints:this._options.mediaConstraints})),new Error(i)}if(!t)throw new Error("Could not generate media stream.")}return this.trigger(new Ee(Te.MEDIA_STREAM_AVAILABLE,this,t)),this.preview(t),t}reorderCodecPreferences(e,t,i){e.getTransceivers().forEach((e=>{if(e.sender&&e.sender.track){const{kind:n}=e.sender.track;if(t&&"video"===n&&e.setCodecPreferences)try{const{codecs:i}=RTCRtpSender.getCapabilities("video"),n=i.findIndex((e=>e.mimeType===`video/${t}`));if(n>-1){const t=i.slice(0),s=i[n];t.splice(n,1),t.unshift(s),e.setCodecPreferences(t)}}catch(e){lt(`[videoEncoding] Could not set codec preferences for ${t}. ${e.message||e}`)}else if(i&&"audio"===n&&e.setCodecPreferences)try{const{codecs:t}=RTCRtpSender.getCapabilities("audio"),n=t.findIndex((e=>e.mimeType===`audio/${i}`));if(n>-1){const i=t[n];t.splice(n,1),t.unshift(i),e.setCodecPreferences(t)}}catch(e){lt(`[audioEncoding] Could not set codec preferences for ${i}. ${e.message||e}`)}}}))}async postOffer(e){var t;try{const{sdp:i}=e;let{videoEncoding:n}=this._options;const{mungeOffer:s,streamMode:o,keyFramerate:a,iceTransport:r,connectionParams:d,mediaConstraints:h,forceVP8:c,audioEncoding:u,offerSDPResolution:_}=this._options;c&&!n&&(n=l.VP8);let p=i;s&&(at(`[MUNGE:before] offer: ${p}`),p=s(p),at(`[MUNGE:after] offer: ${p}`)),_&&(at(`[MUNGE] Setting resolution on offer: ${p}`),p=((e,t)=>{if(!t)return e;const{width:i,height:n}=t;if(!i||!n)return e;const s=`a=framesize:${i}-${n}`,o=e.split("\r\n");let a=o.length;const r=/^m=video/;for(;--a>-1;)if(r.exec(o[a])){for(;++a-1){o.splice(a+1,0,s);break}break}return o.join("\r\n")})(p,((e,t)=>{let i;if(e)try{const t=e.getVideoTracks()&&e.getVideoTracks()[0];if(t){const e=t.getSettings();i={width:e.width,height:e.height}}}catch(e){H("[determineMediaResolution]",`Could not determine resolution from MediaStream. ${e.message||e}`)}if(!i)try{const e=t.video,{width:n,height:s}=e;if(n&&s)if("number"==typeof n&&"number"==typeof s)i={width:n,height:s};else{i={width:n.exact||n.min||n.max||n.ideal||640,height:s.exact||s.min||s.max||s.ideal||480}}}catch(e){H("[determineMediaResolution]",`Could not determine resolution from MediaConstraints. ${e.message||e}`)}return i&&O("[determineMediaResolution]",`constraints: ${JSON.stringify(i,null,2)}`),i})(this._mediaStream,h)),at(`[MUNGE:after] offer: ${p}`));const m={...d,mode:o,transport:r,keyFramerate:a};return n&&(m.videoEncoding=n),u&&(m.audioEncoding=u),await(null===(t=this._whipWhepService)||void 0===t?void 0:t.postSDPOffer(p,m))}catch(e){throw rt(e.message||e),e instanceof $e?this.trigger(new Ee(fe.PUBLISH_INVALID_NAME,this)):(this.trigger(new Ee(fe.CONNECT_FAILURE,this,e)),this.unpublish()),e}}async postCandidateFragments(e){var t;const{connectionParams:i}=this._options,n=Ue(e,void 0,!0);return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.trickle(n,i))}async init(e){var t;this._options={...ot,...e};const i=oe(this._options),{includeDataChannel:n,disableProxy:s}=this._options;return this._whipWhepService=new Je(i,n,s),this._messageTransport=this._whipWhepService,(null===(t=this._options)||void 0===t?void 0:t.stats)&&this.monitorStats(this._options.stats),this._mediaStream=await this.getAndPreviewStreamIfAvailable(),this}async initWithStream(e,t){return this._mediaStream=t,this.init(e)}async publish(e){var t,i,n,s,o;e&&(this._options.streamName=e);const{forceVP8:a,audioEncoding:r,rtcConfiguration:d,dataChannelConfiguration:h,includeDataChannel:c,signalingSocketOnly:u,enableChannelSignaling:_,connectionParams:p,bandwidth:m,mungeAnswer:g}=this._options;let{videoEncoding:v}=this._options;a&&(v=l.VP8,this._options.videoEncoding=v),this._mediaStream||(this._mediaStream=await this.getAndPreviewStreamIfAvailable());try{const e=null!=p?p:{};if(p){const{transcode:t}=p;t&&(e.transcode=t)}const o=await(null===(t=this._whipWhepService)||void 0===t?void 0:t.getOptions(e)),a=!!(null===(i=this._options)||void 0===i?void 0:i.rtcConfiguration)&&Array.isArray(this._options.rtcConfiguration.iceServers)&&this._options.rtcConfiguration.iceServers.length>0;(null==o?void 0:o.links)&&!a&&(this._options.rtcConfiguration={...d,iceServers:o.links}),(null==o?void 0:o.origin)&&this.trigger(new Ee(Te.HOST_ENDPOINT_CHANGED,this,{endpoint:o.origin})),(null==o?void 0:o.statisticsEndpoint)&&this._onStatisticsEndpointChange(o.statisticsEndpoint);const l=c||_||u?h:void 0;this._peerConnectionHelper=new Ve({onDataChannelError:this._onDataChannelError.bind(this),onSendReceived:this._onSendReceived.bind(this),onMetaData:this._onMetaData.bind(this),onConnectionClosed:this._onConnectionClosed.bind(this),onDataChannelOpen:this._onDataChannelOpen.bind(this),onDataChannelClose:this._onDataChannelClose.bind(this),onDataChannelMessage:this._onDataChannelMessage.bind(this),onPeerConnectionOpen:this._onPeerConnectionOpen.bind(this),onPeerConnectionFail:this._onPeerConnectionFail.bind(this),onPeerConnectionClose:this._onPeerConnectionClose.bind(this),onIceCandidate:this._onIceCandidate.bind(this),onSDPSuccess:this._onSDPSuccess.bind(this),onSDPError:this._onSDPError.bind(this),onStatisticsEndpointChange:this._onStatisticsEndpointChange.bind(this),onPublisherStatus:this._onPublisherStatus.bind(this),onPeerConnectionTrackAdd:this._onPeerConnectionTrackAdd.bind(this),onInsufficientBandwidth:this._onInsufficientBandwidth.bind(this),onSufficientBandwidth:this._onSufficientBandwidth.bind(this),onRecoveringBandwidth:this._onRecoveringBandwidth.bind(this),onUnpublish:this._onUnpublish.bind(this)}),await this._peerConnectionHelper.setUpWithPeerConfiguration(this._options.rtcConfiguration,l),this.trigger(new Ee(Te.PEER_CONNECTION_AVAILABLE,this,this.getPeerConnection())),this._mediaStream.getTracks().forEach((e=>{var t;null===(t=this.getPeerConnection())||void 0===t||t.addTransceiver(e,{direction:"sendonly"})})),this.reorderCodecPreferences(this.getPeerConnection(),v,r);const E=await(null===(n=this._peerConnectionHelper)||void 0===n?void 0:n.createOfferWithoutSetLocal(m));await this._peerConnectionHelper.setLocalDescription(E),this.trigger(new Ee(Te.OFFER_START,this,E));const{sdp:S}=await this.postOffer(E);let C=S;g&&(at(`[MUNGE:before] answer: ${C}`),C=g(C),at(`[MUNGE:after] answer: ${C}`)),await this._peerConnectionHelper.setRemoteDescription({type:"answer",sdp:C}),this.trigger(new Ee(Te.OFFER_END,this,C));const f=await this._peerConnectionHelper.waitToGatherIce(),{sdp:T}=f;return await this.postCandidateFragments(T),this.trigger(new Ee(Te.ICE_TRICKLE_COMPLETE,this)),ie.addOrientationChangeHandler(this._onOrientationChange),(null===(s=this._options)||void 0===s?void 0:s.includeDataChannel)||this.trigger(new Ee(fe.PUBLISH_START,this)),this}catch(e){throw rt(null!==(o=e.message)&&void 0!==o?o:"Could not publish."),this.trigger(new Ee(fe.CONNECT_FAILURE,this,e)),this.unpublish(!0),e}}async unpublish(e=!1){var t;at("[unpublish]"),this._peerConnectionHelper&&await this._peerConnectionHelper.tearDown(),this._whipWhepService&&await this._whipWhepService.tearDown(null,e),(null===(t=this._options)||void 0===t?void 0:t.clearMediaOnUnpublish)&&this.unpreview(),this._mediaStream=void 0,this._peerConnectionHelper=void 0,this._whipWhepService=void 0,this._messageTransport=void 0,this._publishView=void 0,this.trigger(new Ee(fe.UNPUBLISH_SUCCESS,this)),ie.removeOrientationChangeHandler(this._onOrientationChange)}preview(e){at("[preview]");const{mediaElementId:t}=this._options;t&&(this._publishView=new qe(t),this._publishView.preview(e))}unpreview(){at("[unpreview]"),this._mediaStream&&this._mediaStream.getTracks().forEach((e=>{e.stop()})),this._publishView&&this._publishView.unpreview(),this._publishView=void 0}monitorStats(e){at("[monitorStats]");const{host:t,endpoint:i,app:n,streamName:s,connectionParams:o}=this._options,a=null!=e?e:_e;return this._statisticsConfiguration={...a,host:t,hostEndpoint:i,app:n,streamName:s,connectionParams:o},this._statsMonitor?lt("Cannot monitor stats without a Peer Connection. Please call `init` before calling `monitorStats`."):this._statsMonitor=new nt(this._statisticsConfiguration,{onStatsReport:this._onStatsReport.bind(this),getPeerConnection:this.getPeerConnection.bind(this),getMessageTransport:this.getMessageTransport.bind(this),on:this.on.bind(this),off:this.off.bind(this),trigger:this.trigger.bind(this),emit:this.emit.bind(this)}),this}unmonitorStats(){return this._statsMonitor&&this._statsMonitor.dispose(),this._statsMonitor=void 0,this._statisticsConfiguration=void 0,this}muteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0}})}unmuteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1}})}muteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!0}})}unmuteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!1}})}send(e,t){var i;return null===(i=this.getMessageTransport())||void 0===i?void 0:i.post({send:{method:e,data:"string"==typeof t?JSON.parse(t):t}})}async callServer(e,t){var i;try{if(!this.getMessageTransport())throw new Error("Message transport not available");return null===(i=this.getMessageTransport())||void 0===i?void 0:i.postAsync({callAdapter:{method:e,arguments:t}})}catch(e){rt(e.message||e)}}sendLog(e,t){var i;try{const n=Object.keys(P).find((t=>t.toLowerCase()===e.toLowerCase()))?e:P.DEBUG,s="string"==typeof t?t:JSON.stringify(t);null===(i=this.getMessageTransport())||void 0===i||i.post({log:n.toUpperCase(),message:s})}catch(e){const t=e.message||e;rt("Could not send log to server. Message parameter expected to be String or JSON-serializable object."),rt(t)}}get options(){return this._options}getOptions(){return this._options}getPeerConnection(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.connection}getDataChannel(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.dataChannel}getMediaStream(){return this._mediaStream}getMessageTransport(){return this._messageTransport}_onDataChannelError(e,t){rt(`Data channel error: ${t}`),this.trigger(new Ee(Te.DATA_CHANNEL_ERROR,this,{dataChannel:e,error:t}))}_onSendReceived(e,t){at(`Send received: ${e} ${JSON.stringify(t)}`),"onMetaData"===e?this._onMetaData(t):this.trigger(new Ee(fe.PUBLISH_SEND_INVOKE,this,{methodName:e,data:t}))}_onMetaData(e){at(`Metadata received: ${JSON.stringify(e)}`),this.trigger(new Ee(fe.PUBLISH_METADATA,this,e))}_onConnectionClosed(){at("Connection closed"),this.unpublish(),this.trigger(new Ee(fe.CONNECTION_CLOSED,this))}_onDataChannelOpen(e){at(`Data channel opened: ${e.label}`),this.trigger(new Ee(Te.DATA_CHANNEL_OPEN,this,{dataChannel:e})),this.trigger(new Ee(Te.DATA_CHANNEL_AVAILABLE,this,{name:e.label,dataChannel:e})),this._messageTransport=this._peerConnectionHelper,this.trigger(new Ce(we.CHANGE,this,{controller:this,transport:this._messageTransport})),this.trigger(new Ee(fe.PUBLISH_START,this))}_onDataChannelClose(e){at(`Data channel closed: ${e.label}`),this.trigger(new Ee(Te.DATA_CHANNEL_CLOSE,this,{dataChannel:e}))}_onDataChannelMessage(e,t){at(`Data channel message: ${t.data}`),this.trigger(new Ee(Te.DATA_CHANNEL_MESSAGE,this,{dataChannel:e,message:t}))}_onPeerConnectionTrackAdd(e){at(`Peer connection track added: ${e.id}`),this.trigger(new Ee(Te.TRACK_ADDED,this,{track:e}))}_onPeerConnectionOpen(){at("Peer connection opened"),this.trigger(new Ee(Te.PEER_CONNECTION_OPEN,this,this.getPeerConnection()))}_onPeerConnectionFail(){rt("Peer connection failed"),this.trigger(new Ee(fe.PUBLISH_FAIL,this))}_onPeerConnectionClose(e){at(`Peer connection closed: ${e.type}`),this._peerConnectionHelper&&this._peerConnectionHelper.tearDown(),this.trigger(new Ee(fe.CONNECTION_CLOSED,this,e))}_onIceCandidate(e){at(`ICE candidate: ${JSON.stringify(e,null,2)}`),this.trigger(new Ee(Te.CANDIDATE_CREATE,this,{candidate:e}))}_onUnpublish(){at("Unpublish received")}_onPublisherStatus(e){at("[publisherstatus] - "+JSON.stringify(e,null,2)),e.code&&"NetStream.Publish.IsAvailable"===e.code?this.trigger(new Ee(fe.PUBLISH_AVAILABLE,this,e)):this.trigger(new Ee(fe.PUBLISH_STATUS,this,e))}_onInsufficientBandwidth(e){this.trigger(new Ee(fe.PUBLISH_INSUFFICIENT_BANDWIDTH,this,e))}_onSufficientBandwidth(e){this.trigger(new Ee(fe.PUBLISH_SUFFICIENT_BANDWIDTH,this,e))}_onRecoveringBandwidth(e){this.trigger(new Ee(fe.PUBLISH_RECOVERING_BANDWIDTH,this,e))}_onSDPSuccess(e=void 0){const t=e?": "+JSON.stringify(e,null,2):"";at(`[onsdpsuccess]:: ${t}`)}_onSDPError(e=void 0){this.trigger(new Ee(fe.PUBLISH_FAIL,this));const t=e?": "+JSON.stringify(e,null,2):"";rt(`[onsdperror]:: ${t}`)}_onOrientationChange(e){const t=this.getMessageTransport();t&&t.post({send:{method:"onMetaData",data:{deviceOrientation:e}}})}_onStatisticsEndpointChange(e){at(`Statistics endpoint changed: ${e}`),this._statsMonitor&&this._statsMonitor.updateEndpoint(e),this.trigger(new Ee(fe.STATISTICS_ENDPOINT_CHANGE,this,{statisticsEndpoint:e}))}_onStatsReport(e,t){this.trigger(new Ee(Te.STATS_REPORT,this,{connection:e,report:t}))}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}trigger(e){super.trigger(e)}emit(e,t){this.trigger(new Ee(e,this,t))}getType(){return"RTC"}}const ht={...{protocol:"https",port:443,app:"live",autoLayoutOrientation:!0,mediaElementId:"red5pro-subscriber",rtcConfiguration:{iceCandidatePoolSize:2,bundlePolicy:"max-bundle"},iceTransport:de.UDP,muteOnAutoplayRestriction:!0,maintainConnectionOnSubscribeErrors:!1,dataChannelConfiguration:{name:"red5pro"},signalingSocketOnly:!1,includeDataChannel:!0,maintainStreamVariant:!1,buffer:0,stats:void 0,renegotiationPolicy:void 0},signalingSocketOnly:!1,enableChannelSignaling:!1,includeDataChannel:!0,disableProxy:!0,trickleIce:!0,postEmptyOffer:!1,mungeOffer:void 0,mungeAnswer:void 0},ct={protocol:"https",port:443,app:"live",mediaElementId:"red5pro-subscriber",muteOnAutoplayRestriction:!0},ut={endpoint:pe.DEV_NULL,interval:3e3},_t="R5ProPlaybackView";class pt{constructor(e="red5pro-subscriber"){try{this._targetElement=ie.resolveElement(e)}catch(e){throw k(_t,`Could not instantiate a new instance of Red5ProSubscriber. Reason: ${e.message||e}`),e}}attachStream(e){const t=this.isAutoplay;O(_t,"[attachstream]"),ie.setVideoSource(this._targetElement,e,t)}detachStream(){O(_t,"[detachstream]"),ie.setVideoSource(this._targetElement,null,this.isAutoplay)}get isAutoplay(){return ie.hasAttributeDefined(this._targetElement,"autoplay")}get view(){return this._targetElement}}const mt="RTCPeerConnectionSubscriber";class gt extends Ne{constructor(e){super(e,mt)}_removeConnectionHandlers(e){e.onconnectionstatechange=null,e.oniceconnectionstatechange=null,e.onicegatheringstatechange=null,e.onsignalingstatechange=null,e.onicecandidate=null,e.ontrack=null,e.onnegotiationneeded=null}_addConnectionHandlers(e){let t;e.onsignalingstatechange=()=>{const t=e.signalingState;O(mt,`[peer.onsignalingstatechange] - State: ${t}`)},e.onconnectionstatechange=()=>{const{connectionState:t}=e;"connected"===t?(O(this._name,"[peerconnection:open]"),this._responder.onPeerConnectionOpen()):"failed"===t||"disconnected"===t?(H(this._name,`[peerconnection:error]:: ${t}`),"failed"===t&&this._responder.onPeerConnectionFail()):O(this._name,`[peerconnection:state]:: ${t}`)},e.oniceconnectionstatechange=i=>{const{iceConnectionState:n}=e;O(this._name,`[peer.oniceconnectionstatechange] - State: ${n}`),"failed"===n?(t&&clearTimeout(t),this._responder.onPeerConnectionFail(),this._responder.onPeerConnectionClose(i)):"disconnected"===n?t=setTimeout((()=>{O(this._name,"[peer.oniceconnectionstatechange] - Reconnect timeout reached."),clearTimeout(t),this._responder.onPeerConnectionClose(i)}),3e3):t&&(O(this._name,"[peer.oniceconnectionstatechange] - Clearing timeout for reconnect."),clearTimeout(t))},e.onicecandidate=e=>{const{candidate:t}=e;O(this._name,`[peer.onicecandidate] - Peer Candidate: ${null==t?void 0:t.candidate}`),t&&this._responder.onIceCandidate(t)},e.onnegotiationneeded=()=>{O(this._name,"[peer.onnegotiationneeded]")},e.onicegatheringstatechange=()=>{const{iceGatheringState:t}=e;O(this._name,`[peer.onicegatheringstatechange] - State: ${t}`)}}_onDataChannelMessage(e){const t=e;if(super._onDataChannelMessage(e))return!0;const i=this.getJsonFromSocketMessage(t);if(null===i)return H(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0;O(this._name,"[datachannel-response]: "+JSON.stringify(i,null,2));const{data:n}=i;if(n&&"status"===n.type)return"NetStream.Play.UnpublishNotify"===n.code?(this._responder.onUnpublish(),this._responder.onConnectionClosed(),!0):"Application.Statistics.Endpoint"===n.code?(this._responder.onStatisticsEndpointChange(n.statistics),!0):(O(mt,`[datachannel.message] status :: ${n.code}`),this._responder.onSubscriberStatus(n),!0);if(n&&n.status&&"NetStream.Play.UnpublishNotify"===n.status)return this._responder.onUnpublish(),this._responder.onConnectionClosed(),!0;if(n&&"result"===n.type){const{message:e}=n;if("Stream switch: Success"===e)try{return this._responder.onStreamSwitchComplete(),!0}catch(e){}}return this._responder.onDataChannelMessage(this._dataChannel,t),!1}}var vt;!function(e){e.EMPTY="Empty",e.VIDEO="Video",e.AUDIO="Audio",e.FULL="Video/Audio"}(vt||(vt={}));class Et extends U{trigger(e){super.trigger(e)}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}}class St extends Et{}const Ct=[be.SUBSCRIBE_START,be.SUBSCRIBE_STOP,be.SUBSCRIBE_FAIL,be.SUBSCRIBE_PUBLISHER_CONGESTION,be.SUBSCRIBE_PUBLISHER_RECOVERY,be.PLAY_UNPUBLISH,be.STREAMING_MODE_CHANGE,be.PLAYBACK_STATE_CHANGE,be.STATISTICS_ENDPOINT_CHANGE];class ft extends Ze{constructor(e,t,n){if(super("RTCSubscriberStats",e,t,n),this.estimatedAudioBitrate=0,this.estimatedVideoBitrate=0,this.lastAudioReport=null,this.lastVideoReport=null,this._eventHandler=e=>{const{type:t,data:n}=e;if(Ct.indexOf(t)>-1)if(t===be.STREAMING_MODE_CHANGE){const{streamingMode:e,previousStreamingMode:i}=n;this.postEvent(t,{data:{streamingMode:e,previousStreamingMode:i}})}else if(t===be.PLAYBACK_STATE_CHANGE){const{code:e}=n;let t;e===i.AVAILABLE&&(t={timeToFirstFrameMS:(new Date).getTime()-this._startTime}),this.postEvent(s[e],t)}else{if(t===be.STATISTICS_ENDPOINT_CHANGE){const{statisticsEndpoint:e}=n;this.updateEndpoint(e,!1)}this.postEvent(t)}},this._candidateCreateHandler=({data:{candidate:e}})=>{const{candidate:t}=e,i=tt(t);i&&(this._identifier.publicIP=i)},this._hostEndpointChangedHandler=({data:{endpoint:e,iceServers:t}})=>{this._appendClientDetails({node:e,iceServers:t})},this._client.on("*",this._eventHandler),this._client.on(Ae.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.on(Ae.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),this._client.getPeerConnection())this.start(this._client.getPeerConnection());else{const e=({data:t})=>{this._client.off(Ae.PEER_CONNECTION_AVAILABLE,e),this.start(t)};this._client.on(Ae.PEER_CONNECTION_AVAILABLE,e)}}_handleStatsReport(e){const{type:t}=e,{include:i}=this._config,n=i&&i.length>0;if(n&&i.indexOf(t)>=-1)this.post(e);else if(!n)if(t===Xe.CODEC){const{id:i,clockRate:n,mimeType:s,payloadType:o}=e;this.post({id:i,type:t,clockRate:n,mimeType:s,payloadType:o})}else if(t===Xe.CANDIDATE_PAIR){const{availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o}=e;this._checkCandidatePairHealth(e),this.post({type:t,availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o})}else if([Xe.INBOUND,"inboundrtp"].indexOf(t)>-1){const{timestamp:i,kind:n,codecId:s,jitter:o,packetsLost:a,packetsReceived:r,bytesReceived:l}=e,d={type:t,kind:n,codecId:s,jitter:o,packetsLost:a,packetsReceived:r,bytesReceived:l};if("audio"===n){const{packetsDiscarded:t}=e;if(this.lastAudioReport){const{bytesReceived:e,timestamp:t}=this.lastAudioReport,n=8*(l-e)/(i-t);this.estimatedAudioBitrate=n}this.post({...d,packetsDiscarded:t,estimatedBitrate:Math.floor(this.estimatedAudioBitrate)}),this.lastAudioReport=e}else if("video"===n){const{firCount:t,frameWidth:n,frameHeight:s,framesDecoded:o,framesDropped:a,framesPerSecond:r,framesReceived:h,freezeCount:c,keyFramesDecoded:u,nackCount:_,pauseCount:p,pliCount:m,totalFreezesDuration:g,totalPausesDuration:v}=e,E={...d,firCount:t,frameWidth:n,frameHeight:s,framesDecoded:o,framesDropped:a,framesPerSecond:r,framesReceived:h,freezeCount:c,keyFramesDecoded:u,nackCount:_,pauseCount:p,pliCount:m,totalFreezesDuration:g,totalPausesDuration:v};if(this.lastVideoReport){const{bytesReceived:e,timestamp:t}=this.lastVideoReport,n=8*(l-e)/(i-t);this.estimatedVideoBitrate=n}this.post({...E,estimatedBitrate:Math.floor(this.estimatedVideoBitrate)}),this.lastVideoReport=e}}}dispose(){this._client.off("*",this._eventHandler),this._client.off(Ae.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.off(Ae.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),super.dispose()}}class Tt extends St{constructor(e,t){super(),this._isVOD=!1,this._name=`SourceHandler-${t}`,this._view=e,this._playbackNotificationCenter=this._view,this.onCanPlay=this._onCanPlay.bind(this),this.onDurationChange=this._onDurationChange.bind(this),this.onEnded=this._onEnded.bind(this),this.onTimeUpdate=this._onTimeUpdate.bind(this),this.onPlay=this._onPlay.bind(this),this.onPause=this._onPause.bind(this),this.onVolumeChange=this._onVolumeChange.bind(this),this.onLoadedData=this._onLoadedData.bind(this),this.onLoadedMetadata=this._onLoadedMetadata.bind(this),this.onResize=this._onResize.bind(this),this.onLoadStart=this._onLoadStart.bind(this),this.onSuspend=this._onSuspend.bind(this),this.onStalled=this._onStalled.bind(this),this.onWaiting=this._onWaiting.bind(this),this.onError=this._onError.bind(this),this.onEncrypted=this._onEncrypted.bind(this),this._addPlaybackNotificationCenterHandlers(this._playbackNotificationCenter),ie.onFullScreenStateChange(this._handleFullScreenChange.bind(this))}_addPlaybackNotificationCenterHandlers(e){e.addEventListener("canplay",this.onCanPlay),e.addEventListener("durationchange",this.onDurationChange),e.addEventListener("ended",this.onEnded),e.addEventListener("timeupdate",this.onTimeUpdate),e.addEventListener("play",this.onPlay),e.addEventListener("pause",this.onPause),e.addEventListener("volumechange",this.onVolumeChange),e.addEventListener("loadeddata",this.onLoadedData),e.addEventListener("loadedmetadata",this.onLoadedMetadata),e.addEventListener("resize",this.onResize),e.addEventListener("loadstart",this.onLoadStart),e.addEventListener("suspend",this.onSuspend),e.addEventListener("stalled",this.onStalled),e.addEventListener("waiting",this.onWaiting),e.addEventListener("error",this.onError),e.addEventListener("encrypted",this.onEncrypted)}_removePlaybackNotificationCenterHandlers(e){e.removeEventListener("canplay",this.onCanPlay),e.removeEventListener("durationchange",this.onDurationChange),e.removeEventListener("ended",this.onEnded),e.removeEventListener("timeupdate",this.onTimeUpdate),e.removeEventListener("play",this.onPlay),e.removeEventListener("pause",this.onPause),e.removeEventListener("volumechange",this.onVolumeChange),e.removeEventListener("loadeddata",this.onLoadedData),e.removeEventListener("loadedmetadata",this.onLoadedMetadata),e.removeEventListener("resize",this.onResize),e.removeEventListener("loadstart",this.onLoadStart),e.removeEventListener("suspend",this.onSuspend),e.removeEventListener("stalled",this.onStalled),e.removeEventListener("waiting",this.onWaiting),e.removeEventListener("error",this.onError)}_handleFullScreenChange(e){var t,i;e?null===(t=this._view)||void 0===t||t.classList.add("red5pro-media-container-full-screen"):null===(i=this._view)||void 0===i||i.classList.remove("red5pro-media-container-full-screen"),this.trigger(new Se(be.FULL_SCREEN_STATE_CHANGE,void 0,e))}_cleanup(){this._playbackNotificationCenter&&this._removePlaybackNotificationCenterHandlers(this._playbackNotificationCenter),this._playbackNotificationCenter=void 0,this._view=void 0}_onCanPlay(e){var t;O(this._name,"[videoelement:event] canplay");const s=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,o=this.getControls();o&&o.enable(!0),this.trigger(new Se(be.PLAYBACK_STATE_CHANGE,void 0,{code:i.AVAILABLE,state:n.AVAILABLE})),this.trigger(new Se(be.VOLUME_CHANGE,void 0,{volume:s.volume}))}_onDurationChange(e){var t;O(this._name,"[videoelement:event] durationchange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();n&&n.setPlaybackDuration(i.duration),!isNaN(i.duration)&&Number.isFinite(i.duration)&&(this._isVOD=!0)}_onEnded(){O(this._name,"[videoelement:event] ended");const e=this.getControls();e&&e.setState(i.IDLE),this.trigger(new Se(be.PLAYBACK_STATE_CHANGE,void 0,{code:i.IDLE,state:n.IDLE}))}_onTimeUpdate(e){var t;const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();n&&n.setSeekTime(i.currentTime,this.isVOD()?i.duration:void 0),this.trigger(new Se(be.PLAYBACK_TIME_UPDATE,void 0,{time:i.currentTime,duration:i.duration}))}_onPlay(){O(this._name,"[videoelement:event] play");const e=this.getControls();e&&e.setState(i.PLAYING),this.trigger(new Se(be.PLAYBACK_STATE_CHANGE,void 0,{code:i.PLAYING,state:n.PLAYING}))}_onPause(){O(this._name,"[videoelement:event] pause");const e=this.getControls();e&&e.setState(i.PAUSED),this.trigger(new Se(be.PLAYBACK_STATE_CHANGE,void 0,{code:i.PAUSED,state:n.PAUSED}))}_onVolumeChange(e){var t;O(this._name,"[videoelement:event] volumechange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();n&&n.getVolume()!==i.volume&&n.setVolume(i.volume),this.trigger(new Se(be.VOLUME_CHANGE,void 0,{volume:i.volume}))}_onLoadedData(e){var t,i,n;O(this._name,"[videoelement:event] loadeddata");const s=null!==(t=this._view)&&void 0!==t?t:e.target;this.trigger(new Se(be.VIDEO_DIMENSIONS_CHANGE,void 0,{width:null!==(i=s.videoWidth)&&void 0!==i?i:0,height:null!==(n=s.videoHeight)&&void 0!==n?n:0}))}_onLoadedMetadata(e){var t,i;O(this._name,"[videoelement:event] loadedmetadata");const n=null!==(t=this._view)&&void 0!==t?t:e.target;this.trigger(new Se(be.LOADED_METADATA,void 0,{duration:null!==(i=n.duration)&&void 0!==i?i:0}))}_onResize(e){var t,i,n;O(this._name,"[videoelement:event] resize");const s=null!==(t=this._view)&&void 0!==t?t:e.target;this.trigger(new Se(be.VIDEO_DIMENSIONS_CHANGE,void 0,{width:null!==(i=s.videoWidth)&&void 0!==i?i:0,height:null!==(n=s.videoHeight)&&void 0!==n?n:0}))}_onLoadStart(){O(this._name,"[videoelement:event] loadstart")}_onSuspend(){O(this._name,"[videoelement:event] suspend")}_onStalled(){O(this._name,"[videoelement:event] stalled")}_onWaiting(){O(this._name,"[videoelement:event] waiting")}_onEncrypted(){O(this._name,"[videoelement:event] encrypted")}_onError(e){O(this._name,"[videoelement:event] error"),this.trigger(new Se(be.CONNECT_FAILURE,void 0,{error:e.message}))}async attemptAutoplay(e=!1){try{await this.play(),this.isMuted()&&this.trigger(new Se(be.AUTO_PLAYBACK_MUTED,void 0,{element:this._view}))}catch(t){e?(this.mute(),this.attemptAutoplay(e)):this.trigger(new Se(be.AUTO_PLAYBACK_FAILURE,void 0,{error:t.message?t.message:t,element:this._view}))}}async play(){var e,t;if(O(this._name,"[videoelement:action] play"),!(null===(e=this._view)||void 0===e?void 0:e.paused))return O(this._name,"[videoelement:action] play (ALREADY PLAYING)"),!0;try{return await(null===(t=this._view)||void 0===t?void 0:t.play()),!0}catch(e){throw k(this._name,"[videoelement:action] play (FAULT) - "+e.message),e}}async pause(){var e;O(this._name,"[videoelement:action] pause");try{return await(null===(e=this._view)||void 0===e?void 0:e.pause()),!0}catch(e){H(this._name,"[videoelement:action] pause (CATCH::FAULT) - "+e.message)}return!1}async resume(){var e;O(this._name,"[videoelement:action] resume");try{return await(null===(e=this._view)||void 0===e?void 0:e.play()),!0}catch(e){H(this._name,"[videoelement:action] resume (CATCH::FAULT) - "+e.message)}return!1}async stop(){var e;O(this._name,"[videoelement:action] stop");try{return await(null===(e=this._view)||void 0===e?void 0:e.pause()),!0}catch(e){H(this._name,"[videoelement:action] stop (CATCH::FAULT) - "+e.message)}return!1}mute(){this._view&&(this._view.muted=!0);const e=this.getControls();e&&e.setMutedState(!0)}unmute(){this._view&&(this._view.muted=!1);const e=this.getControls();e&&e.setMutedState(!1)}setVolume(e){this.unmute(),this._view&&(this._view.volume=e)}getVolume(){var e,t;return null!==(t=null===(e=this._view)||void 0===e?void 0:e.volume)&&void 0!==t?t:0}seekTo(e,t=void 0){this._view&&(this._view.currentTime=t?e*t:e)}toggleFullScreen(e){try{(e||this._view)&&ie.toggleFullScreen(null!=e?e:this._view)}catch(e){}}async unpublish(){var e;try{await this.stop(),null===(e=this._view)||void 0===e||e.dispatchEvent(new Event("ended"))}catch(e){}}disconnect(){this._cleanup()}isVOD(){return this._isVOD}isMuted(){var e,t;return null!==(t=null===(e=this._view)||void 0===e?void 0:e.muted)&&void 0!==t&&t}getControls(){}}const bt="WHEPClient",At=ht,wt=e=>O(bt,e),yt=e=>k(bt,e),Lt=e=>H(bt,e);class Nt extends Et{constructor(e,t,i){super(),this._videoMuted=!0,this._audioMuted=!0;const n=e?se(e):At,s=i||At,o={...s,...n,endpoint:e,mediaElementId:t?t.id:s.mediaElementId};this._videoUnmuteHandler=this._onVideoUnmute.bind(this),this._audioUnmuteHandler=this._onAudioUnmute.bind(this),e&&this.internalInit(o)}async internalInit(e){await this.init(e),await this.subscribe()}async _runMuteCheck(){var e,t,i;if(this.getPeerConnection())try{let n=this._videoMuted,s=this._audioMuted;const o=await(null===(e=this.getPeerConnection())||void 0===e?void 0:e.getStats());if(null==o||o.forEach((e=>{const{type:t,kind:i,bytesReceived:o}=e;"inbound-rtp"!==t&&"inboundrtp"!==t||("video"===i?n=o<=0:"audio"===i&&(s=o<=0))})),n===this._videoMuted&&s===this._audioMuted)return;this._videoMuted=n,this._audioMuted=s;const a={data:{streamingMode:(t=!this._videoMuted,i=!this._audioMuted,t&&i?vt.FULL:t?vt.VIDEO:i?vt.AUDIO:vt.EMPTY),method:"onMetaData"},type:"metadata",method:"onMetaData",eventTimestamp:(new Date).getTime()};this._onMetaData(a)}catch(e){yt(e.message||e)}}_onVideoUnmute(e){const t=e.target;null==t||t.removeEventListener("unmute",this._videoUnmuteHandler);const i=setTimeout((async()=>{clearTimeout(i),this._runMuteCheck()}),1e3)}_onAudioUnmute(e){const t=e.target;null==t||t.removeEventListener("unmute",this._audioUnmuteHandler);const i=setTimeout((async()=>{clearTimeout(i),this._runMuteCheck()}),1e3)}_attachSourceHandler(e){this._sourceHandler=new Tt(e,this.getType())}_glomTrigger(e){e.on("*",(e=>{const{type:t,data:i}=e;this.trigger(new Se(t,this,i))}))}_playIfAutoplaySet(e,t){var i;if(e&&t){const{muteOnAutoplayRestriction:n}=e;ie.hasAttributeDefined(t,"autoplay")&&(null===(i=this._sourceHandler)||void 0===i||i.attemptAutoplay(n))}}addMediaStreamToPlayback(e,t){var i;!this._playbackView&&e&&(this._playbackView=new pt(e)),null===(i=this._playbackView)||void 0===i||i.attachStream(t)}async requestOffer(i){var n;wt("[requestoffer]");const{iceTransport:s,maintainStreamVariant:o,videoEncoding:a,audioEncoding:r,connectionParams:l,mungeOffer:d}=this._options;i.addTransceiver("video",{direction:"recvonly"}),i.addTransceiver("audio",{direction:"recvonly"});const h={transport:s,doNotSwitch:o};a&&a!==t.NONE&&(h.videoEncoding=a),r&&r!==e.NONE&&(h.audioEncoding=r);const c=null!=l?l:{},u=await i.createOffer(),_=await(null===(n=this._whipWhepService)||void 0===n?void 0:n.postSDPOffer(u.sdp,{...c,...h},!1));if(!_)throw yt("Failed to get offer from WHEP"),new Error("Failed to get offer from WHEP");const{sdp:p}=_;let m=p;return d&&(wt(`[MUNGE:before] offer: ${m}`),m=d(m),wt(`[MUNGE:after] offer: ${m}`)),m}async requestAnswer(e){const{mungeAnswer:t}=this._options;let i=(await e.createAnswer()).sdp;return t&&(wt(`[MUNGE:before] answer: ${i}`),i=t(i),wt(`[MUNGE:after] answer: ${i}`)),i}async sendAnswer(e){var t;const{connectionParams:i}=this._options;return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.postSDPAnswer(e,i))}async postCandidateFragments(e){var t;const{connectionParams:i}=this._options,n=Ue(e,void 0,!0);return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.trickle(n,i))}_evaluateRenegotiationPolicy(e){const{renegotiationPolicy:t}=this._options;if(t){const{type:i}=t,n=i.toLowerCase();wt(`[evaluateRenegotiationPolicy] - Type: ${e}, Renegotiation Policy: ${t.type}`),(e===ye.CONNECTION_HEALTH_STATE_REGRESSION&&"regression"===n||e===ye.CONNECTION_HEALTH_ICE_TIMEOUT&&"timeout"===n||e===be.CONNECTION_CLOSED&&"disconnect"===n)&&this._reconnect()}}async _reconnect(){var e,t;wt("[reconnect]"),this.trigger(new Se(be.RECONNECT_START,this));try{await this.unsubscribe(!0),await this.init(this._options),await this.subscribe()}catch(i){yt(null!==(e=i.message)&&void 0!==e?e:"Could not reconnect."),this.trigger(new Se(be.RECONNECT_FAILURE,this,{error:null!==(t=i.message)&&void 0!==t?t:"Could not reconnect."}))}}async init(e){var t,i;this._options={...At,...e},this._options.subscriptionId=this._options.subscriptionId||`subscriber-${Math.floor(65536*Math.random()).toString(16)}`;const n=oe(this._options,"whep"),{includeDataChannel:s,disableProxy:o}=this._options;return this._whipWhepService=new Je(`${n}?requestId=${this._options.subscriptionId}`,s,o),this._messageTransport=this._whipWhepService,((null===(t=this._options)||void 0===t?void 0:t.stats)||(null===(i=this._options)||void 0===i?void 0:i.renegotiationPolicy))&&(!this._options.stats&&this._options.renegotiationPolicy&&(this._options.stats=ut),this.monitorStats(this._options.stats,this._options.renegotiationPolicy)),this}async subscribe(){var e,t,i,n,s,o,a,r,l;const{connectionParams:d,rtcConfiguration:h,includeDataChannel:c,signalingSocketOnly:u,enableChannelSignaling:_,dataChannelConfiguration:p}=this._options;try{const l=d||{},g=await(null===(e=this._whipWhepService)||void 0===e?void 0:e.getOptions(l));this.trigger(new Se(be.CONNECT_SUCCESS,this,null===(t=this._whipWhepService)||void 0===t?void 0:t.getUrl()));const v=!!(null===(i=this._options)||void 0===i?void 0:i.rtcConfiguration)&&Array.isArray(this._options.rtcConfiguration.iceServers)&&this._options.rtcConfiguration.iceServers.length>0;(null==g?void 0:g.links)&&!v&&(this._options.rtcConfiguration={...h,iceServers:g.links}),(null==g?void 0:g.origin)&&this.trigger(new Se(Ae.HOST_ENDPOINT_CHANGED,this,{endpoint:g.origin})),(null==g?void 0:g.statisticsEndpoint)&&this._onStatisticsEndpointChange(g.statisticsEndpoint);const E=c||_||u?p:void 0;this._peerConnectionHelper=new gt({onUnpublish:this._onUnpublish.bind(this),onStreamUnavailable:this._onStreamUnavailable.bind(this),onSubscriberStatus:this._onSubscriberStatus.bind(this),onStreamSwitchComplete:this._onStreamSwitchComplete.bind(this),onDataChannelError:this._onDataChannelError.bind(this),onSendReceived:this._onSendReceived.bind(this),onMetaData:this._onMetaData.bind(this),onConnectionClosed:this._onConnectionClosed.bind(this),onDataChannelOpen:this._onDataChannelOpen.bind(this),onDataChannelClose:this._onDataChannelClose.bind(this),onDataChannelMessage:this._onDataChannelMessage.bind(this),onPeerConnectionOpen:this._onPeerConnectionOpen.bind(this),onPeerConnectionFail:this._onPeerConnectionFail.bind(this),onPeerConnectionClose:this._onPeerConnectionClose.bind(this),onIceCandidate:this._onIceCandidate.bind(this),onSDPSuccess:this._onSDPSuccess.bind(this),onSDPError:this._onSDPError.bind(this),onStatisticsEndpointChange:this._onStatisticsEndpointChange.bind(this)}),await this._peerConnectionHelper.setUpWithPeerConfiguration(this._options.rtcConfiguration,E),null===(n=this.getPeerConnection())||void 0===n||n.addEventListener("track",(e=>{const{buffer:t}=this._options;wt("[peerconnection.ontrack]");const{streams:i,track:n,receiver:s,transceiver:o}=e;s.playoutDelayHint=t,s.jitterBufferDelayHint=t,this.trigger(new Se(Ae.TRACK_ADDED,this,{streams:i,track:n,receiver:s,transceiver:o})),this._mediaStream=i&&i.length>0?i[0]:void 0,"video"===n.kind?(this._videoMuted=n.muted,n.muted&&n.addEventListener("unmute",this._videoUnmuteHandler)):"audio"===n.kind&&(this._audioMuted=n.muted,n.muted&&n.addEventListener("unmute",this._audioUnmuteHandler)),this._runMuteCheck()})),this.trigger(new Se(Ae.PEER_CONNECTION_AVAILABLE,this,this.getPeerConnection())),this.trigger(new Se(Ae.OFFER_START,this));const S=await this.requestOffer(this.getPeerConnection()),C=new RTCSessionDescription({type:"offer",sdp:S});await(null===(s=this.getPeerConnection())||void 0===s?void 0:s.setRemoteDescription(C)),this.trigger(new Se(Ae.OFFER_END,this)),this.trigger(new Se(Ae.ANSWER_START,this));const f=await this.requestAnswer(this.getPeerConnection()),T=(m=f).includes("stereo=1")?m:m.replace("useinbandfec=1","useinbandfec=1;stereo=1;sprop-stereo=1"),b=new RTCSessionDescription({type:"answer",sdp:T});await(null===(o=this.getPeerConnection())||void 0===o?void 0:o.setLocalDescription(b)),await this.sendAnswer(T),this.trigger(new Se(Ae.ANSWER_END,this));const A=await this._peerConnectionHelper.waitToGatherIce(),{sdp:w}=A;return await this.postCandidateFragments(w),this.trigger(new Se(Ae.ICE_TRICKLE_COMPLETE,this)),this._mediaStream&&(this.trigger(new Se(Ae.ON_ADD_STREAM,this,this._mediaStream)),this.addMediaStreamToPlayback(this._options.mediaElementId,this._mediaStream)),(null===(a=this._playbackView)||void 0===a?void 0:a.view)&&this._attachSourceHandler(this._playbackView.view),this._sourceHandler&&this._glomTrigger(this._sourceHandler),this._playIfAutoplaySet(this._options,null===(r=this._playbackView)||void 0===r?void 0:r.view),this}catch(e){throw yt(null!==(l=e.message)&&void 0!==l?l:"Could not subscribe."),e instanceof $e?this._onStreamUnavailable(e):this.trigger(new Se(be.CONNECT_FAILURE,this,e)),this._options.maintainConnectionOnSubscribeErrors||this.unsubscribe(!0),e}var m}async unsubscribe(e=!1){var t;wt("[unsubscribe]"),this._peerConnectionHelper&&await this._peerConnectionHelper.tearDown(),this._whipWhepService&&await this._whipWhepService.tearDown(null,e),this._sourceHandler&&this._sourceHandler.disconnect(),this.unmonitorStats(),null===(t=this._playbackView)||void 0===t||t.detachStream(),this._playbackView=void 0,this._whipWhepService=void 0,this._messageTransport=void 0,this._peerConnectionHelper=void 0,this._sourceHandler=void 0,this._mediaStream=void 0,this.trigger(new Se(be.SUBSCRIBE_STOP,this))}send(e,t){var i;return null===(i=this.getMessageTransport())||void 0===i?void 0:i.post({send:{method:e,data:"string"==typeof t?JSON.parse(t):t}})}async callServer(e,t){var i;const n="switchStreams"===e,{app:s,streamName:o}=this._options;if(n){const{path:i}=t[0];this._requestedStreamSwitch=i,wt(`[callServer:switch]:: ${e}, ${s}/${o} -> ${i}`)}return null===(i=this.getMessageTransport())||void 0===i?void 0:i.postAsync({callAdapter:{method:e,arguments:t}})}sendLog(e,t){var i;try{const n=Object.keys(P).find((t=>t.toLowerCase()===e.toLowerCase()))?e:P.DEBUG,s="string"==typeof t?t:JSON.stringify(t);null===(i=this.getMessageTransport())||void 0===i||i.post({log:n.toUpperCase(),message:s})}catch(e){const t=e.message||e;yt("Could not send log to server. Message parameter expected to be String or JSON-serializable object."),yt(t)}}enableStandby(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0,muteVideo:!0}})}disableStandby(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1,muteVideo:!1}})}muteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0}})}unmuteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1}})}muteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!0}})}unmuteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!1}})}get options(){return this._options}getOptions(){return this._options}getPeerConnection(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.connection}getDataChannel(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.dataChannel}getMediaStream(){return this._mediaStream}getMessageTransport(){return this._messageTransport}getPlayer(){var e;return null===(e=this._playbackView)||void 0===e?void 0:e.view}play(){wt("[play]"),this._sourceHandler?this._sourceHandler.play():Lt("Cannot play without a Source Handler.")}pause(){wt("[pause]"),this._sourceHandler?this._sourceHandler.pause():Lt("Cannot pause without a Source Handler.")}resume(){wt("[resume]"),this._sourceHandler?this._sourceHandler.resume():Lt("Cannot resume without a Source Handler.")}stop(){wt("[stop]"),this._sourceHandler?this._sourceHandler.stop():Lt("Cannot stop without a Source Handler.")}setVolume(e){wt("[setVolume]"),this._sourceHandler?this._sourceHandler.setVolume(e):Lt("Cannot set volume without a Source Handler.")}getVolume(){var e,t,i;return wt("[getVolume]"),this._sourceHandler?this._sourceHandler.getVolume():(Lt("Cannot get volume without a Source Handler."),null!==(i=null===(t=null===(e=this._playbackView)||void 0===e?void 0:e.view)||void 0===t?void 0:t.volume)&&void 0!==i?i:0)}mute(){wt("[mute]"),this._sourceHandler?this._sourceHandler.mute():Lt("Cannot mute without a Source Handler.")}unmute(){wt("[unmute]"),this._sourceHandler?this._sourceHandler.unmute():Lt("Cannot unmute without a Source Handler.")}seekTo(e){wt("[seekTo]"),this._sourceHandler?this._sourceHandler.seekTo(e):Lt("Cannot seek without a Source Handler.")}toggleFullScreen(){wt("[toggleFullScreen]"),this._sourceHandler?this._sourceHandler.toggleFullScreen():Lt("Cannot toggle full screen without a Source Handler.")}monitorStats(e,t){wt(`[monitorStats]:: Stats: ${e?JSON.stringify(e):"undefined"}`),wt(`[monitorStats]:: Renegotiation Policy: ${t?JSON.stringify(t):"undefined"}`);const{host:i,endpoint:n,app:s,streamName:o,subscriptionId:a,connectionParams:r}=this._options,l=null!=e?e:_e;return this._statisticsConfiguration={...l,host:i,app:s,hostEndpoint:n,streamName:o,subscriptionId:a,connectionParams:r},this._statsMonitor?Lt("Cannot monitor stats without a Peer Connection. Please call `init` before calling `monitorStats`."):this._statsMonitor=new ft(this._statisticsConfiguration,{onStatsReport:this._onStatsReport.bind(this),getPeerConnection:this.getPeerConnection.bind(this),getMessageTransport:this.getMessageTransport.bind(this),on:this.on.bind(this),off:this.off.bind(this),trigger:this.trigger.bind(this),emit:this.emit.bind(this)},t),this}unmonitorStats(){return this._statsMonitor&&this._statsMonitor.dispose(),this._statsMonitor=void 0,this._statisticsConfiguration=void 0,this}_onUnpublish(){wt("[unpublish]"),this.trigger(new Se(be.PLAY_UNPUBLISH,this)),this._sourceHandler&&this._sourceHandler.unpublish()}_onStreamUnavailable(e){wt(`Stream ${this._options.streamName} does not exist.`),wt("[onstreamunavailable]: "+JSON.stringify(e,null,2)),this.trigger(new Se(be.SUBSCRIBE_INVALID_NAME,this))}_onDataChannelError(e,t){yt(`Data channel error: ${t}`),this.trigger(new Se(Ae.DATA_CHANNEL_ERROR,this,{dataChannel:e,error:t}))}_onSendReceived(e,t){wt(`Send received: ${e} ${JSON.stringify(t)}`),"onMetaData"===e?this._onMetaData(t):this.trigger(new Se(be.SUBSCRIBE_SEND_INVOKE,this,{methodName:e,data:t}))}_onStreamSwitchComplete(){wt("[streamswitch::complete]");const e=this._requestedStreamSwitch;this.trigger(new Se(Ae.SUBSCRIBE_STREAM_SWITCH,this,{path:e})),this._requestedStreamSwitch=void 0}_onMetaData(e){const{orientation:t,streamingMode:i}=e,n=this._streamingMode;void 0!==t&&t!==this._orientation&&(this._orientation=t,this.trigger(new Se(be.ORIENTATION_CHANGE,this,{orientation:parseInt(t,10),viewElement:this._playbackView?this._playbackView.view:void 0}))),i&&void 0!==i&&i!==n&&(this._streamingMode=i,this.trigger(new Se(be.STREAMING_MODE_CHANGE,this,{streamingMode:i,previousStreamingMode:n,viewElement:this._playbackView?this._playbackView.view:void 0}))),this.trigger(new Se(be.SUBSCRIBE_METADATA,this,e))}_onConnectionClosed(){wt("Connection closed"),this.unsubscribe(!0),this.trigger(new Se(be.CONNECTION_CLOSED,this))}_onDataChannelOpen(e){wt(`Data channel opened: ${e.label}`),this.trigger(new Se(Ae.DATA_CHANNEL_OPEN,this,{dataChannel:e})),this.trigger(new Se(Ae.DATA_CHANNEL_AVAILABLE,this,{name:e.label,dataChannel:e})),this._messageTransport=this._peerConnectionHelper,this.trigger(new Ce(we.CHANGE,this,{controller:this,transport:this._messageTransport})),this.trigger(new Se(be.SUBSCRIBE_START,this))}_onDataChannelClose(e){wt(`Data channel closed: ${e.label}`),this.trigger(new Se(Ae.DATA_CHANNEL_CLOSE,this,{dataChannel:e}))}_onDataChannelMessage(e,t){wt(`Data channel message: ${t.data}`),this.trigger(new Se(Ae.DATA_CHANNEL_MESSAGE,this,{dataChannel:e,message:t}))}_onPeerConnectionOpen(){var e;wt("Peer connection opened"),this.trigger(new Se(Ae.PEER_CONNECTION_OPEN,this,this.getPeerConnection())),(null===(e=this._options)||void 0===e?void 0:e.includeDataChannel)||this.trigger(new Se(be.SUBSCRIBE_START,this))}_onPeerConnectionFail(){yt("Peer connection failed"),this.trigger(new Se(be.SUBSCRIBE_FAIL,this))}_onPeerConnectionClose(e){wt(`Peer connection closed: ${e.type}`),this._evaluateRenegotiationPolicy(be.CONNECTION_CLOSED)}_onIceCandidate(e){wt(`ICE candidate: ${e.candidate}`),this.trigger(new Se(Ae.CANDIDATE_CREATE,this,{candidate:e}))}_onPeerConnectionTrackAdd(e){wt(`Peer connection track added: ${e.id}`)}_onSubscriberStatus(e){wt(`Subscriber status: ${JSON.stringify(e)}`)}_onSDPSuccess(){wt("SDP success")}_onSDPError(e){yt(`SDP error: ${e}`)}_onStatisticsEndpointChange(e){wt(`Statistics endpoint changed: ${e}`),this._statsMonitor&&this._statsMonitor.updateEndpoint(e),this.trigger(new Se(be.STATISTICS_ENDPOINT_CHANGE,this,{statisticsEndpoint:e}))}_onStatsReport(e,t){this.trigger(new Se(Ae.STATS_REPORT,this,{connection:e,report:t}))}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}trigger(e){super.trigger(e)}emit(e,t){this.trigger(new Se(e,this,t)),this._evaluateRenegotiationPolicy(e)}getType(){return"RTC"}}class Pt extends Tt{constructor(e,t){super(e,t),this._playingStarted=!1,this.onOrientation=this._onOrientationMetadata.bind(this),this.onStreamingMode=this._onStreamingModeMetadata.bind(this),ie.onOrientationMetadata(this._view,this.onOrientation),ie.onStreamingModeMetadata(this._view,this.onStreamingMode),this.onPlaying=this._onPlaying.bind(this),this.onSourceError=this._onSourceError.bind(this),this._view.addEventListener("playing",this.onPlaying)}addSource(e){this._source=ie.createElement("source"),this._source.type="application/x-mpegURL",this._source.src=e,this._view.firstChild?this._view.insertBefore(this._source,this._view.firstChild):this._view.appendChild(this._source),this._source.addEventListener("error",this.onSourceError)}_onPlaying(){this._playingStarted||this.trigger(new Se(be.SUBSCRIBE_START,this._view)),this._playingStarted=!0}_onSourceError(e){O(this._name,"[source:event] error"),this.trigger(new Se(be.CONNECT_FAILURE,void 0,e))}_onOrientationMetadata(e){const{orientation:t}=e,i=parseInt(t,10);t&&this._orientation!==i&&(O(this._name,"Metadata received: "+JSON.stringify(e,null,2)),this._orientation=i,this.trigger(new Se(be.ORIENTATION_CHANGE,{orientation:this._orientation,viewElement:this._view})),this.trigger(new Se(be.SUBSCRIBE_METADATA,void 0,e)))}_onStreamingModeMetadata(e){const{streamingMode:t}=e,i=this._streamingMode;t&&i!==t&&(O(this._name,"Metadata received: "+JSON.stringify(e,null,2)),this._streamingMode=t,this.trigger(new Se(be.STREAMING_MODE_CHANGE,void 0,{streamingMode:this._streamingMode,previousStreamingMode:i,viewElement:this._view})),this.trigger(new Se(be.SUBSCRIBE_METADATA,void 0,e)))}_cleanup(){this._view&&this._view.removeEventListener("playing",this.onPlaying),this._source&&(this._source.removeEventListener("error",this.onSourceError),this._view.removeChild(this._source),this._source=void 0),super._cleanup()}}const Rt="HLSSubscriber",Dt=e=>O(Rt,e),It=e=>H(Rt,e);class Ot extends Et{constructor(){super()}_glomTrigger(e){e.on("*",(e=>{const{type:t,data:i}=e;this.trigger(new Se(t,this,i))}))}_playIfAutoplaySet(e,t){var i;if(e&&t){const{muteOnAutoplayRestriction:n}=e;ie.hasAttributeDefined(t,"autoplay")&&(null===(i=this._sourceHandler)||void 0===i||i.attemptAutoplay(n))}}async init(e){if(!ie.supportsHLS())throw new Error("Native HLS playback is not supported on this browser.");return this._options={...ct,...e},this}async subscribe(){var e;try{const t=/^http(|s).*\.m3u8/g,{endpoint:i,mediaElementId:n}=this._options;return this._fileURL=i&&i.match(t)?i:(e=>{const{host:t,protocol:i,port:n,app:s,streamName:o,connectionParams:a}=e,r="ws"===i||"http"===i?"http":"https",l=`${r}://${t}:${n||("http"===r?5080:443)}/${s}/${o}.m3u8`;if(a)return`${l}?${Object.entries(a).map((([e,t])=>`${e}=${t}`)).join("&")}`;return l})(this._options),!this._playbackView&&n&&(this._playbackView=new pt(n),this._sourceHandler=new Pt(this._playbackView.view,this.getType()),this._sourceHandler.addSource(this._fileURL),this._glomTrigger(this._sourceHandler)),this.trigger(new Se(be.CONNECT_SUCCESS,this,this._fileURL)),this._playIfAutoplaySet(this._options,null===(e=this._playbackView)||void 0===e?void 0:e.view),this}catch(e){throw e(e.message),this.trigger(new Se(be.CONNECT_FAILURE,this,e.message)),e}}async unsubscribe(){var e;return this._sourceHandler&&this._sourceHandler.disconnect(),null===(e=this._playbackView)||void 0===e||e.detachStream(),this._playbackView=void 0,this._sourceHandler=void 0,this.trigger(new Se(be.SUBSCRIBE_STOP,this)),this}play(){Dt("[play]"),this._sourceHandler?this._sourceHandler.play():It("Cannot play without a Source Handler.")}pause(){Dt("[pause]"),this._sourceHandler?this._sourceHandler.pause():It("Cannot pause without a Source Handler.")}resume(){Dt("[resume]"),this._sourceHandler?this._sourceHandler.resume():It("Cannot resume without a Source Handler.")}stop(){Dt("[stop]"),this._sourceHandler?this._sourceHandler.stop():It("Cannot stop without a Source Handler.")}setVolume(e){Dt("[setVolume]"),this._sourceHandler?this._sourceHandler.setVolume(e):It("Cannot set volume without a Source Handler.")}getVolume(){var e,t,i;return Dt("[getVolume]"),this._sourceHandler?this._sourceHandler.getVolume():(It("Cannot get volume without a Source Handler."),null!==(i=null===(t=null===(e=this._playbackView)||void 0===e?void 0:e.view)||void 0===t?void 0:t.volume)&&void 0!==i?i:0)}mute(){Dt("[mute]"),this._sourceHandler?this._sourceHandler.mute():It("Cannot mute without a Source Handler.")}unmute(){Dt("[unmute]"),this._sourceHandler?this._sourceHandler.unmute():It("Cannot unmute without a Source Handler.")}seekTo(e){Dt("[seekTo]"),this._sourceHandler?this._sourceHandler.seekTo(e):It("Cannot seek without a Source Handler.")}toggleFullScreen(){Dt("[toggleFullScreen]"),this._sourceHandler?this._sourceHandler.toggleFullScreen():It("Cannot toggle full screen without a Source Handler.")}getPlayer(){var e;return null===(e=this._playbackView)||void 0===e?void 0:e.view}get options(){return this._options}getOptions(){return this._options}get fileURL(){return this._fileURL}getFileURL(){return this._fileURL}getType(){return"HLS"}}const Ht={baseURL:void 0,fullURL:void 0,hlsjsRef:void 0,hlsElement:void 0,usePlaybackControlsUI:!0,options:{debug:!1,backBufferLength:0}},kt={...ht,liveSeek:Ht};class Mt extends U{trigger(e){super.trigger(e)}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}}var Ut,Bt;!function(e){e.SEEK_START="Seek.Start",e.SEEK_END="Seek.End"}(Ut||(Ut={})),function(e){e.CHANGE="Slider.Change",e.CHANGE_START="Slider.Change.Start",e.CHANGE_COMPLETE="Slider.Change.Complete"}(Bt||(Bt={}));class Vt extends ve{constructor(e,t,i){super(e,i),this._slider=t}get slider(){return this._slider}}const{createElement:$t,addGlobalEventListener:Ft,removeGlobalEventListener:Gt,globalUnassign:Wt,getAssignedValue:xt,globalAssign:jt}=ie,Kt="ControlSlider",zt="r5_liveseek_event_owner";class Jt extends U{constructor(e){super(),this._value=0,this._disabled=!1,this._eventStartPosition=0,this.debug=e=>O(Kt,e),this.warn=e=>H(Kt,e),this.name=[Kt,e].join("::"),this.debug("[init]"),this._container=$t("div"),this._button=this.createButton(),this._track=this.createTrack(),this._progressBar=this.createProgressBar(),this._container.appendChild(this._track),this._container.appendChild(this._progressBar),this._container.appendChild(this._button),this._layout(),this._mouseupHandler=this._mouseup.bind(this),this._mousedownHandler=this._mousedown.bind(this),this._mousemoveHandler=this._mousemove.bind(this),this._touchupHandler=this._touchproxy.bind(this),this._touchdownHandler=this._touchproxy.bind(this),this._touchmoveHandler=this._touchproxy.bind(this),this._updateHandlers(this._disabled)}_touchproxy(e){var t,i,n,s;const o=e;this.debug(`${o.type} touches: ${(null===(t=o.changedTouches)||void 0===t?void 0:t.length)||0}`);try{o.preventDefault()}catch(e){this.warn("Failed to prevent default on touch event.")}if(!o.touches||o.touches.length>1||"touchend"===o.type&&o.touches.length>0)return;let a,r="";const l=o.target||document.body;switch(o.type){case"touchstart":r="mousedown",a=null===(i=o.changedTouches)||void 0===i?void 0:i[0];break;case"touchmove":r="mousemove",a=null===(n=o.changedTouches)||void 0===n?void 0:n[0];break;case"touchend":r="mouseup",a=null===(s=o.changedTouches)||void 0===s?void 0:s[0]}if(a&&r){const e=new MouseEvent(r,{bubbles:!0,cancelable:!0,view:l.ownerDocument.defaultView,screenX:a.screenX,screenY:a.screenY,clientX:a.clientX,clientY:a.clientY,ctrlKey:o.ctrlKey,altKey:o.altKey,shiftKey:o.shiftKey,metaKey:o.metaKey,button:0,relatedTarget:null});l.dispatchEvent(e)}}_mouseup(){this._eventStartPosition=0,Wt(zt),Gt("mousemove",this._mousemoveHandler),Gt("mouseup",this._mouseupHandler),Gt("touchmove",this._touchmoveHandler),Gt("touchend",this._touchupHandler),this.trigger(new Vt(Bt.CHANGE_COMPLETE,this))}_mousemove(e){if(xt(zt)!==this.name)return;this.debug(`[mousemove] ${this.name}`);const t=e.clientX-this._eventStartPosition,i=this._button.parentNode.getBoundingClientRect();let n=this._eventStartPosition+t-i.left;n=Math.max(0,n),n=Math.min(n,i.width);const s=n/i.width;this.trigger(new Vt(Bt.CHANGE,this,s))}_mousedown(e){this._eventStartPosition=e.clientX,this.trigger(new Vt(Bt.CHANGE_START,this)),jt(zt,this.name),Ft("mousemove",this._mousemoveHandler),Ft("mouseup",this._mouseupHandler),Ft("touchmove",this._touchmoveHandler),Ft("touchend",this._touchupHandler)}_updateHandlers(e){this._eventStartPosition=0,e?(this._track.removeEventListener("click",this._mousemoveHandler),this._progressBar.removeEventListener("click",this._mousemoveHandler),this._button.removeEventListener("mousedown",this._mousedownHandler),Gt("mousemove",this._mousemoveHandler),Gt("mouseup",this._mouseupHandler),Gt("touchmove",this._touchmoveHandler),Gt("touchend",this._touchupHandler),this._track.classList.add("red5pro-media-slider-disabled"),this._progressBar.classList.add("red5pro-media-slider-disabled"),this._button.classList.add("red5pro-media-slider-disabled")):(this._track.addEventListener("click",this._mousemoveHandler),this._progressBar.addEventListener("click",this._mousemoveHandler),this._button.addEventListener("mousedown",this._mousedownHandler),this._button.addEventListener("touchstart",this._touchdownHandler),this._track.classList.remove("red5pro-media-slider-disabled"),this._progressBar.classList.remove("red5pro-media-slider-disabled"),this._button.classList.remove("red5pro-media-slider-disabled"))}_layout(){const e=this._progressBar.parentNode.clientWidth*this._value;this._progressBar.style.width=e+"px",this._button.style.left=e-.5*this._button.clientWidth+"px"}createButton(){const e=$t("span");return e.classList.add("red5pro-media-slider-button"),e}createProgressBar(){const e=$t("span");return e.classList.add("red5pro-media-slider-progress"),e}createTrack(){const e=$t("span");return e.classList.add("red5pro-media-slider-track"),e}get value(){return this._value}set value(e){this._value=e,this._layout()}get disabled(){return this._disabled}set disabled(e){this._disabled=e,this._updateHandlers(e)}get view(){return this._container}}const{createElement:Yt,isTouchEnabled:qt,isPossiblySafari:Xt}=ie,Qt=e=>O("PlaybackControls",e);class Zt extends Mt{constructor(e,t){super(),this._state=i.IDLE,this._mutedState=!1,this._resumeAfterSeek=!1,this._playbackDuration=0,this._volumeValue=1,this._player=e,this._container=t,this._onPlayPauseClickBound=this._onPlayPauseClick.bind(this),this._decorate(this._container)}_decorate(e){if(!e)return;Qt("[decorate]");const t=Yt("div");let n;t.classList.add("red5pro-media-control-bar"),this._playPauseButton=this._createPlayPauseButton(),this._muteButton=this._createMuteButton(),this._volumeField=this._createVolumeControl(),this._seekTimeField=this._createSeekControl(),this._timeField=this._createPlaybackTime(),this._fullScreenButton=this._createFullScreenToggle(),t.appendChild(this._playPauseButton),t.appendChild(this._timeField),t.appendChild(this._seekTimeField.view),t.appendChild(this._muteButton),t.appendChild(this._volumeField.view),t.appendChild(this._fullScreenButton),e.appendChild(t),this._controlbar=t;const s=()=>{clearTimeout(n),n=setTimeout((()=>{t.classList.remove("red5pro-media-control-bar-show")}),6e3)};qt()?(t.classList.add("red5pro-media-control-bar-show"),e.addEventListener("touchend",(()=>{t.classList.toggle("red5pro-media-control-bar-show"),s()})),s()):(e.addEventListener("mouseover",(()=>{t.classList.add("red5pro-media-control-bar-show")})),e.addEventListener("mouseout",(()=>{t.classList.remove("red5pro-media-control-bar-show")}))),this.setState(i.IDLE).onFullScreenChange(!1).setSeekTime(0).enable(!1)}_onPlayPauseClick(){return this.getState()===i.PLAYING?this._player.pause(!0):this.getState()===i.PAUSED?this._player.resume(!0):this._player.play(!0),this}_createPlayPauseButton(){const e=Yt("button");return e.setAttribute("aria-label","Toggle Playback"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-playpause-button"),e}_createMuteButton(){const e=Yt("button");return e.setAttribute("aria-label","Toggle Mute Audio"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-muteunmute-button"),e.addEventListener("click",(()=>{this.getMutedState()?(this._player.unmute(),this.setMutedState(!1)):(this._player.mute(),this.setMutedState(!0))})),e}_createVolumeControl(){const e=new Jt("volume");return e.view.classList.add("red5pro-media-control-element"),e.view.classList.add("red5pro-media-volume-slider"),e.view.classList.add("red5pro-media-slider"),e.on(Bt.CHANGE,(e=>{const t=Number(e.data);this._player.setVolume(t)})),e}_createSeekControl(){const e=new Jt("seek");return e.view.classList.add("red5pro-media-control-element"),e.view.classList.add("red5pro-media-seektime-slider"),e.view.classList.add("red5pro-media-slider"),e.on(Bt.CHANGE_START,(()=>{this.getState()===i.PLAYING&&(this._resumeAfterSeek=!0,this._player.pause(!0,!0)),this.trigger(new ve(Ut.SEEK_START))})),e.on(Bt.CHANGE,(e=>{const t=Number(e.data);this._player.seekTo(t,0===this._playbackDuration?void 0:this._playbackDuration),this.setSeekTime(t*this._playbackDuration,this._playbackDuration)})),e.on(Bt.CHANGE_COMPLETE,(()=>{this._resumeAfterSeek&&this.getState()===i.PAUSED&&(this._resumeAfterSeek=!1,this._player.resume(!0)),this.trigger(new ve(Ut.SEEK_END))})),e}_createPlaybackTime(){const e=Yt("span"),t=Yt("text");return t.textContent="00:00",e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-time-field"),e.appendChild(t),e}_createFullScreenToggle(){const e=Yt("button");return e.setAttribute("aria-label","Toggle Fullscreen"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-fullscreen-button"),e.addEventListener("click",(()=>{this._player.toggleFullScreen()})),e}_formatTime(e){const t=new Date(1e3*e);return`${String(t.getUTCHours()).padStart(2,"0")}:${String(t.getUTCMinutes()).padStart(2,"0")}:${String(t.getUTCSeconds()).padStart(2,"0")}`}onStateChange(e){var t,n,s,o;return e===i.PLAYING?(null===(t=this._playPauseButton)||void 0===t||t.classList.remove("red5pro-media-play-button"),null===(n=this._playPauseButton)||void 0===n||n.classList.add("red5pro-media-pause-button")):(null===(s=this._playPauseButton)||void 0===s||s.classList.add("red5pro-media-play-button"),null===(o=this._playPauseButton)||void 0===o||o.classList.remove("red5pro-media-pause-button")),this}onMutedStateChange(e){var t,i,n,s;return e?(null===(t=this._muteButton)||void 0===t||t.classList.add("red5pro-media-mute-button"),null===(i=this._muteButton)||void 0===i||i.classList.remove("red5pro-media-unmute-button"),this._volumeField&&(this._volumeField.value=0)):(null===(n=this._muteButton)||void 0===n||n.classList.remove("red5pro-media-mute-button"),null===(s=this._muteButton)||void 0===s||s.classList.add("red5pro-media-unmute-button"),this._volumeField&&(this._volumeField.value=this._volumeValue)),this}onFullScreenChange(e){var t,i,n,s;return e?(null===(t=this._fullScreenButton)||void 0===t||t.classList.add("red5pro-media-exit-fullscreen-button"),null===(i=this._fullScreenButton)||void 0===i||i.classList.remove("red5pro-media-fullscreen-button")):(null===(n=this._fullScreenButton)||void 0===n||n.classList.remove("red5pro-media-exit-fullscreen-button"),null===(s=this._fullScreenButton)||void 0===s||s.classList.add("red5pro-media-fullscreen-button")),this}enable(e){var t,i,n,s;return e?(null===(t=this._playPauseButton)||void 0===t||t.classList.remove("red5pro-media-element-button-disabled"),null===(i=this._playPauseButton)||void 0===i||i.addEventListener("click",this._onPlayPauseClickBound)):(null===(n=this._playPauseButton)||void 0===n||n.classList.add("red5pro-media-element-button-disabled"),null===(s=this._playPauseButton)||void 0===s||s.removeEventListener("click",this._onPlayPauseClickBound)),this}getVolume(){return this._volumeValue}setVolume(e){return this._volumeField&&(this._volumeField.value=e),this._volumeValue=e,0===e?this.setMutedState(!0):this.getMutedState()&&this.setMutedState(!1),this}setSeekTime(e,t=0){return this._seekTimeField&&(this._seekTimeField.value=0===t?0:e/t,0!==this._playbackDuration&&this._playbackDuration<=e&&(this._seekTimeField.value=1)),this._timeField&&(!isFinite(this._playbackDuration)&&Xt()?this._timeField.innerText="Live Broadcast":this._timeField.innerText=this._formatTime(Math.floor(e))),this}setPlaybackDuration(e){return this._playbackDuration=e,this}getPlaybackDuration(){return this._playbackDuration}getState(){return this._state}setState(e){return Qt(`[setState]: ${s[e]}`),this._state=e,this.onStateChange(this._state),this}setMutedState(e){return this._mutedState=e,this.onMutedStateChange(this._mutedState),this}getMutedState(){return"muted"in this._player?this._player.muted:this._mutedState}setAsVOD(e){return Qt(`[setAsVOD]: ${e}`),this._seekTimeField&&(e?this._seekTimeField.disabled=!1:(this._seekTimeField.value=0,this._seekTimeField.disabled=!0)),this}detach(){this.enable(!1),this._controlbar&&this._controlbar.parentNode&&this._controlbar.parentNode.removeChild(this._controlbar),this._controlbar=void 0,this._container=void 0}}var ei,ti;!function(e){e[e.LIVE=0]="LIVE",e[e.VOD=1]="VOD"}(ei||(ei={})),function(e){e.LIVE="LiveSeek.LIVE",e.VOD="LiveSeek.VOD"}(ti||(ti={}));const ii={[ei.LIVE]:ti.LIVE,[ei.VOD]:ti.VOD};var ni;!function(e){e.LIVE_SEEK_UNSUPPORTED="WebRTC.LiveSeek.Unsupported",e.LIVE_SEEK_ERROR="WebRTC.LiveSeek.Error",e.LIVE_SEEK_ENABLED="WebRTC.LiveSeek.Enabled",e.LIVE_SEEK_DISABLED="WebRTC.LiveSeek.Disabled",e.LIVE_SEEK_LOADING="WebRTC.LiveSeek.FragmentLoading",e.LIVE_SEEK_LOADED="WebRTC.LiveSeek.FragmentLoaded",e.LIVE_SEEK_CHANGE="WebRTC.LiveSeek.Change"}(ni||(ni={}));const{createElement:si,findByQuerySelector:oi,createHLSClient:ai,getHLSClientEventEnum:ri}=ie,li="SourceHandlerSeekable",di=e=>O(li,e),hi=e=>k(li,e),ci=e=>H(li,e);class ui extends Tt{constructor(e,t,i,n,s=!0){super(e,`${t}-Seekable`),this._hlsElementGenerated=!1,this._hlsRecoverFlop=!1,this._hlsRecoverAttempts=0,this._isFragLoading=!1,this._wallOffset=NaN,this._lastDurationUpdate=0,this._averageSegmentDuration=6,this._isSeekable=!1,this._isHLSPlaybackActive=!1,this._container=s?this._determineContainer(e):void 0,this._liveSeekConfig=i,this._hlsOptions=n,this._usePlaybackControls=s,this.onHLSDurationChange=this._onHLSDurationChange.bind(this),this.onHLSTimeUpdate=this._onHLSTimeUpdate.bind(this),this.onHLSPlay=this._onHLSPlay.bind(this),this.onHLSPause=this._onHLSPause.bind(this)}_determineContainer(e){if(e.parentNode&&e.parentNode.classList.contains("red5pro-media-container"))return e.classList.add("red5pro-media"),e.parentNode;{const t=e.parentNode,i=si("div");return i.classList.add("red5pro-media-container"),e.classList.add("red5pro-media"),t.insertBefore(i,e),t.removeChild(e),i.appendChild(e),i}}_generateHLSLivePlayback(e,t,i){const n=`${i}-hls-vod`;let s=oi(`#${n}`);return s||(s=si("video"),s.id=n,s.classList.add("red5pro-hls-vod"),s.classList.add("red5pro-media-background"),s.setAttribute("playsinline","playsinline"),s.style.width="100%",s.style.height="100%",s.style.display="none",e.insertBefore(s,t),this._hlsElementGenerated=!0),s}_onDurationChange(e){var t;di("[videoelement:event] durationchange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();!this.isSeekable&&n&&n.setPlaybackDuration(i.duration)}_onTimeUpdate(e){var t;const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();if(this.isSeekable){if(!this._isHLSPlaybackActive){const e=this._hlsElement.duration,t=i.currentTime-this._lastDurationUpdate,s=isNaN(e)||0===e?i.currentTime:e+this._averageSegmentDuration+t;n&&n.setSeekTime(s,s),this.trigger(new Se(be.PLAYBACK_TIME_UPDATE,void 0,{time:s,duration:s,action:"rtc time update (1)"}))}}else super._onTimeUpdate(e)}_onEnded(){this.isHLSPlaybackActive||super._onEnded()}_onHLSDurationChange(e){const t=e.target,i=e.duration||t.duration;isNaN(this._wallOffset)&&(this._wallOffset=i-this._view.currentTime),this._lastDurationUpdate=this._view.currentTime;const n=i+this._averageSegmentDuration;di(`[HLS:videoelement:duration] ${i}, ${this._averageSegmentDuration}`);const s=this.getControls();s&&s.setPlaybackDuration(n),this._isHLSPlaybackActive?this.trigger(new Se(be.PLAYBACK_TIME_UPDATE,void 0,{time:t.currentTime,duration:n,action:"hls time update"})):this.trigger(new Se(be.PLAYBACK_TIME_UPDATE,void 0,{time:n,duration:n,action:"hls time update"}))}_onHLSTimeUpdate(e){const t=e.target,i=this.getControls();i&&i.setSeekTime(t.currentTime,i.getPlaybackDuration()),t.currentTime>=t.duration?this._showHLSLivePlayback(!1,this._hlsElement,this._view,this._container):!isNaN(t.duration)&&this._isHLSPlaybackActive&&this.trigger(new Se(be.PLAYBACK_TIME_UPDATE,void 0,{time:t.currentTime,duration:t.duration+this._averageSegmentDuration,action:"hls time update"}))}_onHLSPlay(){di("[HLS:videoelement:event] play");const e=this.getControls();e&&e.setState(i.PLAYING),this.trigger(new Se(be.PLAYBACK_STATE_CHANGE,void 0,{code:i.PLAYING,state:s[i.PLAYING]}))}_onHLSPause(){di("[HLS:videoelement:event] pause");const e=this.getControls();e&&e.setState(i.PAUSED),this.trigger(new Se(be.PLAYBACK_STATE_CHANGE,void 0,{code:i.PAUSED,state:s[i.PAUSED]}))}_addSeekableHandlers(e,t,i){if(t){const i=ri();t.on(i.ERROR,((i,n)=>{const{type:s,details:o,fatal:a,url:r}=n;if("networkerror"===s.toLowerCase()){if("levelemptyerror"===o.toLowerCase()){this.trigger(new Se(ni.LIVE_SEEK_DISABLED,void 0,{hlsElement:e,hlsControl:t})),this.isSeekable=!1,t.destroy();const i=setTimeout((()=>{clearTimeout(i),this.enableLiveSeek(r,this._subscriptionId,this._hlsElement,!1)}),3e3);return}this.trigger(new Se(ni.LIVE_SEEK_ERROR,void 0,{hlsElement:e,hlsControl:t,error:n}))}else this.trigger(new Se(ni.LIVE_SEEK_ERROR,void 0,{hlsElement:e,hlsControl:t,error:n}));"mediaerror"===s.toLowerCase()&&(this._hlsRecoverFlop&&t.swapAudioCodec(),this._hlsRecoverFlop=!this._hlsRecoverFlop,this._hlsRecoverAttempts=this._hlsRecoverAttempts+1,t.recoverMediaError()),a&&"networkerror"===s.toLowerCase()&&t.startLoad()})),t.on(i.MANIFEST_PARSED,(()=>{try{e.pause()}catch(e){di(`Could not pause seekable live stream: ${e.message}`)}this.isSeekable=!0,this.trigger(new Se(ni.LIVE_SEEK_ENABLED,void 0,{hlsElement:e,hlsControl:t}))})),t.on(i.FRAG_LOADING,((i,n)=>{const{frag:{stats:{loaded:s,total:o}}}=n;this.trigger(new Se(ni.LIVE_SEEK_LOADING,void 0,{hlsElement:e,hlsControl:t,progress:s/o*100})),(this._isHLSPlaybackActive||this._isFragLoading)&&(this._isFragLoading=s/o>=1)})),t.on(i.FRAG_LOADED,((i,n)=>{this._isFragLoading=!1;const{frag:{endDTS:s,loader:o}}=n;if(!this._isHLSPlaybackActive&&!s)return;let a=6,r=0;if(o&&o.stats&&o.stats.segments){const e=o.stats.segments;for(let t=0;t{this._isFragLoading=!1;const{frag:{endDTS:s,loader:o}}=n;if(!this._isHLSPlaybackActive&&!s)return;let a=6,r=0;if(o&&o.stats&&o.stats.segments){const e=o.stats.segments;for(let t=0;tn.test(e)));if(!a)return void ci(`Could not find last segment in manifest: ${e}`);const r=o.find((e=>i.test(e)));if(!r)return void ci(`Could not find duration line in manifest: ${e}`);const l=r.match(i);if(!l)return void ci(`Could not find duration in manifest: ${e}`);const d=l[1],h=parseFloat(d),c=a.match(n);if(!c)return void ci(`Could not find segment length in manifest: ${e}`);const u=c[1];let _=parseInt(u,10);isNaN(_)&&(_=1),_=_>1?_-1:_,this._averageSegmentDuration=h,this.isSeekable=!0,this.trigger(new Se(ni.LIVE_SEEK_ENABLED,void 0,{hlsElement:this._hlsElement,hlsControl:void 0})),this.onHLSDurationChange({target:t,duration:h*_}),this._manifestLoadTimeout=setTimeout((()=>{clearTimeout(this._manifestLoadTimeout),this._loadManifest(e,t)}),1e3*h)}catch(e){hi(`Could not load manifest: ${e.message}.`),this.trigger(new Se(ni.LIVE_SEEK_DISABLED,void 0,{hlsElement:t,hlsControl:void 0})),this.isSeekable=!1}}_cleanup(){this._removeSeekableHandlers(this._hlsElement,this._hlsjsRef),this._hlsjsRef&&(this._hlsjsRef.detachMedia(),this._hlsjsRef=void 0),this._hlsElement&&(this._hlsElement.parentNode&&this._hlsElementGenerated&&this._hlsElement.parentNode.removeChild(this._hlsElement),this._hlsElement=void 0),this._playbackControls&&(this._playbackControls.detach(),this._playbackControls=void 0),this._isVOD=!1,this._isSeekable=!1,this._isHLSPlaybackActive=!1,this._isFragLoading=!1,this._hlsRecoverFlop=!1,this._hlsRecoverAttempts=0,this._averageSegmentDuration=6,this._hlsElementGenerated=!1,this._wallOffset=NaN,this._lastDurationUpdate=0,this._manifestLoadTimeout&&(clearTimeout(this._manifestLoadTimeout),this._manifestLoadTimeout=void 0),super._cleanup()}addSource(){di("[addSource]"),this._view.controls=!0,this._view.classList.add("red5pro-media");this._view.hasAttribute("controls")&&this._view.classList.contains("red5pro-media")&&(this._container=this._determineContainer(this._view));const e=this._view.hasAttribute("muted");this._usePlaybackControls?(this._playbackControls=new Zt(this,this._container),this._view.controls=!1,this._playbackControls.setAsVOD(this.isSeekable),this._playbackControls.setMutedState(e)):this._view.controls=!1}enableLiveSeek(e,t,i,n=!1){if(this.getControls()&&this.getControls().setSeekTime(1,1),this._url=e,this._subscriptionId=t,this._hlsElement=i||this._generateHLSLivePlayback(this._container,this._view,t),this._showHLSLivePlayback(this._isHLSPlaybackActive,this._hlsElement,this._view,this._container),n){this._addSeekableHandlers(this._hlsElement,void 0,!1);const t=si("source");t.src=e,this._hlsElement.appendChild(t),this._loadManifest(e,this._hlsElement)}else{const t=this._hlsOptions,{liveSeek:{hlsjsRef:i}}=this._liveSeekConfig,n=i?new i(t):ai(t);this._addSeekableHandlers(this._hlsElement,n,!0),n.attachMedia(this._hlsElement,e),n.on(ri().MEDIA_ATTACHED,(()=>{n.loadSource(e)})),this._hlsjsRef=n}}switchLiveSeek(e){this._hlsjsRef&&(this._hlsjsRef.destroy(),this._hlsjsRef=void 0),this.enableLiveSeek(e,this._subscriptionId,this._hlsElement),this.seekTo(1);try{this._view.play()}catch(e){ci("[videoelement:action] play (FAULT) - "+e.message)}this._url=e}async play(e=!1){di("[videoelement:action] play");try{return e&&this._hlsElement&&this._hlsElement.paused?(await this._hlsElement.play(),!0):super.play()}catch(e){ci("[videoelement:action] play (CATCH::FAULT) - "+e.message)}return!1}async pause(e=!1,t=!1){di("[videoelement:action] pause");try{return e&&t&&this._hlsElement?(this._hlsElement.pause(),super.pause()):e&&this._hlsElement&&!this._hlsElement.paused?(this._hlsElement.pause(),!0):super.pause()}catch(e){ci("[videoelement:action] pause (CATCH::FAULT) - "+e.message)}return!1}async resume(e=!1){var t,i;di("[videoelement:action] resume");try{const n=this._isHLSPlaybackActive&&this._hlsElement?this._hlsElement.play():null===(t=this._view)||void 0===t?void 0:t.play();if(e&&this._isHLSPlaybackActive)return await(null===(i=this._view)||void 0===i?void 0:i.play()),!0;n&&n.then((()=>di("[videoelement:action] play (START)"))).catch((e=>ci("[videoelement:action] play (CATCH::FAULT) "+(e.message?e.message:e))))}catch(e){ci("[videoelement:action] resume (CATCH::FAULT) - "+e.message)}return!1}async stop(){di("[videoelement:action] stop");try{return this._hlsElement&&this._hlsElement.pause(),super.stop()}catch(e){ci("[videoelement:action] stop (CATCH::FAULT) - "+e.message)}return!1}mute(){this._hlsElement&&(this._hlsElement.muted=this._isHLSPlaybackActive),this._view&&(this._view.muted=!0);const e=this.getControls();e&&e.setMutedState(!0)}unmute(){this._hlsElement&&(this._hlsElement.muted=!this._isHLSPlaybackActive,this._view&&(this._view.muted=this._isHLSPlaybackActive)),this._view&&(this._view.muted=!1);const e=this.getControls();e&&e.setMutedState(!1)}setVolume(e){this.unmute(),this._hlsElement&&this._isHLSPlaybackActive?this._hlsElement.volume=e:this._view?this._view.volume=e:hi("[videoelement:action] setVolume (CATCH::FAULT) - "+e)}seekTo(e,t=void 0){if(this.isSeekable)if(this.getControls()&&this.getControls().setSeekTime(e,t),this.trigger(new Se(ni.LIVE_SEEK_CHANGE,void 0,{seek:e,duration:t})),this._hlsElement&&e<1)try{this._hlsElement.classList.remove("hidden"),this._hlsElement.currentTime=this._hlsElement.duration*e,this._isFragLoading=!0,this._showHLSLivePlayback(!0,this._hlsElement,this._view,this._container),this._view.paused||(di("[hlsvod:action] play (START) - (seekTo)"),this.play(!0))}catch(e){ci("[hlsvod:action] play (CATCH::FAULT) - "+e.message)}else this._hlsElement&&e>=1&&(this._isFragLoading=!1,this._showHLSLivePlayback(!1,this._hlsElement,this._view,this._container));else this._view.currentTime=t?e*t:e}toggleFullScreen(e){var t;this._container&&super.toggleFullScreen(null!==(t=this._container)&&void 0!==t?t:e)}getControls(){return this._playbackControls}get isSeekable(){return this._isSeekable}set isSeekable(e){this._isSeekable=e,this.getControls()&&this.getControls().setAsVOD(e)}get isHLSPlaybackActive(){return this._isHLSPlaybackActive}get url(){return this._url}}const{supportsHLS:_i,supportsNonNativeHLS:pi}=ie,mi="WHEPLiveSeekClient",gi=e=>k(mi,e);class vi extends Nt{constructor(e,t,i){super(e,t,i)}async init(e){const{liveSeek:t}=e;return t||(e.liveSeek=Ht),super.init(e)}_attachSourceHandler(e){var t;if((null===(t=this._playbackView)||void 0===t?void 0:t.view)&&!this._enableLiveSeek(this._playbackView.view))return H(mi,"LiveSeek is not enabled, using default source handler"),void super._attachSourceHandler(e);this._startSeekableIfSeekableEnabled(this._options)}_enableLiveSeek(e){const{liveSeek:t}=this._options;if(t){const{hlsjsRef:i,usePlaybackControlsUI:n,options:s}=t;if(_i()||pi(i))return this._sourceHandler=new ui(e,this.getType(),this._options,s,n),this._sourceHandler.addSource(),!0;gi("Could not utilize the 'LiveSeek' request. This feature requires either native HLS playback or hls.js as a depenency."),this.trigger(new Se(ni.LIVE_SEEK_UNSUPPORTED,this,{feature:"Live Seek",message:"Live Seek requires integration with the HLS.JS plugin in order work properly. Most likely you are viewing this on a browser that does not support the use of HLS.JS."}))}return!1}_startSeekableIfSeekableEnabled(e){const{liveSeek:t,subscriptionId:i}=e;if(!t)return;const{hlsjsRef:n,hlsElement:s}=t;if(this._sourceHandler)try{if(!_i()&&!pi(n))throw new Error;{const t=ne(e);this._sourceHandler.enableLiveSeek(t,i,s,!pi(n))}}catch(e){gi("Could not utilize the 'LiveSeek' request. This feature requires either native HLS playback or hls.js as a depenency.")}}_onUnpublish(){super._onUnpublish();const{liveSeek:e}=this._options;e||this.unsubscribe(!0)}_onStreamSwitchComplete(){const e=this._requestedStreamSwitch,{liveSeek:t}=this._options;if(t&&e){const{baseURL:i,fullURL:n}=t,s=e.split("/"),o=s.pop(),a=s.join("/"),r={...this._options,app:a,streamName:o};let l=n;if(n){const e=/.*\/(.*)\.m3u8/.exec(n);if(e&&e.length>1){const t=`${e[1]}.m3u8`;l=n.replace(t,`${o}.m3u8`)}}const d=ne(r,i,l);this._sourceHandler&&this._sourceHandler.switchLiveSeek(d)}super._onStreamSwitchComplete()}}const Ei="15.2.0";R(P.ERROR);const Si=(e,t=!1)=>{Object.prototype.hasOwnProperty.call(P,e.toUpperCase())&&(R(e,t),console&&console.log(`Red5 Pro SDK Version ${Ci()}`))},Ci=()=>Ei;O("RED5",`Red5 Pro HTML SDK Version: ${Ei}`);var fi={version:Ei,LOG_LEVELS:P,getLogger:D,getRecordedLogs:I,setLogLevel:Si,getVersion:Ci,PlaybackVideoEncoder:t,PlaybackAudioEncoder:e,PlaybackState:i,PlaybackStateReadableMap:s,PublishVideoEncoder:l,PublishAudioEncoder:r,SubscriberEvent:Se,PublisherEvent:Ee,MessageTransportStateEvent:Ce,PublisherEventTypes:fe,SubscriberEventTypes:be,RTCPublisherEventTypes:Te,RTCSubscriberEventTypes:Ae,MessageTransportStateEventTypes:we,WHIPClient:dt,WHEPClient:Nt,HLSSubscriber:Ot,LiveSeekClient:vi,defaultWhepSubscriberConfig:ht,defaultWhipPublisherConfig:me};export{ve as Event,U as EventEmitter,Ot as HLSSubscriber,P as LOG_LEVELS,vi as LiveSeekClient,Ce as MessageTransportStateEvent,we as MessageTransportStateEventTypes,e as PlaybackAudioEncoder,Et as PlaybackController,Mt as PlaybackControls,i as PlaybackState,s as PlaybackStateReadableMap,t as PlaybackVideoEncoder,r as PublishAudioEncoder,l as PublishVideoEncoder,Ee as PublisherEvent,fe as PublisherEventTypes,Te as RTCPublisherEventTypes,Ae as RTCSubscriberEventTypes,St as SourceHandler,Tt as SourceHandlerImpl,Se as SubscriberEvent,be as SubscriberEventTypes,Nt as WHEPClient,dt as WHIPClient,fi as default,ct as defaultHLSSubscriberConfig,kt as defaultLiveSeekConfig,_e as defaultStatsConfig,ht as defaultWhepSubscriberConfig,me as defaultWhipPublisherConfig,D as getLogger,I as getRecordedLogs,Ci as getVersion,Si as setLogLevel};
diff --git a/static/lib/red5pro/red5pro-sdk.min.js b/static/lib/red5pro/red5pro-sdk.min.js
index ef936e79..16635c93 100644
--- a/static/lib/red5pro/red5pro-sdk.min.js
+++ b/static/lib/red5pro/red5pro-sdk.min.js
@@ -1,8 +1,8 @@
/**
*
- * red5pro-html-sdk-ts - Red5 Pro HTML SDK - TypeScript Edition
+ * red5pro-html-sdk - Red5 Pro HTML SDK
* Author: Infrared5 Inc.
- * Version: NEW-15.0.0.11-release.b189
+ * Version: 15.2.0
* Url: https://www.red5.net
*
* Copyright © 2015 Infrared5, Inc. All rights reserved.
@@ -31,4 +31,4 @@
*
*/
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).red5prosdk={})}(this,function(e){"use strict";var t,i,n,s;e.PlaybackAudioEncoder=void 0,(t=e.PlaybackAudioEncoder||(e.PlaybackAudioEncoder={})).OPUS="OPUS",t.NONE="NONE",e.PlaybackVideoEncoder=void 0,(i=e.PlaybackVideoEncoder||(e.PlaybackVideoEncoder={})).VP8="VP8",i.H264="H264",i.H265="H265",i.NONE="NONE",e.PlaybackState=void 0,(n=e.PlaybackState||(e.PlaybackState={}))[n.UNAVAILABLE=1e3]="UNAVAILABLE",n[n.AVAILABLE=0]="AVAILABLE",n[n.IDLE=1]="IDLE",n[n.PLAYING=2]="PLAYING",n[n.PAUSED=3]="PAUSED",function(e){e.UNAVAILABLE="Playback.UNAVAILABLE",e.AVAILABLE="Playback.AVAILABLE",e.IDLE="Playback.IDLE",e.PLAYING="Playback.PLAYING",e.PAUSED="Playback.PAUSED"}(s||(s={}));const o={[e.PlaybackState.UNAVAILABLE]:s.UNAVAILABLE,[e.PlaybackState.AVAILABLE]:s.AVAILABLE,[e.PlaybackState.IDLE]:s.IDLE,[e.PlaybackState.PLAYING]:s.PLAYING,[e.PlaybackState.PAUSED]:s.PAUSED};var r,a,l;!function(e){e.RTMP="rtmp",e.RTC="rtc"}(r||(r={})),function(e){e.LIVE="live",e.RECORD="record",e.APPEND="append"}(a||(a={})),e.PublishAudioEncoder=void 0,(e.PublishAudioEncoder||(e.PublishAudioEncoder={})).OPUS="OPUS",e.PublishVideoEncoder=void 0,(l=e.PublishVideoEncoder||(e.PublishVideoEncoder={})).VP8="VP8",l.H264="H264",l.H265="H265";var d={trace:10,debug:20,info:30,warn:40,error:50,fatal:60},h={};function c(e){return"string"==typeof e?d[e.toLowerCase()]:e}function u(e,t){return u=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},u(e,t)}function p(e,t,i){return p=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}()?Reflect.construct:function(e,t,i){var n=[null];n.push.apply(n,t);var s=new(Function.bind.apply(e,n));return i&&u(s,i.prototype),s},p.apply(null,arguments)}function _(e){if(null==e)return e;if(Array.isArray(e))return e.slice();if("object"==typeof e){var t={};return Object.keys(e).forEach(function(i){t[i]=e[i]}),t}return e}function m(e){return void 0===e?"undefined":null===e?"null":Array.isArray(e)?"[ "+e.map(function(e){return m(e)}).join(", ")+" ]":"object"==typeof e?JSON.stringify(e):"function"==typeof e?"[Function: "+e.name+"]":"boolean"==typeof e||"number"==typeof e?e:"'"+e.toString()+"'"}function g(e){if("string"!=typeof e){for(var t=new Array(arguments.length),i=0;i=o)return e;switch(e){case"%s":return String(s[n++]);case"%d":return Number(s[n++]);case"%j":try{return JSON.stringify(s[n++])}catch(e){return"[Circular]"}default:return e}}),a=s[n];ne||(s=function(s){var o;s[0]instanceof Error?(i={err:t.serializers&&t.serializers.err?t.serializers.err(s[0]):T.err(s[0])},o={err:!0},n=1===s.length?[i.err.message]:Array.prototype.slice.call(s,1)):"object"!=typeof s[0]&&null!==s[0]||Array.isArray(s[0])?(i=null,n=Array.prototype.slice.call(s)):(i=s[0],n=1===s.length&&i.err&&i.err instanceof Error?[i.err.message]:Array.prototype.slice.call(s,1));var r=_(t.fields);r.level=e;var a=i?_(i):null;if(a&&(t.serializers&&t._applySerializers(a,o),Object.keys(a).forEach(function(e){r[e]=a[e]})),r.levelName=h[e],r.msg=n.length?g.apply(t,n):"",r.time||(r.time=new Date),t.src&&!r.src)try{throw new Error("call-stack-error")}catch(e){var l=e.stack?function(e,t){var i=e.split("\n");i[0]&&i[0].indexOf("call-stack-error")>=0&&i.shift();var n=i[t],s=null;if(n){var o=/^\s*(at|.*@)\s*(.+)?$/.exec(n);s=Array.isArray(o)&&o[2]?o[2]:n}return s}(e.stack,2):"";l||function(e){return v[e]}("src")||E("Unable to determine src line info","src"),r.src=l||""}return r.v=1,r}(n),this._emit(s))}}function f(e){var t=e.stack||e.toString();if(e.cause&&"function"==typeof e.cause){var i=e.cause();i&&(t+="\nCaused by: "+f(i))}return t}C.prototype.trace=b(10),C.prototype.debug=b(20),C.prototype.info=b(30),C.prototype.warn=b(40),C.prototype.error=b(50),C.prototype.fatal=b(60);var T={err:function(e){return e&&e.stack?{message:e.message,name:e.name,stack:f(e),code:e.code,signal:e.signal}:e}};const y={10:"TRACE",20:"DEBUG",30:"INFO",40:"WARN",50:"ERROR",60:"FATAL"};class w{write(e){console.log("%s - [%s] %s: %s",e.time.toISOString(),e.name,y[e.level]||"UNKNOWN",e.msg)}}let A,P;const L=e=>(t,i)=>{var n;A&&"function"==typeof A[e]&&A[e]((n=t,e=>`(${n}) ${e}`)(i))},N={TRACE:"trace",INFO:"info",DEBUG:"debug",WARN:"warn",ERROR:"error",FATAL:"fatal"},R=(e,t=!1,i)=>{const n=[{level:e,stream:new w,type:"raw"}];if(i){const t=i.map(t=>({...t,level:e}));n.push(...t)}t&&(P=[],n.push({level:e,stream:{write:t=>{const i=`[${t.time.toISOString()}] ${e.toUpperCase()}: ${t.msg}`;null==P||P.push(i)}},type:"raw"}));A=function(){return p(C,[].slice.call(arguments))}({level:e,name:"red5pro-sdk",streams:n})},D=()=>(A||R(N.INFO),A),H=()=>P||[];L(N.TRACE),L(N.INFO);const k=L(N.DEBUG),I=L(N.WARN),O=L(N.ERROR);L(N.FATAL);const M="RED5PRO";class U{constructor(){this._callbacks={},this._callbacks[M]=[]}_notify(e,t){let i;const n=e.length;for(i=0;i1&&(s=V.exec(e),n[1]===t&&s&&s.length>1)?s[1]:void 0}}function W(e){const t=G(e,"orientation");if(t)return{orientation:parseInt(t)}}function x(e){const t=G(e,"streamingMode");if(t)return{streamingMode:t}}const j=e=>F.get(e),K=e=>{const t=e.textTracks;t&&(e.addTextTrack("metadata"),t.addEventListener("addtrack",t=>{const i=t.track;i.mode="hidden",i.addEventListener("cuechange",t=>{let n,s;for(t&&t.currentTarget?n=t.currentTarget.cues:(n=i.cues,n=n&&n.length>0?n:i.activeCues),n=n||[],s=0;s{e(n)}),s&&o&&o.streamingMode&&o.streamingMode.forEach(e=>{e(s)})}}})}))},z="BrowserEnvironment",J=e=>k(z,e),Y=e=>I(z,e);let q=[];const Q=()=>{const e=screen.orientation?screen.orientation.angle:void 0,t=void 0===e?window.matchMedia("(orientation: portrait)").matches?0:90:e,i=q.length;J(`[window:onorientationchange]: orientation(${t}).`);for(let e=0;e{const e=document.createElement("video");return e.canPlayType("application/vnd.apple.mpegURL").length>0||e.canPlayType("application/x-mpegURL").length>0||e.canPlayType("audio/mpegurl").length>0||e.canPlayType("audio/x-mpegurl").length>0},te="undefined"!=typeof window&&window.adapter;var ie={gUM:async e=>navigator.mediaDevices.getUserMedia(e),createElement:e=>document.createElement(e),resolveElement:e=>document.getElementById(e),getElementId:e=>e.id,setVideoSource:(e,t,i)=>{if(e.srcObject=t,i)try{const t=e.play();t&&t.then(()=>J("[setVideoSource:action]: play (START)")).catch(t=>{Y(`[setVideoSource:action]: play (CATCH::FAULT) ${t.message}`);try{e.setAttribute("autoplay","false"),e.pause()}catch(e){Y(`[setVideoSource:action]: pause (CATCH::FAULT) ${e.message}`)}})}catch(e){Y(`[setVideoSource:action]: play (CATCH::FAULT) ${e.message}`)}},hasAttributeDefined:(e,t)=>e.hasAttribute(t),addOrientationChangeHandler:(e,t=!0)=>{"onorientationchange"in window&&(J("[window:orientation:addOrientationChangeHandler]: add"),q.push(e),t&&Q()),1===q.length&&(J("[window:orientation:addOrientationChangeHandler]: add"),window.addEventListener("orientationchange",Q))},removeOrientationChangeHandler:e=>{q=q.filter(t=>t!==e),0===q.length&&window.removeEventListener("orientationchange",Q)},toggleFullScreen:e=>{window.screenfull&&window.screenfull.enabled?window.screenfull.toggle(e):document.fullscreenEnabled&&(document.fullscreenElement&&document.fullscreenElement===e?document.exitFullscreen():e.requestFullscreen())},onFullScreenStateChange:e=>{var t;Z.push(e),t=window.screenfull,X||(X=!0,window.screenfull?window.screenfull.on("change",()=>{Z.forEach(e=>e(t.isFullscreen))}):document.fullscreenEnabled&&document.addEventListener("fullscreenchange",()=>{Z.forEach(e=>e(null!==document.fullscreenElement))}))},getOrGenerateFingerprint:()=>{const e=window.localStorage;if(e&&e.getItem("red5_fingerprint"))return e.getItem("red5_fingerprint");let t;try{t=window.crypto.randomUUID()}catch(e){t="10000000-1000-4000-8000-100000000000".replace(/[018]/g,e=>(Number(e)^crypto.getRandomValues(new Uint8Array(1))[0]&15>>Number(e)/4).toString(16))}return e.setItem("red5_fingerprint",t),t},getBrowserDetails:()=>{const e=void 0!==window.adapter,{navigator:t,adapter:i}=window,{appVersion:n,platform:s,userAgent:o,vendor:r}=t,a={appVersion:n,platform:s,userAgent:o,vendor:r};return e?{...i.browserDetails,...a}:a},supportsHLS:ee,onOrientationMetadata:(e,t)=>{const i=F.get(e);F.has(e)?Object.prototype.hasOwnProperty.call(i,"orientation")||(F.get(e).orientation=[]):(K(e),F.set(e,{orientation:[]})),F.get(e).orientation.push(t)},onStreamingModeMetadata:(e,t)=>{const i=F.get(e);F.has(e)?Object.prototype.hasOwnProperty.call(i,"streamingMode")||(F.get(e).streamingMode=[]):(K(e),F.set(e,{streamingMode:[]})),F.get(e).streamingMode.push(t)},isTouchEnabled:()=>"ontouchstart"in window,isPossiblySafari:()=>te?"safari"===window.adapter.browserDetails.browser.toLowerCase():ee(),findByQuerySelector:e=>document.querySelector(e),addGlobalEventListener:(e,t,i=document)=>{i.addEventListener(e,t)},removeGlobalEventListener:(e,t,i=document)=>{i.removeEventListener(e,t)},supportsNonNativeHLS:e=>{if(e)try{return e.isSupported()}catch(e){return Y("Could not access Hls.js."),!1}return!!window.Hls&&window.Hls.isSupported()},createHLSClient:(e={})=>new window.Hls(e),getHLSClientEventEnum:()=>window.Hls.Events,globalAssign:(e,t)=>{window[e]=t},globalUnassign:e=>{delete window[e]},getAssignedValue:e=>window[e]};const ne=(e,t,i)=>{const{liveSeek:{baseURL:n,fullURL:s}}=e,{host:o,protocol:r,port:a,app:l,streamName:d}=e;if(i||s)return i||s;const h=o,c="ws"===r?"http":"https",u=5080===a?5080:443,p=l,_=t||n;if(_){const e=_.length-1;return`${"/"===_.charAt(e)?_.substring(0,e):_}/${p}/${d}.m3u8`}return`${c}://${h}:${u}/${p}/${d}.m3u8`},se=e=>{const t=new URL(e),i=t.pathname.split("/").filter(e=>e.length>0),n="https:"===t.protocol?"https":"http",s=t.hostname;return{protocol:n,port:t.port.length>0?t.port:443,app:i[0],host:s,streamName:i[i.length-1]}},oe=(e,t="whip")=>{var i;const{endpoint:n,proxy:s}=e;if(n)return n;{const{protocol:n,host:o,port:r,app:a,streamName:l}=e,d=n.match(/^http/)?n:"ws"===n?"http":"https";return(null==s?void 0:s.enabled)?`${d}://${o}:${r}/as/${null!==(i=s.version)&&void 0!==i?i:"v1"}/proxy/${t}/${a}/${l}`:`${d}://${o}:${r}/${a}/${t}/endpoint/${l}`}},re=e=>{const t={audio:!1,video:!1},i={audio:!1,video:!1};return e.getTracks().forEach(e=>{"video"===e.kind?(i.video=e.getSettings(),t.video=e.getConstraints()):"audio"===e.kind&&(i.audio=e.getSettings(),t.audio=e.getConstraints())}),{requested:t,accepted:i}},ae=e=>{const t=e.length;return function i(...n){return n.length>=t?e(...n):function(...e){return i(...n,...e)}}},le=ae((e,t)=>{let i=0;const n=t.length,s=[];for(;i{this._responder.onDataChannelError(t,e.error.message)},t.onmessage=e=>{this._onDataChannelMessage(e)},t.onopen=()=>{this._responder.onDataChannelOpen(t)},t.onclose=i=>{this._responder.onDataChannelClose(t),this.trigger(new Ee(e.MessageTransportStateEventTypes.CLOSE,this._name,{socket:this,event:i}))}}_isErrorMessage(e){return!("error"!==(null==e?void 0:e.type)||!(null==e?void 0:e.message)&&!(null==e?void 0:e.code))}_isStatusMessage(e){return!("status"!==(null==e?void 0:e.type))}_onDataChannelMessage(e){if(this.handleMessageResponse(e))return!0;const t=this.getJsonFromSocketMessage(e);return t?(k(this._name,`[datachannel-response]: ${JSON.stringify(t,null,2)}`),this._handleMessageContent(t)):(I(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0)}_handleMessageContent(e){const{async:t,data:i,method:n,send:s,type:o,id:r}=e;if(this._isErrorMessage(i)){const e=(null==i?void 0:i.message)||(null==i?void 0:i.code);if(e)return this._responder.onDataChannelError(this._dataChannel,e),!0}if(n)return this._responder.onSendReceived(n,i),!0;if(s){const{senderName:t,dcLabel:i}=e,{data:n,method:o}=s,r={...n,senderName:t,dcLabel:i};return this._responder.onSendReceived(o,r),!0}return"metadata"===o&&i?(this._responder.onMetaData(i),!0):this._isStatusMessage(i)&&"NetConnection.Connect.Closed"===(null==i?void 0:i.code)?(this._responder.onConnectionClosed(),!0):!(!t||!r)&&this._handleAsyncResponse(r,e)}_handleAsyncResponse(e,t){const i=this._asyncTickets.find(t=>t.id===e);if(!i)return!1;const{promise:n}=i,{data:s}=t;if("error"===(null==s?void 0:s.type)){const e=s.message||s.code||"Unknown error";n.reject(new Error(e))}else n.resolve(s);return this._asyncTickets=this._asyncTickets.filter(t=>t.id!==e),!0}async setUpWithPeerConfiguration(e,t){this.tearDown();try{k(this._name,`[peerconnection:setUpWithPeerConfiguration]: ${JSON.stringify(e,null,2)}`);const i=new RTCPeerConnection(e);return t&&(this._dataChannel=i.createDataChannel(t.name,{ordered:!0}),this._addDataChannelHandlers(this._dataChannel)),this._addConnectionHandlers(i),this._peerConnection=i,i}catch(e){throw I(this._name,`Could not establish a PeerConnection. ${e.message}`),new Error(e.message)}}tearDown(){if(this._dataChannel){k(this._name,"[teardown:datachannel]"),this._removeDataChannelHandlers(this._dataChannel);try{this._dataChannel.close()}catch(e){I(this._name,`[datachannel.close] error: ${e.message}`)}finally{this._dataChannel=void 0}}if(this._peerConnection){k(this._name,"[teardown:peerconnection]"),this._removeConnectionHandlers(this._peerConnection);try{this._peerConnection.close()}catch(e){I(this._name,`[peerconnection.close] error: ${e.message}`)}finally{this._peerConnection=void 0}}}async setLocalDescription(e){var t;return k(this._name,"[setlocaldescription]"),null===(t=this._peerConnection)||void 0===t?void 0:t.setLocalDescription(e)}async setRemoteDescription(e){var t;return k(this._name,"[setremotedescription]"),null===(t=this._peerConnection)||void 0===t?void 0:t.setRemoteDescription(new RTCSessionDescription(e))}async addIceCandidate(e){var t;return k(this._name,"[addcandidate]"),null===(t=this._peerConnection)||void 0===t?void 0:t.addIceCandidate(e)}async waitToGatherIce(e=5e3){const t=this._peerConnection;return k(this._name,"[waittogatherice]"),new Promise(i=>{if("complete"===t.iceGatheringState)k(this._name,"[waittogatherice] ice gathering state complete."),t.addIceCandidate(null).then(()=>{i(t.localDescription)}).catch(e=>{I(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)});else{k(this._name,"[waittogatherice] waiting...");const n=setTimeout(()=>{clearTimeout(n),t.addIceCandidate(null).then(()=>{i(t.localDescription)}).catch(e=>{I(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)})},e);t.onicegatheringstatechange=()=>{clearTimeout(n),k(this._name,"[waittogatherice] ice gathering state complete."),"complete"===t.iceGatheringState&&t.addIceCandidate(null).then(()=>{i(t.localDescription)}).catch(e=>{I(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)})}}})}post(e){if(this._dataChannel){const t="string"==typeof e?e:JSON.stringify(e,null,2);k(this._name,`[datachannel.send] message: ${t}`);try{return this._dataChannel.send(t),Promise.resolve(!0)}catch(e){O(this._name,e.message)}}return Promise.resolve(!1)}get connection(){return this._peerConnection}get dataChannel(){return this._dataChannel}}const we=[{label:"4K(UHD)",width:3840,height:2160},{label:"1080p(FHD)",width:1920,height:1080},{label:"UXGA",width:1600,height:1200},{label:"720p(HD)",width:1280,height:720},{label:"SVGA",width:800,height:600},{label:"VGA",width:640,height:480},{label:"360p(nHD)",width:640,height:360},{label:"CIF",width:352,height:288},{label:"QVGA",width:320,height:240},{label:"QCIF",width:176,height:144},{label:"QQVGA",width:160,height:120}],Ae=e=>"number"==typeof e?e:e.exact||e.ideal||e.max||e.min||e,Pe=ae((e,t)=>{var i,n;if("boolean"==typeof e.video)return!0;const s=(null===(i=e.video)||void 0===i?void 0:i.width)?Ae(e.video.width):0,o=(null===(n=e.video)||void 0===n?void 0:n.height)?Ae(e.video.height):0,r=s===t.width&&o===t.height;return r&&k("[gum:isExact]",`Found matching resolution for ${t.width}, ${t.height}.`),r}),Le=ae((e,t)=>{const i=le(Pe(t))(e);return k("[gum:hasMatchingFormat]","Filtered list: "+JSON.stringify(i,null,2)),i.length>0}),Ne=ae((e,t)=>{var i,n;if("boolean"==typeof e.video)return!0;const s=((null===(i=e.video)||void 0===i?void 0:i.width)?Ae(e.video.width):0)*((null===(n=e.video)||void 0===n?void 0:n.height)?Ae(e.video.height):0);return t.width*t.height{const i=Ne(t);return le(i)(e)}),De=async e=>{k("[gum:determineSupportedResolution]","Determine next neighbor based on constraints: "+JSON.stringify(e,null,2));const t=Re(we)(e),i={...e};return await(async(e,t)=>{let i={...e};if(0==t.length)i.video;else{const n=t.shift();i={...e,video:{...e.video,width:{exact:n.width},height:{exact:n.height}}}}return{media:await ie.gUM(i),constraints:i}})(i,t)},He=async e=>{let t;const i=Le(we),n=async t=>{if(t){const e="string"==typeof t?t:[t.name,t.message].join(": ");k("[gum:getUserMedia]",`Failure in getUserMedia: ${e}. Attempting other resolution tests...`)}return await De(e)};if((e=>e.video&&"object"==typeof e.video&&(e.video.width||e.video.height))(e)){if(!i(e))return await n(void 0);{k("[gum:getUserMedia]","Found constraints in list. Checking quick support for faster setup with: "+JSON.stringify(e,null,2));const i=(e=>{var t,i;const n={...e};return"boolean"==typeof e.video||(n.video={...n.video},(null===(t=e.video)||void 0===t?void 0:t.width)&&(n.video.width={exact:Ae(e.video.width)}),(null===(i=e.video)||void 0===i?void 0:i.height)&&(n.video.height={exact:Ae(e.video.height)})),n})(e);try{return t=await ie.gUM(i),{media:t,constraints:i}}catch(e){return await n(e)}}}else try{return t=await ie.gUM(e),{media:t,constraints:e}}catch(e){return await n(e)}},ke=(e,t,i)=>{const n="a=end-of-candidates",s=/^a=candidate:/,o=/^a=ice-ufrag:/,r=/^a=ice-pwd:/,a=/^m=(audio|video|application)\ /,l=e.split("\r\n");let d,h="",c="";const u=[];l.forEach(e=>{!d&&a.exec(e)?d=e:o.exec(e)?h=e:r.exec(e)?c=e:s.exec(e)&&(t&&-1!=e.indexOf(t)?u.push(e):t||u.push(e))}),i&&u[u.length-1]!==n&&u.push(n);return[h,c,d,"a=mid:0"].concat(u).join("\r\n")},Ie="RTCPeerConnectionPublisher";class Oe extends ye{constructor(e){super(e,Ie)}_removeConnectionHandlers(e){e.onconnectionstatechange=null,e.oniceconnectionstatechange=null,e.onsignalingstatechange=null,e.onicecandidate=null,e.ontrack=null}_addConnectionHandlers(e){let t;e.onsignalingstatechange=()=>{const t=e.signalingState;k(Ie,`[peer.onsignalingstatechange] - State: ${t}`)},e.onconnectionstatechange=()=>{const{connectionState:t}=e;"connected"===t?(k(this._name,"[peerconnection:open]"),this._responder.onPeerConnectionOpen()):"failed"!==t&&"disconnected"!==t||(I(this._name,"[peerconnection:error]"),"failed"===t&&this._responder.onPeerConnectionFail())},e.oniceconnectionstatechange=i=>{const{iceConnectionState:n}=e;k(this._name,`[peer.oniceconnectionstatechange] - State: ${n}`),"failed"===n?(t&&clearTimeout(t),this._responder.onPeerConnectionClose(i)):"disconnected"===n?t=setTimeout(()=>{k(this._name,"[peer.oniceconnectionstatechange] - Reconnect timeout reached. Closing PeerConnection."),clearTimeout(t),this._responder.onPeerConnectionClose(i)},3e3):t&&(k(this._name,"[peer.oniceconnectionstatechange] - Clearing timeout for reconnect."),clearTimeout(t))},e.onicecandidate=e=>{const{candidate:t}=e;k(this._name,`[peer.onicecandidate] - Peer Candidate: ${null==t?void 0:t.candidate}`),t&&this._responder.onIceCandidate(t)},e.ontrack=e=>{k(this._name,"[peer:ontrack]"),this._responder.onPeerConnectionTrackAdd(e.track)}}_onDataChannelMessage(e){const t=e;if(super._onDataChannelMessage(e))return!0;const i=this.getJsonFromSocketMessage(t);if(null===i)return I(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0;k(this._name,"[datachannel-response]: "+JSON.stringify(i,null,2));const{data:n}=i;return n&&"status"===n.type?"NetStream.Play.UnpublishNotify"===n.code?(this._responder.onUnpublish(),!0):"NetConnection.Publish.InsufficientBW"===n.code?(this._responder.onInsufficientBandwidth(n),!0):"NetConnection.Publish.SufficientBW"===n.code?(this._responder.onSufficientBandwidth(n),!0):"NetConnection.Publish.RecoveringBW"===n.code?(this._responder.onRecoveringBandwidth(n),!0):"Application.Statistics.Endpoint"===n.code?(this._responder.onStatisticsEndpointChange(n.statistics),!0):(k(Ie,`[datachannel.message] status :: ${n.code}`),this._responder.onPublisherStatus(n),!0):(this._responder.onDataChannelMessage(this._dataChannel,t),!1)}addTrack(e){this._peerConnection?this._peerConnection.addTrack(e):I(Ie,"PeerConnection not initialized. Cannot add track.")}async postUnpublish(e){const t=this.post({unpublish:e});return k(Ie,`[peerconnection:unpublish] complete: ${t}`),t}async createOfferWithoutSetLocal(e=null){var t;k(Ie,`[createoffer:withoutlocal]:: bandwidth request: ${JSON.stringify(e,null,2)}`);try{const i=await(null===(t=this._peerConnection)||void 0===t?void 0:t.createOffer());if(e){const t=((e,t)=>{const i=t.indexOf("m=audio");let n,s,o,r=t.indexOf("m=video"),a=t.indexOf("m=application");return i>-1&&e.audio&&(n=t.indexOf("\r\n",i),s=t.slice(0,n),o=t.slice(n+2,t.length),r=(t=[s,"b=AS:"+e.audio,o].join("\r\n")).indexOf("m=video"),a=t.indexOf("m=application")),r>-1&&e.video&&(n=t.indexOf("\r\n",r),s=t.slice(0,n),o=t.slice(n+2,t.length),a=(t=[s,"b=AS:"+e.video,o].join("\r\n")).indexOf("m=application")),a>-1&&e.dataChannel&&(n=t.indexOf("\r\n",a),s=t.slice(0,n),o=t.slice(n+2,t.length),t=[s,"b=AS:"+e.dataChannel,o].join("\r\n")),t})(e,i.sdp);i.sdp=t}return this._responder.onSDPSuccess(),i}catch(e){throw k(Ie,"[createoffer:error]"),this._responder.onSDPError(e),e}}async updateBandwidthRequest(e=null){var t;k(Ie,`[updatebandwidthrequest]:: bandwidth request: ${JSON.stringify(e,null,2)}`);try{const i=null===(t=this._peerConnection)||void 0===t?void 0:t.getSenders();if(e&&(null==i?void 0:i.length)&&i.length>0){const t=(e,t,i)=>new Promise((n,s)=>{try{k(Ie,`[updatebandwidthrequest:${i}]:: bandwidth(${t.encodings[0].maxBitrate})`),e.setParameters(t).then(n).catch(s)}catch(e){s(e)}}),n=[];null==i||i.forEach(async i=>{var s,o;if("video"===(null===(s=i.track)||void 0===s?void 0:s.kind)&&e.video){const e=i.getParameters();e.encodings||(e.encodings=[{}]),e.encodings[0].maxBitrate=75e4,e.encodings[0].maxFramerate=60,e.encodings[0].priority="high",n.push(t(i,e,"video"))}else if("audio"===(null===(o=i.track)||void 0===o?void 0:o.kind)&&e.audio){const e=i.getParameters();e.encodings||(e.encodings=[{}]),e.encodings[0].maxBitrate=128e3,n.push(t(i,e,"audio"))}}),await Promise.all(n).catch(e=>{O(Ie,`[updatebandwidthrequest:error]:: ${e.message}`)})}return!0}catch(e){O(Ie,`[updatebandwidthrequest:error]:: ${e.message}`)}return!1}}class Me extends Error{constructor(e){super(e),this.name="InvalidNameError"}}const Ue="WhipWhepSignalingHelper",Be=new Map;Be.set(400,"Invalid offer SDP."),Be.set(401,"Not authorized."),Be.set(404,"Scope resolver failed for the publish name and / or scope."),Be.set(405,"Remember to update the URL passed into the WHIP or WHEP client."),Be.set(406,"Scope connection rejected."),Be.set(409,"Session already initialized."),Be.set(412,"Invalid request body."),Be.set(417,"Session lookup or creation failure.");const Ve=new Map;Ve.set(400,"Offer already sent, double POST assumed."),Ve.set(401,"Not authorized."),Ve.set(404,"Scope resolver failed for the playback name and / or scope."),Ve.set(406,"Playback failed due to an exception during creation."),Ve.set(409,"Stream is not available to playback.");const Fe=["transcode"];var $e;!function(e){e.ICE_SERVER="ice-server",e.STATISTICS="statistics"}($e||($e={}));const Ge=e=>e&&(e=>{const t=/[?&](.*)=([^]*)/.exec(e);return t&&t.length>0})(e)?"&":"?",We=e=>e.split(";").map(e=>e.trim()).map(e=>"<"===e.charAt(0)?["url",e.substring(1,e.length-1)]:e.split("=")).reduce((e,t)=>e.set(t[0].replaceAll('"',""),t[1].replaceAll('"',"")),new Map);class xe{constructor(e,t=!1,i=!0){k(Ue,`[whipwhep] ${e}`),this._url=e,this._origin=void 0,this._forceHost=i,this._resource=void 0,this._enableSignalingChannel=t}async getOptions(e={}){let t=`${this._url}${Ge(this._url)}signal=${this._enableSignalingChannel}`;e&&Object.keys(e).forEach(i=>{t+=`&${i}=${e[i]}`}),k(Ue,`[whipwhep-options] ${t}`);try{const e=await fetch(t,{method:"OPTIONS",mode:"cors"}),{status:i,headers:n}=e;if(200===i||204===i){const e=/^(L|l)ink/,t=/^(S|s)ession-(H|h)ost/,i=[];let s;return n.forEach((n,o)=>{if(t.exec(o)&&(this._origin=n),e.exec(o))if(n.indexOf(`rel="${$e.ICE_SERVER}"`)>-1){const e=We(n),t=e.get("url"),{protocol:s,host:o}=(e=>{const t=e.split(":");return t.length>1?{protocol:t[0],host:t[1]}:{protocol:void 0,host:e}})(t),r=e.get("username"),a=e.get("credential");s&&o&&r&&a?i.push({username:r,credential:a,urls:t}):t&&i.push({urls:t})}else if(n.indexOf(`rel="${$e.STATISTICS}"`)>-1){const e=We(n).get("url");e&&(s=e)}}),k(Ue,`[whipwhep-links]: ${JSON.stringify(i)}`),k(Ue,`[whipwhep-origin]: ${this._origin}`),{links:i.length>0?i:void 0,origin:this._origin,statisticsEndpoint:s}}throw new Error(`Failed to get options: ${i}`)}catch(e){throw O(Ue,e.message),e}}async postSDPOffer(e,t={},i=!0){let n=`${this._url}${Ge(this._url)}signal=${this._enableSignalingChannel}`;t&&Object.keys(t).forEach(e=>{-1===Fe.indexOf(e)&&(n+=`&${e}=${t[e]}`)}),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n+=`&host=${this._origin}`),k(Ue,`[whipwhep:post-offer] ${n}: `+JSON.stringify(e,null,2));try{const t={method:"POST",mode:"cors",headers:{"Content-Type":"application/sdp"}};e&&e.length>0&&(t.body=e);const s=await fetch(n,t),{status:o,headers:r}=s;if(r&&r.forEach((e,t)=>{k(Ue,`[header] ${t}: ${e}`)}),o>=200&&o<300){const e=await s.text(),t=r.get("Location")||r.get("location");if(t){if(t.match(/^(http|https)/))this._resource=t;else{k(Ue,`[whipwhep-response] Location provided as relative path: ${t}`);const e=new URL(this._url);e.pathname=t.split("?")[0],this._resource=e.toString().replace(/\/endpoint\//,"/resource/")}return k(Ue,`[whipwhep-response] ${this._resource}: ${e}`),{sdp:e,location:this._resource}}return I(Ue,"Location not provided in header response to Offer."),this._resource=new URL(this._url).toString().replace(/\/endpoint\//,"/resource/"),{sdp:e,location:this._resource}}if(i&&Be.get(o)){if(k(Ue,Be.get(o)),404===o||409===o)throw new Me(Be.get(o));throw new Error(Be.get(o))}if(!i&&Ve.get(o)){if(k(Ue,Ve.get(o)),404===o||409===o)throw new Me(Ve.get(o));throw new Error(Ve.get(o))}{const e=await s.text();throw Error(e)}}catch(e){throw O(Ue,e.message),e}}async postSDPAnswer(e,t={}){k(Ue,`[whipwhep:post-answer] ${this._resource}: `+JSON.stringify(e,null,2));let i=this._resource,n=Ge(i);t&&Object.keys(t).forEach(e=>{-1===Fe.indexOf(e)&&(n=Ge(i),i+=`${n}${e}=${t[e]}`)}),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n=i.indexOf("?")>-1?"&":"?",i+=`${n}host=${this._origin}`);try{const t=await fetch(i,{method:"PATCH",mode:"cors",headers:{"Content-Type":"application/sdp"},body:e}),{status:n}=t;if(n>=200&&n<300)return{success:!0,code:n};if(Ve.get(n))throw k(Ue,Ve.get(n)),new Error(Ve.get(n));{const e=await t.text();throw Error(e)}}catch(e){throw O(Ue,e.message),e}}async trickle(e,t={}){k(Ue,`[whipwhep-trickle] ${this._resource}: `+JSON.stringify(e,null,2));let i=this._resource,n=Ge(i);t&&Object.keys(t).forEach(e=>{-1===Fe.indexOf(e)&&(n=Ge(i),i+=`${n}${e}=${t[e]}`)}),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n=Ge(i),i+=`${n}host=${this._origin}`);try{const t=await fetch(i,{method:"PATCH",mode:"cors",headers:{"Content-Type":"application/trickle-ice-sdpfrag"},body:e}),{status:n}=t;if(n>=200&&n<300){const e=await t.text();return k(Ue,`[whipwhep-response] ${this._resource}: ${e}`),{candidate:e}}if(405===n)throw k(Ue,"Remember to update the URL passed into the WHIP or WHEP client"),new Error("Remember to update the URL passed into the WHIP or WHEP client");{const e=await t.text();throw Error(e)}}catch(e){throw O(Ue,e.message),e}}async tearDown(e={},t=!1){if(!this._resource)return;let i=this._resource,n=Ge(i);e&&Object.keys(e).forEach(t=>{-1===Fe.indexOf(t)&&(n=Ge(i),i+=`${n}${t}=${e[t]}`)}),this._forceHost&&this._origin&&!(null==e?void 0:e.host)&&(n=Ge(i),i+=`${n}host=${this._origin}`),k(Ue,"[whipwhep-teardown]");try{await fetch(i,{method:"DELETE",mode:"cors"})}catch(e){if(O(Ue,e.message),!t)throw e}this._url=void 0,this._origin=void 0,this._resource=void 0,this._forceHost=!1,this._enableSignalingChannel=!1}async post(){return k(Ue,"[whipwhep:post] transport called."),Promise.resolve(!1)}async postAsync(){return k(Ue,"[whipwhep:postAsync] transport called."),Promise.resolve(null)}getUrl(){return this._url}}const je="R5ProPublishView";class Ke{constructor(e="red5pro-publisher"){try{this._targetElement=ie.resolveElement(e)}catch(e){throw O(je,`Could not instantiate a new instance of PublishView. Reason: ${e.message}`),e}}preview(e){const t=this.isAutoplay;k(je,`[preview]: autoplay(${t})`),ie.setVideoSource(this._targetElement,e,t)}unpreview(){ie.setVideoSource(this._targetElement,null,this.isAutoplay)}get isAutoplay(){return ie.hasAttributeDefined(this._targetElement,"autoplay")}get view(){return this._targetElement}}const ze={endpoint:null,interval:5e3,include:[]};var Je;!function(e){e.INBOUND="inbound-rtp",e.OUTBOUND="outbound-rtp",e.CODEC="codec",e.MEDIA_SOURCE="media-source",e.CANDIDATE_PAIR="candidate-pair",e.CERTIFICATE="certificate",e.DATA_CHANNEL="data-channel",e.LOCAL_CANDIDATE="local-candidate",e.REMOTE_CANDIDATE="remote-candidate",e.PEER_CONNECTION="peer-connection",e.REMOTE_INBOUND="remote-inbound-rtp",e.REMOTE_OUTBOUND="remote-outbound-rtp",e.TRANSPORT="transport"}(Je||(Je={}));class Ye{constructor(e,t,i){this._name="RTCStatsMonitor",this._queue=[],this._startTime=0,this._stopped=!1,this._interval=0,this._name=e,this._config={...ze,...t},this._client=i,this._identifier={name:this._name,created:(new Date).getTime(),fingerprint:ie.getOrGenerateFingerprint(),device:ie.getBrowserDetails(),client:t}}_emptyStatsReportQueue(){for(;this._queue.length>0;){const e=this._client.getMessageTransport();if(e){const t=this._queue.shift();e.post(t)}else I(this._name,"Failed to post stats data to message transport. Message transport is not available.")}}_getStats(){const{_connection:e}=this;if(e&&"connected"===e.connectionState)try{e.getStats(null).then(e=>{e.forEach(e=>{this._handleStatsReport(e)})}).catch(e=>{O(this._name,`Failed to get stats report. ${e.message||e}`)})}catch(e){O(this._name,`Failed to get stats report. ${e.message||e}`)}}_handleStatsReport(e){console.log(`[${this._name}]: ${JSON.stringify(e,null,2)}`)}_appendClientDetails(e){this._identifier.client={...this._identifier.client,...e}}async start(e){this._startTime=(new Date).getTime(),this._stopped=!1,this._connection=e,this.postAction("started"),this._getStats(),this._interval=setInterval(()=>{this._stopped||this._getStats()},this._config.interval)}stop(){this._stopped=!0,clearInterval(this._interval),this.postAction("ended")}async post(t){const i={...this._identifier,type:"stats-report",timestamp:(new Date).getTime(),data:t},{endpoint:n,additionalHeaders:s}=this._config;if(this._client&&this._client.onStatsReport&&null===n)return void this._client.onStatsReport(this._connection,i);let o={"Content-Type":"application/json"};if(s&&(o={...o,...s}),n)try{const e=await fetch(n,{method:"POST",headers:o,body:JSON.stringify(i)});e.status>=200&&e.status<300?k(this._name,`Posted stats data to endpoint: ${n}.`):O(this._name,`Failed to post stats data to endpoint: ${n}. ${e.status}`)}catch(e){O(this._name,`Failed to post stats data to endpoint: ${n}. ${e.message||e}`)}else if(this._client&&this._client.getMessageTransport())try{let t=!1;const n=this._client.getMessageTransport();n&&(t=await n.post(i)),t||(this._queue.push(i),this._client.on(e.MessageTransportStateEventTypes.CHANGE,()=>{this._client.off(e.MessageTransportStateEventTypes.CHANGE),this._emptyStatsReportQueue()}),I(this._name,"Failed to post stats data to message transport. Message transport is not available. Pushed to Queue."))}catch(e){O(this._name,`Failed to post stats data to message transport. ${e.message||e}`)}}async postAction(e,t=void 0){return this.post({action:{type:e,data:t,timestamp:(new Date).getTime()}})}async postEvent(e,t){return this.post({event:{type:e,data:t||void 0,timestamp:(new Date).getTime()}})}updateEndpoint(e,t=!0){const{endpoint:i}=this._config;t?this._config.endpoint=e:t||i||(this._config.endpoint=e)}dispose(){this.stop(),this._connection=void 0,this._client=void 0}}const qe=/(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b) \d+ typ srflx/,Qe=e=>{const t=e.match(qe);return t&&t.length>1?t[1]:null},Xe=[e.PublisherEventTypes.PUBLISH_START,e.PublisherEventTypes.PUBLISH_FAIL,e.PublisherEventTypes.PUBLISH_INSUFFICIENT_BANDWIDTH,e.PublisherEventTypes.PUBLISH_SUFFICIENT_BANDWIDTH,e.PublisherEventTypes.PUBLISH_RECOVERING_BANDWIDTH,e.PublisherEventTypes.STATISTICS_ENDPOINT_CHANGE];class Ze extends Ye{constructor(t,i){if(super("RTCPublisherStats",t,i),this.estimatedAudioBitrate=0,this.estimatedVideoBitrate=0,this.lastAudioReport=null,this.lastVideoReport=null,this._eventHandler=t=>{const{type:i,data:n}=t;if(Xe.indexOf(i)>-1){if(i===e.PublisherEventTypes.STATISTICS_ENDPOINT_CHANGE){const{statisticsEndpoint:e}=n;this.updateEndpoint(e,!1)}this.postEvent(i)}},this._candidateCreateHandler=({data:{candidate:e}})=>{const{candidate:t}=e,i=Qe(t);i&&(this._identifier.publicIP=i)},this._hostEndpointChangedHandler=({data:{endpoint:e,iceServers:t}})=>{this._appendClientDetails({node:e,iceServers:t})},this._client.on("*",this._eventHandler),this._client.on(e.RTCPublisherEventTypes.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.on(e.RTCPublisherEventTypes.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),this._client.getPeerConnection())this.start(this._client.getPeerConnection());else{const t=({data:i})=>{this._client.off(e.RTCPublisherEventTypes.PEER_CONNECTION_AVAILABLE,t),this.start(i)};this._client.on(e.RTCPublisherEventTypes.PEER_CONNECTION_AVAILABLE,t)}}_handleStatsReport(e){const{type:t}=e,{include:i}=this._config,n=i&&i.length>0;if(n&&i.indexOf(t)>=-1)this.post(e);else if(!n)if(t===Je.CODEC){const{id:i,clockRate:n,mimeType:s,payloadType:o}=e;this.post({id:i,type:t,clockRate:n,mimeType:s,payloadType:o})}else if(t===Je.CANDIDATE_PAIR){const{availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o}=e;this.post({type:t,availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o})}else if(t===Je.MEDIA_SOURCE){const{kind:i}=e;if("audio"===i)this.post({type:t,kind:i});else if("video"===i){const{framesPerSecond:n,height:s,width:o}=e;this.post({type:t,kind:i,framesPerSecond:n,height:s,width:o})}}else if([Je.OUTBOUND,"outboundrtp"].indexOf(t)>-1){const{timestamp:i,kind:n,codecId:s,mediaType:o,active:r,bytesSent:a,packetsSent:l,totalPacketsSendDelay:d}=e,h={type:t,kind:n,codecId:s,mediaType:o,active:r,bytesSent:a,packetsSent:l,totalPacketsSendDelay:d};if("audio"===n){if(this.lastAudioReport){const{bytesSent:e,timestamp:t}=this.lastAudioReport,n=8*(a-e)/(i-t);this.estimatedAudioBitrate=n}this.post({...h,estimatedBitrate:Math.floor(this.estimatedAudioBitrate)}),this.lastAudioReport=e}else if("video"===n){const{firCount:t,pliCount:n,frameWidth:s,frameHeight:o,framesEncoded:r,framesPerSecond:l,framesSent:d,keyFramesEncoded:c,qualityLimitationReason:u,qualityLimitationDurations:p}=e;let _={...h,firCount:t,pliCount:n,frameWidth:s,frameHeight:o,framesEncoded:r,framesPerSecond:l,framesSent:d,keyFramesEncoded:c,qualityLimitationReason:"none"!==u?u:void 0,qualityLimitationDurations:"none"!==u?p:void 0};if(this.lastVideoReport){const{bytesSent:e,timestamp:t}=this.lastVideoReport,n=8*(a-e)/(i-t);this.estimatedVideoBitrate=n}this.post({..._,estimatedBitrate:Math.floor(this.estimatedVideoBitrate)}),this.lastVideoReport=e}}}dispose(){this._client.off("*",this._eventHandler),this._client.off(e.RTCPublisherEventTypes.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.off(e.RTCPublisherEventTypes.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),super.dispose()}}const et="WHIPClient",tt=pe,it=e=>k(et,e),nt=e=>O(et,e),st=e=>I(et,e);class ot extends U{constructor(e,t,i){super();const n=e?se(e):tt,s=i||tt,o={...s,...n,endpoint:e,mediaElementId:t?t.id:s.mediaElementId};e&&this.internalInit(o),this._onOrientationChange=this._onOrientationChange.bind(this)}async internalInit(e){await this.init(e),await this.publish()}async generateMediaStream(t){var i,n;const{onGetUserMedia:s}=t;if(s){it("Requesting gUM from user-defined configuration:onGetUserMedia.");const t=await s();return this.trigger(new ge(e.RTCPublisherEventTypes.CONSTRAINTS_ACCEPTED,this,re(t))),t}{const{mediaConstraints:s}=t;let o;it(`Requesting gUM using mediaConstraints: ${JSON.stringify(s,null,2)}`);let r=s;const a=await He(r);return a&&a.media||(o=await ie.gUM(r)),o=null!==(i=null==a?void 0:a.media)&&void 0!==i?i:o,r=null!==(n=null==a?void 0:a.constraints)&&void 0!==n?n:s,it(`Constraints accepted: ${JSON.stringify(r,null,2)}`),this.trigger(new ge(e.RTCPublisherEventTypes.CONSTRAINTS_ACCEPTED,this,{constraints:r,...re(o)})),o}}async getAndPreviewStreamIfAvailable(){var t;let i=this._mediaStream;if(!i){try{i=null!=i?i:await this.generateMediaStream(this._options)}catch(i){const n=null!==(t=i.message)&&void 0!==t?t:"Could not generate media stream.";throw this.trigger(new ge(e.RTCPublisherEventTypes.CONSTRAINTS_REJECTED,this,{constraints:this._options.mediaConstraints})),new Error(n)}if(!i)throw new Error("Could not generate media stream.")}return this.trigger(new ge(e.RTCPublisherEventTypes.MEDIA_STREAM_AVAILABLE,this,i)),this.preview(i),i}reorderCodecPreferences(e,t,i){e.getTransceivers().forEach(e=>{if(e.sender&&e.sender.track){const{kind:n}=e.sender.track;if(t&&"video"===n&&e.setCodecPreferences)try{const{codecs:i}=RTCRtpSender.getCapabilities("video"),n=i.findIndex(e=>e.mimeType===`video/${t}`);if(n>-1){const t=i.slice(0),s=i[n];t.splice(n,1),t.unshift(s),e.setCodecPreferences(t)}}catch(e){st(`[videoEncoding] Could not set codec preferences for ${t}. ${e.message||e}`)}else if(i&&"audio"===n&&e.setCodecPreferences)try{const{codecs:t}=RTCRtpSender.getCapabilities("audio"),n=t.findIndex(e=>e.mimeType===`audio/${i}`);if(n>-1){const i=t[n];t.splice(n,1),t.unshift(i),e.setCodecPreferences(t)}}catch(e){st(`[audioEncoding] Could not set codec preferences for ${i}. ${e.message||e}`)}}})}async postOffer(t){var i;try{const{sdp:n}=t;let{videoEncoding:s}=this._options;const{mungeOffer:o,streamMode:r,keyFramerate:a,iceTransport:l,connectionParams:d,mediaConstraints:h,forceVP8:c,audioEncoding:u,offerSDPResolution:p}=this._options;c&&!s&&(s=e.PublishVideoEncoder.VP8);let _=n;o&&(it(`[MUNGE:before] offer: ${_}`),_=o(_),it(`[MUNGE:after] offer: ${_}`)),p&&(it(`[MUNGE] Setting resolution on offer: ${_}`),_=((e,t)=>{if(!t)return e;const{width:i,height:n}=t;if(!i||!n)return e;const s=`a=framesize:${i}-${n}`,o=e.split("\r\n");let r=o.length;const a=/^m=video/;for(;--r>-1;)if(a.exec(o[r])){for(;++r-1){o.splice(r+1,0,s);break}break}return o.join("\r\n")})(_,((e,t)=>{let i;if(e)try{const t=e.getVideoTracks()&&e.getVideoTracks()[0];if(t){const e=t.getSettings();i={width:e.width,height:e.height}}}catch(e){I("[determineMediaResolution]",`Could not determine resolution from MediaStream. ${e.message||e}`)}if(!i)try{const e=t.video,{width:n,height:s}=e;if(n&&s)if("number"==typeof n&&"number"==typeof s)i={width:n,height:s};else{i={width:n.exact||n.min||n.max||n.ideal||640,height:s.exact||s.min||s.max||s.ideal||480}}}catch(e){I("[determineMediaResolution]",`Could not determine resolution from MediaConstraints. ${e.message||e}`)}return i&&k("[determineMediaResolution]",`constraints: ${JSON.stringify(i,null,2)}`),i})(this._mediaStream,h)),it(`[MUNGE:after] offer: ${_}`));const m={...d,mode:r,transport:l,keyFramerate:a};return s&&(m.videoEncoding=s),u&&(m.audioEncoding=u),await(null===(i=this._whipWhepService)||void 0===i?void 0:i.postSDPOffer(_,m))}catch(t){throw nt(t.message||t),t instanceof Me?this.trigger(new ge(e.PublisherEventTypes.PUBLISH_INVALID_NAME,this)):(this.trigger(new ge(e.PublisherEventTypes.CONNECT_FAILURE,this,t)),this.unpublish()),t}}async postCandidateFragments(e){var t;const{connectionParams:i}=this._options,n=ke(e,void 0,!0);return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.trickle(n,i))}async init(e){var t;this._options={...tt,...e};const i=oe(this._options),{includeDataChannel:n,disableProxy:s}=this._options;return this._whipWhepService=new xe(i,n,s),this._messageTransport=this._whipWhepService,(null===(t=this._options)||void 0===t?void 0:t.stats)&&this.monitorStats(this._options.stats),this._mediaStream=await this.getAndPreviewStreamIfAvailable(),this}async initWithStream(e,t){return this._mediaStream=t,this.init(e)}async publish(t){var i,n,s,o;t&&(this._options.streamName=t);const{forceVP8:r,audioEncoding:a,rtcConfiguration:l,dataChannelConfiguration:d,includeDataChannel:h,signalingSocketOnly:c,enableChannelSignaling:u,connectionParams:p,bandwidth:_,mungeAnswer:m}=this._options;let{videoEncoding:g}=this._options;r&&(g=e.PublishVideoEncoder.VP8,this._options.videoEncoding=g),this._mediaStream||(this._mediaStream=await this.getAndPreviewStreamIfAvailable());try{const t=null!=p?p:{};if(p){const{transcode:e}=p;e&&(t.transcode=e)}const o=await(null===(i=this._whipWhepService)||void 0===i?void 0:i.getOptions(t));(null==o?void 0:o.links)&&(this._options.rtcConfiguration={...l,iceServers:o.links}),(null==o?void 0:o.origin)&&this.trigger(new ge(e.RTCPublisherEventTypes.HOST_ENDPOINT_CHANGED,this,{endpoint:o.origin})),(null==o?void 0:o.statisticsEndpoint)&&this._onStatisticsEndpointChange(o.statisticsEndpoint);const r=h||u||c?d:void 0;this._peerConnectionHelper=new Oe({onDataChannelError:this._onDataChannelError.bind(this),onSendReceived:this._onSendReceived.bind(this),onMetaData:this._onMetaData.bind(this),onConnectionClosed:this._onConnectionClosed.bind(this),onDataChannelOpen:this._onDataChannelOpen.bind(this),onDataChannelClose:this._onDataChannelClose.bind(this),onDataChannelMessage:this._onDataChannelMessage.bind(this),onPeerConnectionOpen:this._onPeerConnectionOpen.bind(this),onPeerConnectionFail:this._onPeerConnectionFail.bind(this),onPeerConnectionClose:this._onPeerConnectionClose.bind(this),onIceCandidate:this._onIceCandidate.bind(this),onSDPSuccess:this._onSDPSuccess.bind(this),onSDPError:this._onSDPError.bind(this),onStatisticsEndpointChange:this._onStatisticsEndpointChange.bind(this),onPublisherStatus:this._onPublisherStatus.bind(this),onPeerConnectionTrackAdd:this._onPeerConnectionTrackAdd.bind(this),onInsufficientBandwidth:this._onInsufficientBandwidth.bind(this),onSufficientBandwidth:this._onSufficientBandwidth.bind(this),onRecoveringBandwidth:this._onRecoveringBandwidth.bind(this),onUnpublish:this._onUnpublish.bind(this)}),await this._peerConnectionHelper.setUpWithPeerConfiguration(this._options.rtcConfiguration,r),this.trigger(new ge(e.RTCPublisherEventTypes.PEER_CONNECTION_AVAILABLE,this,this.getPeerConnection())),this._mediaStream.getTracks().forEach(e=>{var t;null===(t=this.getPeerConnection())||void 0===t||t.addTransceiver(e,{direction:"sendonly"})}),this.reorderCodecPreferences(this.getPeerConnection(),g,a);const v=await(null===(n=this._peerConnectionHelper)||void 0===n?void 0:n.createOfferWithoutSetLocal(_));await this._peerConnectionHelper.setLocalDescription(v),this.trigger(new ge(e.RTCPublisherEventTypes.OFFER_START,this,v));const{sdp:E}=await this.postOffer(v);let S=E;m&&(it(`[MUNGE:before] answer: ${S}`),S=m(S),it(`[MUNGE:after] answer: ${S}`)),await this._peerConnectionHelper.setRemoteDescription({type:"answer",sdp:S}),this.trigger(new ge(e.RTCPublisherEventTypes.OFFER_END,this,S));const C=await this._peerConnectionHelper.waitToGatherIce(),{sdp:b}=C;return await this.postCandidateFragments(b),this.trigger(new ge(e.RTCPublisherEventTypes.ICE_TRICKLE_COMPLETE,this)),ie.addOrientationChangeHandler(this._onOrientationChange),(null===(s=this._options)||void 0===s?void 0:s.includeDataChannel)||this.trigger(new ge(e.PublisherEventTypes.PUBLISH_START,this)),this}catch(t){throw nt(null!==(o=t.message)&&void 0!==o?o:"Could not publish."),this.trigger(new ge(e.PublisherEventTypes.CONNECT_FAILURE,this,t)),this.unpublish(!0),t}}async unpublish(t=!1){var i;it("[unpublish]"),this._peerConnectionHelper&&await this._peerConnectionHelper.tearDown(),this._whipWhepService&&await this._whipWhepService.tearDown(null,t),(null===(i=this._options)||void 0===i?void 0:i.clearMediaOnUnpublish)&&this.unpreview(),this._mediaStream=void 0,this._peerConnectionHelper=void 0,this._whipWhepService=void 0,this._messageTransport=void 0,this._publishView=void 0,this.trigger(new ge(e.PublisherEventTypes.UNPUBLISH_SUCCESS,this)),ie.removeOrientationChangeHandler(this._onOrientationChange)}preview(e){it("[preview]");const{mediaElementId:t}=this._options;t&&(this._publishView=new Ke(t),this._publishView.preview(e))}unpreview(){it("[unpreview]"),this._mediaStream&&this._mediaStream.getTracks().forEach(e=>{e.stop()}),this._publishView&&this._publishView.unpreview(),this._publishView=void 0}monitorStats(e){it("[monitorStats]");const{host:t,endpoint:i,app:n,streamName:s,connectionParams:o}=this._options,r=null!=e?e:ze;return this._statisticsConfiguration={...r,host:t,hostEndpoint:i,app:n,streamName:s,connectionParams:o},this._statsMonitor?st("Cannot monitor stats without a Peer Connection. Please call `init` before calling `monitorStats`."):this._statsMonitor=new Ze(this._statisticsConfiguration,{onStatsReport:this._onStatsReport.bind(this),getPeerConnection:this.getPeerConnection.bind(this),getMessageTransport:this.getMessageTransport.bind(this),on:this.on.bind(this),off:this.off.bind(this),trigger:this.trigger.bind(this)}),this}unmonitorStats(){return this._statsMonitor&&this._statsMonitor.dispose(),this._statsMonitor=void 0,this._statisticsConfiguration=void 0,this}muteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0}})}unmuteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1}})}muteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!0}})}unmuteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!1}})}send(e,t){var i;return null===(i=this.getMessageTransport())||void 0===i?void 0:i.post({send:{method:e,data:"string"==typeof t?JSON.parse(t):t}})}async callServer(e,t){var i;try{if(!this.getMessageTransport())throw new Error("Message transport not available");return null===(i=this.getMessageTransport())||void 0===i?void 0:i.postAsync({callAdapter:{method:e,arguments:t}})}catch(e){nt(e.message||e)}}sendLog(e,t){var i;try{const n=Object.keys(N).find(t=>t.toLowerCase()===e.toLowerCase())?e:N.DEBUG,s="string"==typeof t?t:JSON.stringify(t);null===(i=this.getMessageTransport())||void 0===i||i.post({log:n.toUpperCase(),message:s})}catch(e){const t=e.message||e;nt("Could not send log to server. Message parameter expected to be String or JSON-serializable object."),nt(t)}}get options(){return this._options}getOptions(){return this._options}getPeerConnection(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.connection}getDataChannel(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.dataChannel}getMediaStream(){return this._mediaStream}getMessageTransport(){return this._messageTransport}_onDataChannelError(t,i){nt(`Data channel error: ${i}`),this.trigger(new ge(e.RTCPublisherEventTypes.DATA_CHANNEL_ERROR,this,{dataChannel:t,error:i}))}_onSendReceived(t,i){it(`Send received: ${t} ${JSON.stringify(i)}`),"onMetaData"===t?this._onMetaData(i):this.trigger(new ge(e.PublisherEventTypes.PUBLISH_SEND_INVOKE,this,{methodName:t,data:i}))}_onMetaData(t){it(`Metadata received: ${JSON.stringify(t)}`),this.trigger(new ge(e.PublisherEventTypes.PUBLISH_METADATA,this,t))}_onConnectionClosed(){it("Connection closed"),this.unpublish(),this.trigger(new ge(e.PublisherEventTypes.CONNECTION_CLOSED,this))}_onDataChannelOpen(t){it(`Data channel opened: ${t.label}`),this.trigger(new ge(e.RTCPublisherEventTypes.DATA_CHANNEL_OPEN,this,{dataChannel:t})),this.trigger(new ge(e.RTCPublisherEventTypes.DATA_CHANNEL_AVAILABLE,this,{name:t.label,dataChannel:t})),this._messageTransport=this._peerConnectionHelper,this.trigger(new Ee(e.MessageTransportStateEventTypes.CHANGE,this,{controller:this,transport:this._messageTransport})),this.trigger(new ge(e.PublisherEventTypes.PUBLISH_START,this))}_onDataChannelClose(t){it(`Data channel closed: ${t.label}`),this.trigger(new ge(e.RTCPublisherEventTypes.DATA_CHANNEL_CLOSE,this,{dataChannel:t}))}_onDataChannelMessage(t,i){it(`Data channel message: ${i.data}`),this.trigger(new ge(e.RTCPublisherEventTypes.DATA_CHANNEL_MESSAGE,this,{dataChannel:t,message:i}))}_onPeerConnectionTrackAdd(t){it(`Peer connection track added: ${t.id}`),this.trigger(new ge(e.RTCPublisherEventTypes.TRACK_ADDED,this,{track:t}))}_onPeerConnectionOpen(){it("Peer connection opened"),this.trigger(new ge(e.RTCPublisherEventTypes.PEER_CONNECTION_OPEN,this,this.getPeerConnection()))}_onPeerConnectionFail(){nt("Peer connection failed"),this.trigger(new ge(e.PublisherEventTypes.PUBLISH_FAIL,this))}_onPeerConnectionClose(t){it(`Peer connection closed: ${t.type}`),this._peerConnectionHelper&&this._peerConnectionHelper.tearDown(),this.trigger(new ge(e.PublisherEventTypes.CONNECTION_CLOSED,this,t))}_onIceCandidate(t){it(`ICE candidate: ${JSON.stringify(t,null,2)}`),this.trigger(new ge(e.RTCPublisherEventTypes.CANDIDATE_CREATE,this,{candidate:t}))}_onUnpublish(){it("Unpublish received")}_onPublisherStatus(t){it("[publisherstatus] - "+JSON.stringify(t,null,2)),t.code&&"NetStream.Publish.IsAvailable"===t.code?this.trigger(new ge(e.PublisherEventTypes.PUBLISH_AVAILABLE,this,t)):this.trigger(new ge(e.PublisherEventTypes.PUBLISH_STATUS,this,t))}_onInsufficientBandwidth(t){this.trigger(new ge(e.PublisherEventTypes.PUBLISH_INSUFFICIENT_BANDWIDTH,this,t))}_onSufficientBandwidth(t){this.trigger(new ge(e.PublisherEventTypes.PUBLISH_SUFFICIENT_BANDWIDTH,this,t))}_onRecoveringBandwidth(t){this.trigger(new ge(e.PublisherEventTypes.PUBLISH_RECOVERING_BANDWIDTH,this,t))}_onSDPSuccess(e=void 0){const t=e?": "+JSON.stringify(e,null,2):"";it(`[onsdpsuccess]:: ${t}`)}_onSDPError(t=void 0){this.trigger(new ge(e.PublisherEventTypes.PUBLISH_FAIL,this));const i=t?": "+JSON.stringify(t,null,2):"";nt(`[onsdperror]:: ${i}`)}_onOrientationChange(e){const t=this.getMessageTransport();t&&t.post({send:{method:"onMetaData",data:{deviceOrientation:e}}})}_onStatisticsEndpointChange(t){it(`Statistics endpoint changed: ${t}`),this._statsMonitor&&this._statsMonitor.updateEndpoint(t),this.trigger(new ge(e.PublisherEventTypes.STATISTICS_ENDPOINT_CHANGE,this,{statisticsEndpoint:t}))}_onStatsReport(t,i){this.trigger(new ge(e.RTCPublisherEventTypes.STATS_REPORT,this,{connection:t,report:i}))}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}trigger(e){super.trigger(e)}getType(){return"RTC"}}const rt={...{protocol:"https",port:443,app:"live",autoLayoutOrientation:!0,mediaElementId:"red5pro-subscriber",rtcConfiguration:{iceServers:[{urls:"stun:stun2.l.google.com:19302"}],iceCandidatePoolSize:2,bundlePolicy:"max-bundle"},iceTransport:de.UDP,muteOnAutoplayRestriction:!0,maintainConnectionOnSubscribeErrors:!1,dataChannelConfiguration:{name:"red5pro"},signalingSocketOnly:!1,includeDataChannel:!0,maintainStreamVariant:!1,buffer:0,stats:void 0},signalingSocketOnly:!1,enableChannelSignaling:!1,includeDataChannel:!0,disableProxy:!0,trickleIce:!0,postEmptyOffer:!1,mungeOffer:void 0,mungeAnswer:void 0},at={protocol:"https",port:443,app:"live",mediaElementId:"red5pro-subscriber",muteOnAutoplayRestriction:!0},lt="R5ProPlaybackView";class dt{constructor(e="red5pro-subscriber"){try{this._targetElement=ie.resolveElement(e)}catch(e){throw O(lt,`Could not instantiate a new instance of Red5ProSubscriber. Reason: ${e.message||e}`),e}}attachStream(e){const t=this.isAutoplay;k(lt,"[attachstream]"),ie.setVideoSource(this._targetElement,e,t)}detachStream(){k(lt,"[detachstream]"),ie.setVideoSource(this._targetElement,null,this.isAutoplay)}get isAutoplay(){return ie.hasAttributeDefined(this._targetElement,"autoplay")}get view(){return this._targetElement}}const ht="RTCPeerConnectionSubscriber";class ct extends ye{constructor(e){super(e,ht)}_removeConnectionHandlers(e){e.onconnectionstatechange=null,e.oniceconnectionstatechange=null,e.onsignalingstatechange=null,e.onicecandidate=null,e.ontrack=null}_addConnectionHandlers(e){let t;e.onsignalingstatechange=()=>{const t=e.signalingState;k(ht,`[peer.onsignalingstatechange] - State: ${t}`)},e.onconnectionstatechange=()=>{const{connectionState:t}=e;"connected"===t?(k(this._name,"[peerconnection:open]"),this._responder.onPeerConnectionOpen()):"failed"!==t&&"disconnected"!==t||(I(this._name,"[peerconnection:error]"),"failed"===t&&this._responder.onPeerConnectionFail())},e.oniceconnectionstatechange=i=>{const{iceConnectionState:n}=e;k(this._name,`[peer.oniceconnectionstatechange] - State: ${n}`),"failed"===n?(t&&clearTimeout(t),this._responder.onPeerConnectionFail(),this._responder.onPeerConnectionClose(i)):"disconnected"===n?t=setTimeout(()=>{k(this._name,"[peer.oniceconnectionstatechange] - Reconnect timeout reached. Closing PeerConnection."),clearTimeout(t),this._responder.onPeerConnectionClose(i)},3e3):t&&(k(this._name,"[peer.oniceconnectionstatechange] - Clearing timeout for reconnect."),clearTimeout(t))},e.onicecandidate=e=>{const{candidate:t}=e;k(this._name,`[peer.onicecandidate] - Peer Candidate: ${null==t?void 0:t.candidate}`),t&&this._responder.onIceCandidate(t)}}_onDataChannelMessage(e){const t=e;if(super._onDataChannelMessage(e))return!0;const i=this.getJsonFromSocketMessage(t);if(null===i)return I(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0;k(this._name,"[datachannel-response]: "+JSON.stringify(i,null,2));const{data:n}=i;if(n&&"status"===n.type)return"NetStream.Play.UnpublishNotify"===n.code?(this._responder.onUnpublish(),this._responder.onConnectionClosed(),!0):"Application.Statistics.Endpoint"===n.code?(this._responder.onStatisticsEndpointChange(n.statistics),!0):(k(ht,`[datachannel.message] status :: ${n.code}`),this._responder.onSubscriberStatus(n),!0);if(n&&n.status&&"NetStream.Play.UnpublishNotify"===n.status)return this._responder.onUnpublish(),this._responder.onConnectionClosed(),!0;if(n&&"result"===n.type){const{message:e}=n;if("Stream switch: Success"===e)try{return this._responder.onStreamSwitchComplete(),!0}catch(e){}}return this._responder.onDataChannelMessage(this._dataChannel,t),!1}}var ut;!function(e){e.EMPTY="Empty",e.VIDEO="Video",e.AUDIO="Audio",e.FULL="Video/Audio"}(ut||(ut={}));class pt extends U{trigger(e){super.trigger(e)}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}}class _t extends pt{}const mt=[e.SubscriberEventTypes.SUBSCRIBE_START,e.SubscriberEventTypes.SUBSCRIBE_STOP,e.SubscriberEventTypes.SUBSCRIBE_FAIL,e.SubscriberEventTypes.SUBSCRIBE_PUBLISHER_CONGESTION,e.SubscriberEventTypes.SUBSCRIBE_PUBLISHER_RECOVERY,e.SubscriberEventTypes.PLAY_UNPUBLISH,e.SubscriberEventTypes.STREAMING_MODE_CHANGE,e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,e.SubscriberEventTypes.STATISTICS_ENDPOINT_CHANGE];class gt extends Ye{constructor(t,i){if(super("RTCSubscriberStats",t,i),this.estimatedAudioBitrate=0,this.estimatedVideoBitrate=0,this.lastAudioReport=null,this.lastVideoReport=null,this._eventHandler=t=>{const{type:i,data:n}=t;if(mt.indexOf(i)>-1)if(i===e.SubscriberEventTypes.STREAMING_MODE_CHANGE){const{streamingMode:e,previousStreamingMode:t}=n;this.postEvent(i,{data:{streamingMode:e,previousStreamingMode:t}})}else if(i===e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE){const{code:t}=n;let i;t===e.PlaybackState.AVAILABLE&&(i={timeToFirstFrameMS:(new Date).getTime()-this._startTime}),this.postEvent(o[t],i)}else{if(i===e.SubscriberEventTypes.STATISTICS_ENDPOINT_CHANGE){const{statisticsEndpoint:e}=n;this.updateEndpoint(e,!1)}this.postEvent(i)}},this._candidateCreateHandler=({data:{candidate:e}})=>{const{candidate:t}=e,i=Qe(t);i&&(this._identifier.publicIP=i)},this._hostEndpointChangedHandler=({data:{endpoint:e,iceServers:t}})=>{this._appendClientDetails({node:e,iceServers:t})},this._client.on("*",this._eventHandler),this._client.on(e.RTCSubscriberEventTypes.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.on(e.RTCSubscriberEventTypes.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),this._client.getPeerConnection())this.start(this._client.getPeerConnection());else{const t=({data:i})=>{this._client.off(e.RTCSubscriberEventTypes.PEER_CONNECTION_AVAILABLE,t),this.start(i)};this._client.on(e.RTCSubscriberEventTypes.PEER_CONNECTION_AVAILABLE,t)}}_handleStatsReport(e){const{type:t}=e,{include:i}=this._config,n=i&&i.length>0;if(n&&i.indexOf(t)>=-1)this.post(e);else if(!n)if(t===Je.CODEC){const{id:i,clockRate:n,mimeType:s,payloadType:o}=e;this.post({id:i,type:t,clockRate:n,mimeType:s,payloadType:o})}else if(t===Je.CANDIDATE_PAIR){const{availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o}=e;this.post({type:t,availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o})}else if([Je.INBOUND,"inboundrtp"].indexOf(t)>-1){const{timestamp:i,kind:n,codecId:s,jitter:o,packetsLost:r,packetsReceived:a,bytesReceived:l}=e,d={type:t,kind:n,codecId:s,jitter:o,packetsLost:r,packetsReceived:a,bytesReceived:l};if("audio"===n){const{packetsDiscarded:t}=e;if(this.lastAudioReport){const{bytesReceived:e,timestamp:t}=this.lastAudioReport,n=8*(l-e)/(i-t);this.estimatedAudioBitrate=n}this.post({...d,packetsDiscarded:t,estimatedBitrate:Math.floor(this.estimatedAudioBitrate)}),this.lastAudioReport=e}else if("video"===n){const{firCount:t,frameWidth:n,frameHeight:s,framesDecoded:o,framesDropped:r,framesPerSecond:a,framesReceived:h,freezeCount:c,keyFramesDecoded:u,nackCount:p,pauseCount:_,pliCount:m,totalFreezesDuration:g,totalPausesDuration:v}=e,E={...d,firCount:t,frameWidth:n,frameHeight:s,framesDecoded:o,framesDropped:r,framesPerSecond:a,framesReceived:h,freezeCount:c,keyFramesDecoded:u,nackCount:p,pauseCount:_,pliCount:m,totalFreezesDuration:g,totalPausesDuration:v};if(this.lastVideoReport){const{bytesReceived:e,timestamp:t}=this.lastVideoReport,n=8*(l-e)/(i-t);this.estimatedVideoBitrate=n}this.post({...E,estimatedBitrate:Math.floor(this.estimatedVideoBitrate)}),this.lastVideoReport=e}}}dispose(){this._client.off("*",this._eventHandler),this._client.off(e.RTCSubscriberEventTypes.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.off(e.RTCSubscriberEventTypes.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),super.dispose()}}class vt extends _t{constructor(e,t){super(),this._isVOD=!1,this._name=`SourceHandler-${t}`,this._view=e,this._playbackNotificationCenter=this._view,this.onCanPlay=this._onCanPlay.bind(this),this.onDurationChange=this._onDurationChange.bind(this),this.onEnded=this._onEnded.bind(this),this.onTimeUpdate=this._onTimeUpdate.bind(this),this.onPlay=this._onPlay.bind(this),this.onPause=this._onPause.bind(this),this.onVolumeChange=this._onVolumeChange.bind(this),this.onLoadedData=this._onLoadedData.bind(this),this.onLoadedMetadata=this._onLoadedMetadata.bind(this),this.onResize=this._onResize.bind(this),this.onLoadStart=this._onLoadStart.bind(this),this.onSuspend=this._onSuspend.bind(this),this.onStalled=this._onStalled.bind(this),this.onWaiting=this._onWaiting.bind(this),this.onError=this._onError.bind(this),this.onEncrypted=this._onEncrypted.bind(this),this._addPlaybackNotificationCenterHandlers(this._playbackNotificationCenter),ie.onFullScreenStateChange(this._handleFullScreenChange.bind(this))}_addPlaybackNotificationCenterHandlers(e){e.addEventListener("canplay",this.onCanPlay),e.addEventListener("durationchange",this.onDurationChange),e.addEventListener("ended",this.onEnded),e.addEventListener("timeupdate",this.onTimeUpdate),e.addEventListener("play",this.onPlay),e.addEventListener("pause",this.onPause),e.addEventListener("volumechange",this.onVolumeChange),e.addEventListener("loadeddata",this.onLoadedData),e.addEventListener("loadedmetadata",this.onLoadedMetadata),e.addEventListener("resize",this.onResize),e.addEventListener("loadstart",this.onLoadStart),e.addEventListener("suspend",this.onSuspend),e.addEventListener("stalled",this.onStalled),e.addEventListener("waiting",this.onWaiting),e.addEventListener("error",this.onError),e.addEventListener("encrypted",this.onEncrypted)}_removePlaybackNotificationCenterHandlers(e){e.removeEventListener("canplay",this.onCanPlay),e.removeEventListener("durationchange",this.onDurationChange),e.removeEventListener("ended",this.onEnded),e.removeEventListener("timeupdate",this.onTimeUpdate),e.removeEventListener("play",this.onPlay),e.removeEventListener("pause",this.onPause),e.removeEventListener("volumechange",this.onVolumeChange),e.removeEventListener("loadeddata",this.onLoadedData),e.removeEventListener("loadedmetadata",this.onLoadedMetadata),e.removeEventListener("resize",this.onResize),e.removeEventListener("loadstart",this.onLoadStart),e.removeEventListener("suspend",this.onSuspend),e.removeEventListener("stalled",this.onStalled),e.removeEventListener("waiting",this.onWaiting),e.removeEventListener("error",this.onError)}_handleFullScreenChange(t){var i,n;t?null===(i=this._view)||void 0===i||i.classList.add("red5pro-media-container-full-screen"):null===(n=this._view)||void 0===n||n.classList.remove("red5pro-media-container-full-screen"),this.trigger(new ve(e.SubscriberEventTypes.FULL_SCREEN_STATE_CHANGE,void 0,t))}_cleanup(){this._playbackNotificationCenter&&this._removePlaybackNotificationCenterHandlers(this._playbackNotificationCenter),this._playbackNotificationCenter=void 0,this._view=void 0}_onCanPlay(t){var i;k(this._name,"[videoelement:event] canplay");const n=null!==(i=this._playbackNotificationCenter)&&void 0!==i?i:t.target,o=this.getControls();o&&o.enable(!0),this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.AVAILABLE,state:s.AVAILABLE})),this.trigger(new ve(e.SubscriberEventTypes.VOLUME_CHANGE,void 0,{volume:n.volume}))}_onDurationChange(e){var t;k(this._name,"[videoelement:event] durationchange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();n&&n.setPlaybackDuration(i.duration),!isNaN(i.duration)&&Number.isFinite(i.duration)&&(this._isVOD=!0)}_onEnded(){k(this._name,"[videoelement:event] ended");const t=this.getControls();t&&t.setState(e.PlaybackState.IDLE),this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.IDLE,state:s.IDLE}))}_onTimeUpdate(t){var i;const n=null!==(i=this._playbackNotificationCenter)&&void 0!==i?i:t.target,s=this.getControls();s&&s.setSeekTime(n.currentTime,this.isVOD()?n.duration:void 0),this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:n.currentTime,duration:n.duration}))}_onPlay(){k(this._name,"[videoelement:event] play");const t=this.getControls();t&&t.setState(e.PlaybackState.PLAYING),this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.PLAYING,state:s.PLAYING}))}_onPause(){k(this._name,"[videoelement:event] pause");const t=this.getControls();t&&t.setState(e.PlaybackState.PAUSED),this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.PAUSED,state:s.PAUSED}))}_onVolumeChange(t){var i;k(this._name,"[videoelement:event] volumechange");const n=null!==(i=this._playbackNotificationCenter)&&void 0!==i?i:t.target,s=this.getControls();s&&s.getVolume()!==n.volume&&s.setVolume(n.volume),this.trigger(new ve(e.SubscriberEventTypes.VOLUME_CHANGE,void 0,{volume:n.volume}))}_onLoadedData(t){var i,n,s;k(this._name,"[videoelement:event] loadeddata");const o=null!==(i=this._view)&&void 0!==i?i:t.target;this.trigger(new ve(e.SubscriberEventTypes.VIDEO_DIMENSIONS_CHANGE,void 0,{width:null!==(n=o.videoWidth)&&void 0!==n?n:0,height:null!==(s=o.videoHeight)&&void 0!==s?s:0}))}_onLoadedMetadata(t){var i,n;k(this._name,"[videoelement:event] loadedmetadata");const s=null!==(i=this._view)&&void 0!==i?i:t.target;this.trigger(new ve(e.SubscriberEventTypes.LOADED_METADATA,void 0,{duration:null!==(n=s.duration)&&void 0!==n?n:0}))}_onResize(t){var i,n,s;k(this._name,"[videoelement:event] resize");const o=null!==(i=this._view)&&void 0!==i?i:t.target;this.trigger(new ve(e.SubscriberEventTypes.VIDEO_DIMENSIONS_CHANGE,void 0,{width:null!==(n=o.videoWidth)&&void 0!==n?n:0,height:null!==(s=o.videoHeight)&&void 0!==s?s:0}))}_onLoadStart(){k(this._name,"[videoelement:event] loadstart")}_onSuspend(){k(this._name,"[videoelement:event] suspend")}_onStalled(){k(this._name,"[videoelement:event] stalled")}_onWaiting(){k(this._name,"[videoelement:event] waiting")}_onEncrypted(){k(this._name,"[videoelement:event] encrypted")}_onError(t){k(this._name,"[videoelement:event] error"),this.trigger(new ve(e.SubscriberEventTypes.CONNECT_FAILURE,void 0,{error:t.message}))}async attemptAutoplay(t=!1){try{await this.play(),this.isMuted()&&this.trigger(new ve(e.SubscriberEventTypes.AUTO_PLAYBACK_MUTED,void 0,{element:this._view}))}catch(i){t?(this.mute(),this.attemptAutoplay(t)):this.trigger(new ve(e.SubscriberEventTypes.AUTO_PLAYBACK_FAILURE,void 0,{error:i.message?i.message:i,element:this._view}))}}async play(){var e,t;if(k(this._name,"[videoelement:action] play"),!(null===(e=this._view)||void 0===e?void 0:e.paused))return k(this._name,"[videoelement:action] play (ALREADY PLAYING)"),!0;try{return await(null===(t=this._view)||void 0===t?void 0:t.play()),!0}catch(e){throw O(this._name,"[videoelement:action] play (FAULT) - "+e.message),e}}async pause(){var e;k(this._name,"[videoelement:action] pause");try{return await(null===(e=this._view)||void 0===e?void 0:e.pause()),!0}catch(e){I(this._name,"[videoelement:action] pause (CATCH::FAULT) - "+e.message)}return!1}async resume(){var e;k(this._name,"[videoelement:action] resume");try{return await(null===(e=this._view)||void 0===e?void 0:e.play()),!0}catch(e){I(this._name,"[videoelement:action] resume (CATCH::FAULT) - "+e.message)}return!1}async stop(){var e;k(this._name,"[videoelement:action] stop");try{return await(null===(e=this._view)||void 0===e?void 0:e.pause()),!0}catch(e){I(this._name,"[videoelement:action] stop (CATCH::FAULT) - "+e.message)}return!1}mute(){this._view&&(this._view.muted=!0);const e=this.getControls();e&&e.setMutedState(!0)}unmute(){this._view&&(this._view.muted=!1);const e=this.getControls();e&&e.setMutedState(!1)}setVolume(e){this.unmute(),this._view&&(this._view.volume=e)}getVolume(){var e,t;return null!==(t=null===(e=this._view)||void 0===e?void 0:e.volume)&&void 0!==t?t:0}seekTo(e,t=void 0){this._view&&(this._view.currentTime=t?e*t:e)}toggleFullScreen(e){try{(e||this._view)&&ie.toggleFullScreen(null!=e?e:this._view)}catch(e){}}async unpublish(){var e;try{await this.stop(),null===(e=this._view)||void 0===e||e.dispatchEvent(new Event("ended"))}catch(e){}}disconnect(){this._cleanup()}isVOD(){return this._isVOD}isMuted(){var e,t;return null!==(t=null===(e=this._view)||void 0===e?void 0:e.muted)&&void 0!==t&&t}getControls(){}}const Et="WHEPClient",St=rt,Ct=e=>k(Et,e),bt=e=>O(Et,e),ft=e=>I(Et,e);class Tt extends pt{constructor(e,t,i){super(),this._videoMuted=!0,this._audioMuted=!0;const n=e?se(e):St,s=i||St,o={...s,...n,endpoint:e,mediaElementId:t?t.id:s.mediaElementId};this._videoUnmuteHandler=this._onVideoUnmute.bind(this),this._audioUnmuteHandler=this._onAudioUnmute.bind(this),e&&this.internalInit(o)}async internalInit(e){await this.init(e),await this.subscribe()}async _runMuteCheck(){var e,t,i;if(this.getPeerConnection())try{let n=this._videoMuted,s=this._audioMuted;const o=await(null===(e=this.getPeerConnection())||void 0===e?void 0:e.getStats());if(null==o||o.forEach(e=>{const{type:t,kind:i,bytesReceived:o}=e;"inbound-rtp"!==t&&"inboundrtp"!==t||("video"===i?n=o<=0:"audio"===i&&(s=o<=0))}),n===this._videoMuted&&s===this._audioMuted)return;this._videoMuted=n,this._audioMuted=s;const r={data:{streamingMode:(t=!this._videoMuted,i=!this._audioMuted,t&&i?ut.FULL:t?ut.VIDEO:i?ut.AUDIO:ut.EMPTY),method:"onMetaData"},type:"metadata",method:"onMetaData",eventTimestamp:(new Date).getTime()};this._onMetaData(r)}catch(e){bt(e.message||e)}}_onVideoUnmute(e){const t=e.target;null==t||t.removeEventListener("unmute",this._videoUnmuteHandler);const i=setTimeout(async()=>{clearTimeout(i),this._runMuteCheck()},1e3)}_onAudioUnmute(e){const t=e.target;null==t||t.removeEventListener("unmute",this._audioUnmuteHandler);const i=setTimeout(async()=>{clearTimeout(i),this._runMuteCheck()},1e3)}_attachSourceHandler(e){this._sourceHandler=new vt(e,this.getType())}_glomTrigger(e){e.on("*",e=>{const{type:t,data:i}=e;this.trigger(new ve(t,this,i))})}_playIfAutoplaySet(e,t){var i;if(e&&t){const{muteOnAutoplayRestriction:n}=e;ie.hasAttributeDefined(t,"autoplay")&&(null===(i=this._sourceHandler)||void 0===i||i.attemptAutoplay(n))}}addMediaStreamToPlayback(e,t){var i;!this._playbackView&&e&&(this._playbackView=new dt(e)),null===(i=this._playbackView)||void 0===i||i.attachStream(t)}async requestOffer(t){var i;Ct("[requestoffer]");const{iceTransport:n,maintainStreamVariant:s,videoEncoding:o,audioEncoding:r,connectionParams:a,mungeOffer:l}=this._options;t.addTransceiver("video",{direction:"recvonly"}),t.addTransceiver("audio",{direction:"recvonly"});const d={transport:n,doNotSwitch:s};o&&o!==e.PlaybackVideoEncoder.NONE&&(d.videoEncoding=o),r&&r!==e.PlaybackAudioEncoder.NONE&&(d.audioEncoding=r);const h=null!=a?a:{},c=await t.createOffer(),u=await(null===(i=this._whipWhepService)||void 0===i?void 0:i.postSDPOffer(c.sdp,{...h,...d},!1));if(!u)throw bt("Failed to get offer from WHEP"),new Error("Failed to get offer from WHEP");const{sdp:p}=u;let _=p;return l&&(Ct(`[MUNGE:before] offer: ${_}`),_=l(_),Ct(`[MUNGE:after] offer: ${_}`)),_}async requestAnswer(e){const{mungeAnswer:t}=this._options;let i=(await e.createAnswer()).sdp;return t&&(Ct(`[MUNGE:before] answer: ${i}`),i=t(i),Ct(`[MUNGE:after] answer: ${i}`)),i}async sendAnswer(e){var t;const{connectionParams:i}=this._options;return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.postSDPAnswer(e,i))}async postCandidateFragments(e){var t;const{connectionParams:i}=this._options,n=ke(e,void 0,!0);return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.trickle(n,i))}async init(e){var t;this._options={...St,...e},this._options.subscriptionId=this._options.subscriptionId||`subscriber-${Math.floor(65536*Math.random()).toString(16)}`;const i=oe(this._options,"whep"),{includeDataChannel:n,disableProxy:s}=this._options;return this._whipWhepService=new xe(`${i}?requestId=${this._options.subscriptionId}`,n,s),this._messageTransport=this._whipWhepService,(null===(t=this._options)||void 0===t?void 0:t.stats)&&this.monitorStats(this._options.stats),this}async subscribe(){var t,i,n,s,o,r,a,l;const{connectionParams:d,rtcConfiguration:h,includeDataChannel:c,signalingSocketOnly:u,enableChannelSignaling:p,dataChannelConfiguration:_}=this._options;try{const l=d||{},g=await(null===(t=this._whipWhepService)||void 0===t?void 0:t.getOptions(l));this.trigger(new ve(e.SubscriberEventTypes.CONNECT_SUCCESS,this,null===(i=this._whipWhepService)||void 0===i?void 0:i.getUrl())),(null==g?void 0:g.links)&&(this._options.rtcConfiguration={...h,iceServers:g.links}),(null==g?void 0:g.origin)&&this.trigger(new ve(e.RTCSubscriberEventTypes.HOST_ENDPOINT_CHANGED,this,{endpoint:g.origin})),(null==g?void 0:g.statisticsEndpoint)&&this._onStatisticsEndpointChange(g.statisticsEndpoint);const v=c||p||u?_:void 0;this._peerConnectionHelper=new ct({onUnpublish:this._onUnpublish.bind(this),onStreamUnavailable:this._onStreamUnavailable.bind(this),onSubscriberStatus:this._onSubscriberStatus.bind(this),onStreamSwitchComplete:this._onStreamSwitchComplete.bind(this),onDataChannelError:this._onDataChannelError.bind(this),onSendReceived:this._onSendReceived.bind(this),onMetaData:this._onMetaData.bind(this),onConnectionClosed:this._onConnectionClosed.bind(this),onDataChannelOpen:this._onDataChannelOpen.bind(this),onDataChannelClose:this._onDataChannelClose.bind(this),onDataChannelMessage:this._onDataChannelMessage.bind(this),onPeerConnectionOpen:this._onPeerConnectionOpen.bind(this),onPeerConnectionFail:this._onPeerConnectionFail.bind(this),onPeerConnectionClose:this._onPeerConnectionClose.bind(this),onIceCandidate:this._onIceCandidate.bind(this),onSDPSuccess:this._onSDPSuccess.bind(this),onSDPError:this._onSDPError.bind(this),onStatisticsEndpointChange:this._onStatisticsEndpointChange.bind(this)}),await this._peerConnectionHelper.setUpWithPeerConfiguration(this._options.rtcConfiguration,v),null===(n=this.getPeerConnection())||void 0===n||n.addEventListener("track",t=>{const{buffer:i}=this._options;Ct("[peerconnection.ontrack]");const{streams:n,track:s,receiver:o,transceiver:r}=t;o.playoutDelayHint=i,o.jitterBufferDelayHint=i,this.trigger(new ve(e.RTCSubscriberEventTypes.TRACK_ADDED,this,{streams:n,track:s,receiver:o,transceiver:r})),this._mediaStream=n&&n.length>0?n[0]:void 0,"video"===s.kind?(this._videoMuted=s.muted,s.muted&&s.addEventListener("unmute",this._videoUnmuteHandler)):"audio"===s.kind&&(this._audioMuted=s.muted,s.muted&&s.addEventListener("unmute",this._audioUnmuteHandler)),this._runMuteCheck()}),this.trigger(new ve(e.RTCSubscriberEventTypes.PEER_CONNECTION_AVAILABLE,this,this.getPeerConnection())),this.trigger(new ve(e.RTCSubscriberEventTypes.OFFER_START,this));const E=await this.requestOffer(this.getPeerConnection()),S=new RTCSessionDescription({type:"offer",sdp:E});await(null===(s=this.getPeerConnection())||void 0===s?void 0:s.setRemoteDescription(S)),this.trigger(new ve(e.RTCSubscriberEventTypes.OFFER_END,this)),this.trigger(new ve(e.RTCSubscriberEventTypes.ANSWER_START,this));const C=await this.requestAnswer(this.getPeerConnection()),b=(m=C).includes("stereo=1")?m:m.replace("useinbandfec=1","useinbandfec=1;stereo=1;sprop-stereo=1"),f=new RTCSessionDescription({type:"answer",sdp:b});await(null===(o=this.getPeerConnection())||void 0===o?void 0:o.setLocalDescription(f)),await this.sendAnswer(b),this.trigger(new ve(e.RTCSubscriberEventTypes.ANSWER_END,this));const T=await this._peerConnectionHelper.waitToGatherIce(),{sdp:y}=T;return await this.postCandidateFragments(y),this.trigger(new ve(e.RTCSubscriberEventTypes.ICE_TRICKLE_COMPLETE,this)),this._mediaStream&&(this.trigger(new ve(e.RTCSubscriberEventTypes.ON_ADD_STREAM,this,this._mediaStream)),this.addMediaStreamToPlayback(this._options.mediaElementId,this._mediaStream)),(null===(r=this._playbackView)||void 0===r?void 0:r.view)&&this._attachSourceHandler(this._playbackView.view),this._sourceHandler&&this._glomTrigger(this._sourceHandler),this._playIfAutoplaySet(this._options,null===(a=this._playbackView)||void 0===a?void 0:a.view),this}catch(t){throw bt(null!==(l=t.message)&&void 0!==l?l:"Could not subscribe."),t instanceof Me?this._onStreamUnavailable(t):this.trigger(new ve(e.SubscriberEventTypes.CONNECT_FAILURE,this,t)),this._options.maintainConnectionOnSubscribeErrors||this.unsubscribe(!0),t}var m}async unsubscribe(t=!1){var i;Ct("[unsubscribe]"),this._peerConnectionHelper&&await this._peerConnectionHelper.tearDown(),this._whipWhepService&&await this._whipWhepService.tearDown(null,t),this._sourceHandler&&this._sourceHandler.disconnect(),this.unmonitorStats(),null===(i=this._playbackView)||void 0===i||i.detachStream(),this._playbackView=void 0,this._whipWhepService=void 0,this._messageTransport=void 0,this._peerConnectionHelper=void 0,this._sourceHandler=void 0,this._mediaStream=void 0,this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_STOP,this))}send(e,t){var i;return null===(i=this.getMessageTransport())||void 0===i?void 0:i.post({send:{method:e,data:"string"==typeof t?JSON.parse(t):t}})}async callServer(e,t){var i;const n="switchStreams"===e,{app:s,streamName:o}=this._options;if(n){const{path:i}=t[0];this._requestedStreamSwitch=i,Ct(`[callServer:switch]:: ${e}, ${s}/${o} -> ${i}`)}return null===(i=this.getMessageTransport())||void 0===i?void 0:i.postAsync({callAdapter:{method:e,arguments:t}})}sendLog(e,t){var i;try{const n=Object.keys(N).find(t=>t.toLowerCase()===e.toLowerCase())?e:N.DEBUG,s="string"==typeof t?t:JSON.stringify(t);null===(i=this.getMessageTransport())||void 0===i||i.post({log:n.toUpperCase(),message:s})}catch(e){const t=e.message||e;bt("Could not send log to server. Message parameter expected to be String or JSON-serializable object."),bt(t)}}enableStandby(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0,muteVideo:!0}})}disableStandby(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1,muteVideo:!1}})}muteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0}})}unmuteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1}})}muteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!0}})}unmuteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!1}})}get options(){return this._options}getOptions(){return this._options}getPeerConnection(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.connection}getDataChannel(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.dataChannel}getMediaStream(){return this._mediaStream}getMessageTransport(){return this._messageTransport}getPlayer(){var e;return null===(e=this._playbackView)||void 0===e?void 0:e.view}play(){Ct("[play]"),this._sourceHandler?this._sourceHandler.play():ft("Cannot play without a Source Handler.")}pause(){Ct("[pause]"),this._sourceHandler?this._sourceHandler.pause():ft("Cannot pause without a Source Handler.")}resume(){Ct("[resume]"),this._sourceHandler?this._sourceHandler.resume():ft("Cannot resume without a Source Handler.")}stop(){Ct("[stop]"),this._sourceHandler?this._sourceHandler.stop():ft("Cannot stop without a Source Handler.")}setVolume(e){Ct("[setVolume]"),this._sourceHandler?this._sourceHandler.setVolume(e):ft("Cannot set volume without a Source Handler.")}getVolume(){var e,t,i;return Ct("[getVolume]"),this._sourceHandler?this._sourceHandler.getVolume():(ft("Cannot get volume without a Source Handler."),null!==(i=null===(t=null===(e=this._playbackView)||void 0===e?void 0:e.view)||void 0===t?void 0:t.volume)&&void 0!==i?i:0)}mute(){Ct("[mute]"),this._sourceHandler?this._sourceHandler.mute():ft("Cannot mute without a Source Handler.")}unmute(){Ct("[unmute]"),this._sourceHandler?this._sourceHandler.unmute():ft("Cannot unmute without a Source Handler.")}seekTo(e){Ct("[seekTo]"),this._sourceHandler?this._sourceHandler.seekTo(e):ft("Cannot seek without a Source Handler.")}toggleFullScreen(){Ct("[toggleFullScreen]"),this._sourceHandler?this._sourceHandler.toggleFullScreen():ft("Cannot toggle full screen without a Source Handler.")}monitorStats(e){Ct("[monitorStats]");const{host:t,endpoint:i,app:n,streamName:s,subscriptionId:o,connectionParams:r}=this._options,a=null!=e?e:ze;return this._statisticsConfiguration={...a,host:t,app:n,hostEndpoint:i,streamName:s,subscriptionId:o,connectionParams:r},this._statsMonitor?ft("Cannot monitor stats without a Peer Connection. Please call `init` before calling `monitorStats`."):this._statsMonitor=new gt(this._statisticsConfiguration,{onStatsReport:this._onStatsReport.bind(this),getPeerConnection:this.getPeerConnection.bind(this),getMessageTransport:this.getMessageTransport.bind(this),on:this.on.bind(this),off:this.off.bind(this),trigger:this.trigger.bind(this)}),this}unmonitorStats(){return this._statsMonitor&&this._statsMonitor.dispose(),this._statsMonitor=void 0,this._statisticsConfiguration=void 0,this}_onUnpublish(){Ct("[unpublish]"),this.trigger(new ve(e.SubscriberEventTypes.PLAY_UNPUBLISH,this)),this._sourceHandler&&this._sourceHandler.unpublish()}_onStreamUnavailable(t){Ct(`Stream ${this._options.streamName} does not exist.`),Ct("[onstreamunavailable]: "+JSON.stringify(t,null,2)),this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_INVALID_NAME,this))}_onDataChannelError(t,i){bt(`Data channel error: ${i}`),this.trigger(new ve(e.RTCSubscriberEventTypes.DATA_CHANNEL_ERROR,this,{dataChannel:t,error:i}))}_onSendReceived(t,i){Ct(`Send received: ${t} ${JSON.stringify(i)}`),"onMetaData"===t?this._onMetaData(i):this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_SEND_INVOKE,this,{methodName:t,data:i}))}_onStreamSwitchComplete(){Ct("[streamswitch::complete]");const t=this._requestedStreamSwitch;this.trigger(new ve(e.RTCSubscriberEventTypes.SUBSCRIBE_STREAM_SWITCH,this,{path:t})),this._requestedStreamSwitch=void 0}_onMetaData(t){const{orientation:i,streamingMode:n}=t,s=this._streamingMode;void 0!==i&&i!==this._orientation&&(this._orientation=i,this.trigger(new ve(e.SubscriberEventTypes.ORIENTATION_CHANGE,this,{orientation:parseInt(i,10),viewElement:this._playbackView?this._playbackView.view:void 0}))),n&&void 0!==n&&n!==s&&(this._streamingMode=n,this.trigger(new ve(e.SubscriberEventTypes.STREAMING_MODE_CHANGE,this,{streamingMode:n,previousStreamingMode:s,viewElement:this._playbackView?this._playbackView.view:void 0}))),this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_METADATA,this,t))}_onConnectionClosed(){Ct("Connection closed"),this.unsubscribe(!0),this.trigger(new ve(e.SubscriberEventTypes.CONNECTION_CLOSED,this))}_onDataChannelOpen(t){Ct(`Data channel opened: ${t.label}`),this.trigger(new ve(e.RTCSubscriberEventTypes.DATA_CHANNEL_OPEN,this,{dataChannel:t})),this.trigger(new ve(e.RTCSubscriberEventTypes.DATA_CHANNEL_AVAILABLE,this,{name:t.label,dataChannel:t})),this._messageTransport=this._peerConnectionHelper,this.trigger(new Ee(e.MessageTransportStateEventTypes.CHANGE,this,{controller:this,transport:this._messageTransport})),this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_START,this))}_onDataChannelClose(t){Ct(`Data channel closed: ${t.label}`),this.trigger(new ve(e.RTCSubscriberEventTypes.DATA_CHANNEL_CLOSE,this,{dataChannel:t}))}_onDataChannelMessage(t,i){Ct(`Data channel message: ${i.data}`),this.trigger(new ve(e.RTCSubscriberEventTypes.DATA_CHANNEL_MESSAGE,this,{dataChannel:t,message:i}))}_onPeerConnectionOpen(){var t;Ct("Peer connection opened"),this.trigger(new ve(e.RTCSubscriberEventTypes.PEER_CONNECTION_OPEN,this,this.getPeerConnection())),(null===(t=this._options)||void 0===t?void 0:t.includeDataChannel)||this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_START,this))}_onPeerConnectionFail(){bt("Peer connection failed"),this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_FAIL,this))}_onPeerConnectionClose(e){Ct(`Peer connection closed: ${e.type}`)}_onIceCandidate(t){Ct(`ICE candidate: ${t.candidate}`),this.trigger(new ve(e.RTCSubscriberEventTypes.CANDIDATE_CREATE,this,{candidate:t}))}_onPeerConnectionTrackAdd(e){Ct(`Peer connection track added: ${e.id}`)}_onSubscriberStatus(e){Ct(`Subscriber status: ${JSON.stringify(e)}`)}_onSDPSuccess(){Ct("SDP success")}_onSDPError(e){bt(`SDP error: ${e}`)}_onStatisticsEndpointChange(t){Ct(`Statistics endpoint changed: ${t}`),this._statsMonitor&&this._statsMonitor.updateEndpoint(t),this.trigger(new ve(e.SubscriberEventTypes.STATISTICS_ENDPOINT_CHANGE,this,{statisticsEndpoint:t}))}_onStatsReport(t,i){this.trigger(new ve(e.RTCSubscriberEventTypes.STATS_REPORT,this,{connection:t,report:i}))}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}trigger(e){super.trigger(e)}getType(){return"RTC"}}class yt extends vt{constructor(e,t){super(e,t),this._playingStarted=!1,this.onOrientation=this._onOrientationMetadata.bind(this),this.onStreamingMode=this._onStreamingModeMetadata.bind(this),ie.onOrientationMetadata(this._view,this.onOrientation),ie.onStreamingModeMetadata(this._view,this.onStreamingMode),this.onPlaying=this._onPlaying.bind(this),this.onSourceError=this._onSourceError.bind(this),this._view.addEventListener("playing",this.onPlaying)}addSource(e){this._source=ie.createElement("source"),this._source.type="application/x-mpegURL",this._source.src=e,this._view.firstChild?this._view.insertBefore(this._source,this._view.firstChild):this._view.appendChild(this._source),this._source.addEventListener("error",this.onSourceError)}_onPlaying(){this._playingStarted||this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_START,this._view)),this._playingStarted=!0}_onSourceError(t){k(this._name,"[source:event] error"),this.trigger(new ve(e.SubscriberEventTypes.CONNECT_FAILURE,void 0,t))}_onOrientationMetadata(t){const{orientation:i}=t,n=parseInt(i,10);i&&this._orientation!==n&&(k(this._name,"Metadata received: "+JSON.stringify(t,null,2)),this._orientation=n,this.trigger(new ve(e.SubscriberEventTypes.ORIENTATION_CHANGE,{orientation:this._orientation,viewElement:this._view})),this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_METADATA,void 0,t)))}_onStreamingModeMetadata(t){const{streamingMode:i}=t,n=this._streamingMode;i&&n!==i&&(k(this._name,"Metadata received: "+JSON.stringify(t,null,2)),this._streamingMode=i,this.trigger(new ve(e.SubscriberEventTypes.STREAMING_MODE_CHANGE,void 0,{streamingMode:this._streamingMode,previousStreamingMode:n,viewElement:this._view})),this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_METADATA,void 0,t)))}_cleanup(){this._view&&this._view.removeEventListener("playing",this.onPlaying),this._source&&(this._source.removeEventListener("error",this.onSourceError),this._view.removeChild(this._source),this._source=void 0),super._cleanup()}}const wt="HLSSubscriber",At=e=>k(wt,e),Pt=e=>I(wt,e);class Lt extends pt{constructor(){super()}_glomTrigger(e){e.on("*",e=>{const{type:t,data:i}=e;this.trigger(new ve(t,this,i))})}_playIfAutoplaySet(e,t){var i;if(e&&t){const{muteOnAutoplayRestriction:n}=e;ie.hasAttributeDefined(t,"autoplay")&&(null===(i=this._sourceHandler)||void 0===i||i.attemptAutoplay(n))}}async init(e){if(!ie.supportsHLS())throw new Error("Native HLS playback is not supported on this browser.");return this._options={...at,...e},this}async subscribe(){var t;try{const i=/^http(|s).*\.m3u8/g,{endpoint:n,mediaElementId:s}=this._options;return this._fileURL=n&&n.match(i)?n:(e=>{const{host:t,protocol:i,port:n,app:s,streamName:o,connectionParams:r}=e,a="ws"===i||"http"===i?"http":"https",l=`${a}://${t}:${n||("http"===a?5080:443)}/${s}/${o}.m3u8`;if(r)return`${l}?${Object.entries(r).map(([e,t])=>`${e}=${t}`).join("&")}`;return l})(this._options),!this._playbackView&&s&&(this._playbackView=new dt(s),this._sourceHandler=new yt(this._playbackView.view,this.getType()),this._sourceHandler.addSource(this._fileURL),this._glomTrigger(this._sourceHandler)),this.trigger(new ve(e.SubscriberEventTypes.CONNECT_SUCCESS,this,this._fileURL)),this._playIfAutoplaySet(this._options,null===(t=this._playbackView)||void 0===t?void 0:t.view),this}catch(t){throw t(t.message),this.trigger(new ve(e.SubscriberEventTypes.CONNECT_FAILURE,this,t.message)),t}}async unsubscribe(){var t;return this._sourceHandler&&this._sourceHandler.disconnect(),null===(t=this._playbackView)||void 0===t||t.detachStream(),this._playbackView=void 0,this._sourceHandler=void 0,this.trigger(new ve(e.SubscriberEventTypes.SUBSCRIBE_STOP,this)),this}play(){At("[play]"),this._sourceHandler?this._sourceHandler.play():Pt("Cannot play without a Source Handler.")}pause(){At("[pause]"),this._sourceHandler?this._sourceHandler.pause():Pt("Cannot pause without a Source Handler.")}resume(){At("[resume]"),this._sourceHandler?this._sourceHandler.resume():Pt("Cannot resume without a Source Handler.")}stop(){At("[stop]"),this._sourceHandler?this._sourceHandler.stop():Pt("Cannot stop without a Source Handler.")}setVolume(e){At("[setVolume]"),this._sourceHandler?this._sourceHandler.setVolume(e):Pt("Cannot set volume without a Source Handler.")}getVolume(){var e,t,i;return At("[getVolume]"),this._sourceHandler?this._sourceHandler.getVolume():(Pt("Cannot get volume without a Source Handler."),null!==(i=null===(t=null===(e=this._playbackView)||void 0===e?void 0:e.view)||void 0===t?void 0:t.volume)&&void 0!==i?i:0)}mute(){At("[mute]"),this._sourceHandler?this._sourceHandler.mute():Pt("Cannot mute without a Source Handler.")}unmute(){At("[unmute]"),this._sourceHandler?this._sourceHandler.unmute():Pt("Cannot unmute without a Source Handler.")}seekTo(e){At("[seekTo]"),this._sourceHandler?this._sourceHandler.seekTo(e):Pt("Cannot seek without a Source Handler.")}toggleFullScreen(){At("[toggleFullScreen]"),this._sourceHandler?this._sourceHandler.toggleFullScreen():Pt("Cannot toggle full screen without a Source Handler.")}getPlayer(){var e;return null===(e=this._playbackView)||void 0===e?void 0:e.view}get options(){return this._options}getOptions(){return this._options}get fileURL(){return this._fileURL}getFileURL(){return this._fileURL}getType(){return"HLS"}}const Nt={baseURL:void 0,fullURL:void 0,hlsjsRef:void 0,hlsElement:void 0,usePlaybackControlsUI:!0,options:{debug:!1,backBufferLength:0}},Rt={...rt,liveSeek:Nt};class Dt extends U{trigger(e){super.trigger(e)}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}}var Ht,kt;!function(e){e.SEEK_START="Seek.Start",e.SEEK_END="Seek.End"}(Ht||(Ht={})),function(e){e.CHANGE="Slider.Change",e.CHANGE_START="Slider.Change.Start",e.CHANGE_COMPLETE="Slider.Change.Complete"}(kt||(kt={}));class It extends me{constructor(e,t,i){super(e,i),this._slider=t}get slider(){return this._slider}}const{createElement:Ot,addGlobalEventListener:Mt,removeGlobalEventListener:Ut,globalUnassign:Bt,getAssignedValue:Vt,globalAssign:Ft}=ie,$t="ControlSlider",Gt="r5_liveseek_event_owner";class Wt extends U{constructor(e){super(),this._value=0,this._disabled=!1,this._eventStartPosition=0,this.debug=e=>k($t,e),this.warn=e=>I($t,e),this.name=[$t,e].join("::"),this.debug("[init]"),this._container=Ot("div"),this._button=this.createButton(),this._track=this.createTrack(),this._progressBar=this.createProgressBar(),this._container.appendChild(this._track),this._container.appendChild(this._progressBar),this._container.appendChild(this._button),this._layout(),this._mouseupHandler=this._mouseup.bind(this),this._mousedownHandler=this._mousedown.bind(this),this._mousemoveHandler=this._mousemove.bind(this),this._touchupHandler=this._touchproxy.bind(this),this._touchdownHandler=this._touchproxy.bind(this),this._touchmoveHandler=this._touchproxy.bind(this),this._updateHandlers(this._disabled)}_touchproxy(e){var t,i,n,s;const o=e;this.debug(`${o.type} touches: ${(null===(t=o.changedTouches)||void 0===t?void 0:t.length)||0}`);try{o.preventDefault()}catch(e){this.warn("Failed to prevent default on touch event.")}if(!o.touches||o.touches.length>1||"touchend"===o.type&&o.touches.length>0)return;let r,a="";const l=o.target||document.body;switch(o.type){case"touchstart":a="mousedown",r=null===(i=o.changedTouches)||void 0===i?void 0:i[0];break;case"touchmove":a="mousemove",r=null===(n=o.changedTouches)||void 0===n?void 0:n[0];break;case"touchend":a="mouseup",r=null===(s=o.changedTouches)||void 0===s?void 0:s[0]}if(r&&a){const e=new MouseEvent(a,{bubbles:!0,cancelable:!0,view:l.ownerDocument.defaultView,screenX:r.screenX,screenY:r.screenY,clientX:r.clientX,clientY:r.clientY,ctrlKey:o.ctrlKey,altKey:o.altKey,shiftKey:o.shiftKey,metaKey:o.metaKey,button:0,relatedTarget:null});l.dispatchEvent(e)}}_mouseup(){this._eventStartPosition=0,Bt(Gt),Ut("mousemove",this._mousemoveHandler),Ut("mouseup",this._mouseupHandler),Ut("touchmove",this._touchmoveHandler),Ut("touchend",this._touchupHandler),this.trigger(new It(kt.CHANGE_COMPLETE,this))}_mousemove(e){if(Vt(Gt)!==this.name)return;this.debug(`[mousemove] ${this.name}`);const t=e.clientX-this._eventStartPosition,i=this._button.parentNode.getBoundingClientRect();let n=this._eventStartPosition+t-i.left;n=Math.max(0,n),n=Math.min(n,i.width);const s=n/i.width;this.trigger(new It(kt.CHANGE,this,s))}_mousedown(e){this._eventStartPosition=e.clientX,this.trigger(new It(kt.CHANGE_START,this)),Ft(Gt,this.name),Mt("mousemove",this._mousemoveHandler),Mt("mouseup",this._mouseupHandler),Mt("touchmove",this._touchmoveHandler),Mt("touchend",this._touchupHandler)}_updateHandlers(e){this._eventStartPosition=0,e?(this._track.removeEventListener("click",this._mousemoveHandler),this._progressBar.removeEventListener("click",this._mousemoveHandler),this._button.removeEventListener("mousedown",this._mousedownHandler),Ut("mousemove",this._mousemoveHandler),Ut("mouseup",this._mouseupHandler),Ut("touchmove",this._touchmoveHandler),Ut("touchend",this._touchupHandler),this._track.classList.add("red5pro-media-slider-disabled"),this._progressBar.classList.add("red5pro-media-slider-disabled"),this._button.classList.add("red5pro-media-slider-disabled")):(this._track.addEventListener("click",this._mousemoveHandler),this._progressBar.addEventListener("click",this._mousemoveHandler),this._button.addEventListener("mousedown",this._mousedownHandler),this._button.addEventListener("touchstart",this._touchdownHandler),this._track.classList.remove("red5pro-media-slider-disabled"),this._progressBar.classList.remove("red5pro-media-slider-disabled"),this._button.classList.remove("red5pro-media-slider-disabled"))}_layout(){const e=this._progressBar.parentNode.clientWidth*this._value;this._progressBar.style.width=e+"px",this._button.style.left=e-.5*this._button.clientWidth+"px"}createButton(){const e=Ot("span");return e.classList.add("red5pro-media-slider-button"),e}createProgressBar(){const e=Ot("span");return e.classList.add("red5pro-media-slider-progress"),e}createTrack(){const e=Ot("span");return e.classList.add("red5pro-media-slider-track"),e}get value(){return this._value}set value(e){this._value=e,this._layout()}get disabled(){return this._disabled}set disabled(e){this._disabled=e,this._updateHandlers(e)}get view(){return this._container}}const{createElement:xt,isTouchEnabled:jt,isPossiblySafari:Kt}=ie,zt=e=>k("PlaybackControls",e);class Jt extends Dt{constructor(t,i){super(),this._state=e.PlaybackState.IDLE,this._mutedState=!1,this._resumeAfterSeek=!1,this._playbackDuration=0,this._volumeValue=1,this._player=t,this._container=i,this._onPlayPauseClickBound=this._onPlayPauseClick.bind(this),this._decorate(this._container)}_decorate(t){if(!t)return;zt("[decorate]");const i=xt("div");let n;i.classList.add("red5pro-media-control-bar"),this._playPauseButton=this._createPlayPauseButton(),this._muteButton=this._createMuteButton(),this._volumeField=this._createVolumeControl(),this._seekTimeField=this._createSeekControl(),this._timeField=this._createPlaybackTime(),this._fullScreenButton=this._createFullScreenToggle(),i.appendChild(this._playPauseButton),i.appendChild(this._timeField),i.appendChild(this._seekTimeField.view),i.appendChild(this._muteButton),i.appendChild(this._volumeField.view),i.appendChild(this._fullScreenButton),t.appendChild(i),this._controlbar=i;const s=()=>{clearTimeout(n),n=setTimeout(()=>{i.classList.remove("red5pro-media-control-bar-show")},6e3)};jt()?(i.classList.add("red5pro-media-control-bar-show"),t.addEventListener("touchend",()=>{i.classList.toggle("red5pro-media-control-bar-show"),s()}),s()):(t.addEventListener("mouseover",()=>{i.classList.add("red5pro-media-control-bar-show")}),t.addEventListener("mouseout",()=>{i.classList.remove("red5pro-media-control-bar-show")})),this.setState(e.PlaybackState.IDLE).onFullScreenChange(!1).setSeekTime(0).enable(!1)}_onPlayPauseClick(){return this.getState()===e.PlaybackState.PLAYING?this._player.pause(!0):this.getState()===e.PlaybackState.PAUSED?this._player.resume(!0):this._player.play(!0),this}_createPlayPauseButton(){const e=xt("button");return e.setAttribute("aria-label","Toggle Playback"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-playpause-button"),e}_createMuteButton(){const e=xt("button");return e.setAttribute("aria-label","Toggle Mute Audio"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-muteunmute-button"),e.addEventListener("click",()=>{this.getMutedState()?(this._player.unmute(),this.setMutedState(!1)):(this._player.mute(),this.setMutedState(!0))}),e}_createVolumeControl(){const e=new Wt("volume");return e.view.classList.add("red5pro-media-control-element"),e.view.classList.add("red5pro-media-volume-slider"),e.view.classList.add("red5pro-media-slider"),e.on(kt.CHANGE,e=>{const t=Number(e.data);this._player.setVolume(t)}),e}_createSeekControl(){const t=new Wt("seek");return t.view.classList.add("red5pro-media-control-element"),t.view.classList.add("red5pro-media-seektime-slider"),t.view.classList.add("red5pro-media-slider"),t.on(kt.CHANGE_START,()=>{this.getState()===e.PlaybackState.PLAYING&&(this._resumeAfterSeek=!0,this._player.pause(!0,!0)),this.trigger(new me(Ht.SEEK_START))}),t.on(kt.CHANGE,e=>{const t=Number(e.data);this._player.seekTo(t,0===this._playbackDuration?void 0:this._playbackDuration),this.setSeekTime(t*this._playbackDuration,this._playbackDuration)}),t.on(kt.CHANGE_COMPLETE,()=>{this._resumeAfterSeek&&this.getState()===e.PlaybackState.PAUSED&&(this._resumeAfterSeek=!1,this._player.resume(!0)),this.trigger(new me(Ht.SEEK_END))}),t}_createPlaybackTime(){const e=xt("span"),t=xt("text");return t.textContent="00:00",e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-time-field"),e.appendChild(t),e}_createFullScreenToggle(){const e=xt("button");return e.setAttribute("aria-label","Toggle Fullscreen"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-fullscreen-button"),e.addEventListener("click",()=>{this._player.toggleFullScreen()}),e}_formatTime(e){const t=new Date(1e3*e);return`${String(t.getUTCHours()).padStart(2,"0")}:${String(t.getUTCMinutes()).padStart(2,"0")}:${String(t.getUTCSeconds()).padStart(2,"0")}`}onStateChange(t){var i,n,s,o;return t===e.PlaybackState.PLAYING?(null===(i=this._playPauseButton)||void 0===i||i.classList.remove("red5pro-media-play-button"),null===(n=this._playPauseButton)||void 0===n||n.classList.add("red5pro-media-pause-button")):(null===(s=this._playPauseButton)||void 0===s||s.classList.add("red5pro-media-play-button"),null===(o=this._playPauseButton)||void 0===o||o.classList.remove("red5pro-media-pause-button")),this}onMutedStateChange(e){var t,i,n,s;return e?(null===(t=this._muteButton)||void 0===t||t.classList.add("red5pro-media-mute-button"),null===(i=this._muteButton)||void 0===i||i.classList.remove("red5pro-media-unmute-button"),this._volumeField&&(this._volumeField.value=0)):(null===(n=this._muteButton)||void 0===n||n.classList.remove("red5pro-media-mute-button"),null===(s=this._muteButton)||void 0===s||s.classList.add("red5pro-media-unmute-button"),this._volumeField&&(this._volumeField.value=this._volumeValue)),this}onFullScreenChange(e){var t,i,n,s;return e?(null===(t=this._fullScreenButton)||void 0===t||t.classList.add("red5pro-media-exit-fullscreen-button"),null===(i=this._fullScreenButton)||void 0===i||i.classList.remove("red5pro-media-fullscreen-button")):(null===(n=this._fullScreenButton)||void 0===n||n.classList.remove("red5pro-media-exit-fullscreen-button"),null===(s=this._fullScreenButton)||void 0===s||s.classList.add("red5pro-media-fullscreen-button")),this}enable(e){var t,i,n,s;return e?(null===(t=this._playPauseButton)||void 0===t||t.classList.remove("red5pro-media-element-button-disabled"),null===(i=this._playPauseButton)||void 0===i||i.addEventListener("click",this._onPlayPauseClickBound)):(null===(n=this._playPauseButton)||void 0===n||n.classList.add("red5pro-media-element-button-disabled"),null===(s=this._playPauseButton)||void 0===s||s.removeEventListener("click",this._onPlayPauseClickBound)),this}getVolume(){return this._volumeValue}setVolume(e){return this._volumeField&&(this._volumeField.value=e),this._volumeValue=e,0===e?this.setMutedState(!0):this.getMutedState()&&this.setMutedState(!1),this}setSeekTime(e,t=0){return this._seekTimeField&&(this._seekTimeField.value=0===t?0:e/t,0!==this._playbackDuration&&this._playbackDuration<=e&&(this._seekTimeField.value=1)),this._timeField&&(!isFinite(this._playbackDuration)&&Kt()?this._timeField.innerText="Live Broadcast":this._timeField.innerText=this._formatTime(Math.floor(e))),this}setPlaybackDuration(e){return this._playbackDuration=e,this}getPlaybackDuration(){return this._playbackDuration}getState(){return this._state}setState(e){return zt(`[setState]: ${o[e]}`),this._state=e,this.onStateChange(this._state),this}setMutedState(e){return this._mutedState=e,this.onMutedStateChange(this._mutedState),this}getMutedState(){return"muted"in this._player?this._player.muted:this._mutedState}setAsVOD(e){return zt(`[setAsVOD]: ${e}`),this._seekTimeField&&(e?this._seekTimeField.disabled=!1:(this._seekTimeField.value=0,this._seekTimeField.disabled=!0)),this}detach(){this.enable(!1),this._controlbar&&this._controlbar.parentNode&&this._controlbar.parentNode.removeChild(this._controlbar),this._controlbar=void 0,this._container=void 0}}var Yt,qt;!function(e){e[e.LIVE=0]="LIVE",e[e.VOD=1]="VOD"}(Yt||(Yt={})),function(e){e.LIVE="LiveSeek.LIVE",e.VOD="LiveSeek.VOD"}(qt||(qt={}));const Qt={[Yt.LIVE]:qt.LIVE,[Yt.VOD]:qt.VOD};var Xt;!function(e){e.LIVE_SEEK_UNSUPPORTED="WebRTC.LiveSeek.Unsupported",e.LIVE_SEEK_ERROR="WebRTC.LiveSeek.Error",e.LIVE_SEEK_ENABLED="WebRTC.LiveSeek.Enabled",e.LIVE_SEEK_DISABLED="WebRTC.LiveSeek.Disabled",e.LIVE_SEEK_LOADING="WebRTC.LiveSeek.FragmentLoading",e.LIVE_SEEK_LOADED="WebRTC.LiveSeek.FragmentLoaded",e.LIVE_SEEK_CHANGE="WebRTC.LiveSeek.Change"}(Xt||(Xt={}));const{createElement:Zt,findByQuerySelector:ei,createHLSClient:ti,getHLSClientEventEnum:ii}=ie,ni="SourceHandlerSeekable",si=e=>k(ni,e),oi=e=>O(ni,e),ri=e=>I(ni,e);class ai extends vt{constructor(e,t,i,n,s=!0){super(e,`${t}-Seekable`),this._hlsElementGenerated=!1,this._hlsRecoverFlop=!1,this._hlsRecoverAttempts=0,this._isFragLoading=!1,this._wallOffset=NaN,this._lastDurationUpdate=0,this._averageSegmentDuration=6,this._isSeekable=!1,this._isHLSPlaybackActive=!1,this._container=s?this._determineContainer(e):void 0,this._liveSeekConfig=i,this._hlsOptions=n,this._usePlaybackControls=s,this.onHLSDurationChange=this._onHLSDurationChange.bind(this),this.onHLSTimeUpdate=this._onHLSTimeUpdate.bind(this),this.onHLSPlay=this._onHLSPlay.bind(this),this.onHLSPause=this._onHLSPause.bind(this)}_determineContainer(e){if(e.parentNode&&e.parentNode.classList.contains("red5pro-media-container"))return e.classList.add("red5pro-media"),e.parentNode;{const t=e.parentNode,i=Zt("div");return i.classList.add("red5pro-media-container"),e.classList.add("red5pro-media"),t.insertBefore(i,e),t.removeChild(e),i.appendChild(e),i}}_generateHLSLivePlayback(e,t,i){const n=`${i}-hls-vod`;let s=ei(`#${n}`);return s||(s=Zt("video"),s.id=n,s.classList.add("red5pro-hls-vod"),s.classList.add("red5pro-media-background"),s.setAttribute("playsinline","playsinline"),s.style.width="100%",s.style.height="100%",s.style.display="none",e.insertBefore(s,t),this._hlsElementGenerated=!0),s}_onDurationChange(e){var t;si("[videoelement:event] durationchange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();!this.isSeekable&&n&&n.setPlaybackDuration(i.duration)}_onTimeUpdate(t){var i;const n=null!==(i=this._playbackNotificationCenter)&&void 0!==i?i:t.target,s=this.getControls();if(this.isSeekable){if(!this._isHLSPlaybackActive){const t=this._hlsElement.duration,i=n.currentTime-this._lastDurationUpdate,o=isNaN(t)||0===t?n.currentTime:t+this._averageSegmentDuration+i;s&&s.setSeekTime(o,o),this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:o,duration:o,action:"rtc time update (1)"}))}}else super._onTimeUpdate(t)}_onEnded(){this.isHLSPlaybackActive||super._onEnded()}_onHLSDurationChange(t){const i=t.target,n=t.duration||i.duration;isNaN(this._wallOffset)&&(this._wallOffset=n-this._view.currentTime),this._lastDurationUpdate=this._view.currentTime;const s=n+this._averageSegmentDuration;si(`[HLS:videoelement:duration] ${n}, ${this._averageSegmentDuration}`);const o=this.getControls();o&&o.setPlaybackDuration(s),this._isHLSPlaybackActive?this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:i.currentTime,duration:s,action:"hls time update"})):this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:s,duration:s,action:"hls time update"}))}_onHLSTimeUpdate(t){const i=t.target,n=this.getControls();n&&n.setSeekTime(i.currentTime,n.getPlaybackDuration()),i.currentTime>=i.duration?this._showHLSLivePlayback(!1,this._hlsElement,this._view,this._container):!isNaN(i.duration)&&this._isHLSPlaybackActive&&this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:i.currentTime,duration:i.duration+this._averageSegmentDuration,action:"hls time update"}))}_onHLSPlay(){si("[HLS:videoelement:event] play");const t=this.getControls();t&&t.setState(e.PlaybackState.PLAYING),this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.PLAYING,state:o[e.PlaybackState.PLAYING]}))}_onHLSPause(){si("[HLS:videoelement:event] pause");const t=this.getControls();t&&t.setState(e.PlaybackState.PAUSED),this.trigger(new ve(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.PAUSED,state:o[e.PlaybackState.PAUSED]}))}_addSeekableHandlers(e,t,i){if(t){const i=ii();t.on(i.ERROR,(i,n)=>{const{type:s,details:o,fatal:r,url:a}=n;if("networkerror"===s.toLowerCase()){if("levelemptyerror"===o.toLowerCase()){this.trigger(new ve(Xt.LIVE_SEEK_DISABLED,void 0,{hlsElement:e,hlsControl:t})),this.isSeekable=!1,t.destroy();const i=setTimeout(()=>{clearTimeout(i),this.enableLiveSeek(a,this._subscriptionId,this._hlsElement,!1)},3e3);return}this.trigger(new ve(Xt.LIVE_SEEK_ERROR,void 0,{hlsElement:e,hlsControl:t,error:n}))}else this.trigger(new ve(Xt.LIVE_SEEK_ERROR,void 0,{hlsElement:e,hlsControl:t,error:n}));"mediaerror"===s.toLowerCase()&&(this._hlsRecoverFlop&&t.swapAudioCodec(),this._hlsRecoverFlop=!this._hlsRecoverFlop,this._hlsRecoverAttempts=this._hlsRecoverAttempts+1,t.recoverMediaError()),r&&"networkerror"===s.toLowerCase()&&t.startLoad()}),t.on(i.MANIFEST_PARSED,()=>{try{e.pause()}catch(e){si(`Could not pause seekable live stream: ${e.message}`)}this.isSeekable=!0,this.trigger(new ve(Xt.LIVE_SEEK_ENABLED,void 0,{hlsElement:e,hlsControl:t}))}),t.on(i.FRAG_LOADING,(i,n)=>{const{frag:{stats:{loaded:s,total:o}}}=n;this.trigger(new ve(Xt.LIVE_SEEK_LOADING,void 0,{hlsElement:e,hlsControl:t,progress:s/o*100})),(this._isHLSPlaybackActive||this._isFragLoading)&&(this._isFragLoading=s/o>=1)}),t.on(i.FRAG_LOADED,(i,n)=>{this._isFragLoading=!1;const{frag:{endDTS:s,loader:o}}=n;if(!this._isHLSPlaybackActive&&!s)return;let r=6,a=0;if(o&&o.stats&&o.stats.segments){const e=o.stats.segments;for(let t=0;t{this._isFragLoading=!1;const{frag:{endDTS:s,loader:o}}=n;if(!this._isHLSPlaybackActive&&!s)return;let r=6,a=0;if(o&&o.stats&&o.stats.segments){const e=o.stats.segments;for(let t=0;tn.test(e));if(!r)return void ri(`Could not find last segment in manifest: ${e}`);const a=o.find(e=>i.test(e));if(!a)return void ri(`Could not find duration line in manifest: ${e}`);const l=a.match(i);if(!l)return void ri(`Could not find duration in manifest: ${e}`);const d=l[1],h=parseFloat(d),c=r.match(n);if(!c)return void ri(`Could not find segment length in manifest: ${e}`);const u=c[1];let p=parseInt(u,10);isNaN(p)&&(p=1),p=p>1?p-1:p,this._averageSegmentDuration=h,this.isSeekable=!0,this.trigger(new ve(Xt.LIVE_SEEK_ENABLED,void 0,{hlsElement:this._hlsElement,hlsControl:void 0})),this.onHLSDurationChange({target:t,duration:h*p}),this._manifestLoadTimeout=setTimeout(()=>{clearTimeout(this._manifestLoadTimeout),this._loadManifest(e,t)},1e3*h)}catch(e){oi(`Could not load manifest: ${e.message}.`),this.trigger(new ve(Xt.LIVE_SEEK_DISABLED,void 0,{hlsElement:t,hlsControl:void 0})),this.isSeekable=!1}}_cleanup(){this._removeSeekableHandlers(this._hlsElement,this._hlsjsRef),this._hlsjsRef&&(this._hlsjsRef.detachMedia(),this._hlsjsRef=void 0),this._hlsElement&&(this._hlsElement.parentNode&&this._hlsElementGenerated&&this._hlsElement.parentNode.removeChild(this._hlsElement),this._hlsElement=void 0),this._playbackControls&&(this._playbackControls.detach(),this._playbackControls=void 0),this._isVOD=!1,this._isSeekable=!1,this._isHLSPlaybackActive=!1,this._isFragLoading=!1,this._hlsRecoverFlop=!1,this._hlsRecoverAttempts=0,this._averageSegmentDuration=6,this._hlsElementGenerated=!1,this._wallOffset=NaN,this._lastDurationUpdate=0,this._manifestLoadTimeout&&(clearTimeout(this._manifestLoadTimeout),this._manifestLoadTimeout=void 0),super._cleanup()}addSource(){si("[addSource]"),this._view.controls=!0,this._view.classList.add("red5pro-media");this._view.hasAttribute("controls")&&this._view.classList.contains("red5pro-media")&&(this._container=this._determineContainer(this._view));const e=this._view.hasAttribute("muted");this._usePlaybackControls?(this._playbackControls=new Jt(this,this._container),this._view.controls=!1,this._playbackControls.setAsVOD(this.isSeekable),this._playbackControls.setMutedState(e)):this._view.controls=!1}enableLiveSeek(e,t,i,n=!1){if(this.getControls()&&this.getControls().setSeekTime(1,1),this._url=e,this._subscriptionId=t,this._hlsElement=i||this._generateHLSLivePlayback(this._container,this._view,t),this._showHLSLivePlayback(this._isHLSPlaybackActive,this._hlsElement,this._view,this._container),n){this._addSeekableHandlers(this._hlsElement,void 0,!1);const t=Zt("source");t.src=e,this._hlsElement.appendChild(t),this._loadManifest(e,this._hlsElement)}else{const t=this._hlsOptions,{liveSeek:{hlsjsRef:i}}=this._liveSeekConfig,n=i?new i(t):ti(t);this._addSeekableHandlers(this._hlsElement,n,!0),n.attachMedia(this._hlsElement,e),n.on(ii().MEDIA_ATTACHED,()=>{n.loadSource(e)}),this._hlsjsRef=n}}switchLiveSeek(e){this._hlsjsRef&&(this._hlsjsRef.destroy(),this._hlsjsRef=void 0),this.enableLiveSeek(e,this._subscriptionId,this._hlsElement),this.seekTo(1);try{this._view.play()}catch(e){ri("[videoelement:action] play (FAULT) - "+e.message)}this._url=e}async play(e=!1){si("[videoelement:action] play");try{return e&&this._hlsElement&&this._hlsElement.paused?(await this._hlsElement.play(),!0):super.play()}catch(e){ri("[videoelement:action] play (CATCH::FAULT) - "+e.message)}return!1}async pause(e=!1,t=!1){si("[videoelement:action] pause");try{return e&&t&&this._hlsElement?(this._hlsElement.pause(),super.pause()):e&&this._hlsElement&&!this._hlsElement.paused?(this._hlsElement.pause(),!0):super.pause()}catch(e){ri("[videoelement:action] pause (CATCH::FAULT) - "+e.message)}return!1}async resume(e=!1){var t,i;si("[videoelement:action] resume");try{const n=this._isHLSPlaybackActive&&this._hlsElement?this._hlsElement.play():null===(t=this._view)||void 0===t?void 0:t.play();if(e&&this._isHLSPlaybackActive)return await(null===(i=this._view)||void 0===i?void 0:i.play()),!0;n&&n.then(()=>si("[videoelement:action] play (START)")).catch(e=>ri("[videoelement:action] play (CATCH::FAULT) "+(e.message?e.message:e)))}catch(e){ri("[videoelement:action] resume (CATCH::FAULT) - "+e.message)}return!1}async stop(){si("[videoelement:action] stop");try{return this._hlsElement&&this._hlsElement.pause(),super.stop()}catch(e){ri("[videoelement:action] stop (CATCH::FAULT) - "+e.message)}return!1}mute(){this._hlsElement&&(this._hlsElement.muted=this._isHLSPlaybackActive),this._view&&(this._view.muted=!0);const e=this.getControls();e&&e.setMutedState(!0)}unmute(){this._hlsElement&&(this._hlsElement.muted=!this._isHLSPlaybackActive,this._view&&(this._view.muted=this._isHLSPlaybackActive)),this._view&&(this._view.muted=!1);const e=this.getControls();e&&e.setMutedState(!1)}setVolume(e){this.unmute(),this._hlsElement&&this._isHLSPlaybackActive?this._hlsElement.volume=e:this._view?this._view.volume=e:oi("[videoelement:action] setVolume (CATCH::FAULT) - "+e)}seekTo(e,t=void 0){if(this.isSeekable)if(this.getControls()&&this.getControls().setSeekTime(e,t),this.trigger(new ve(Xt.LIVE_SEEK_CHANGE,void 0,{seek:e,duration:t})),this._hlsElement&&e<1)try{this._hlsElement.classList.remove("hidden"),this._hlsElement.currentTime=this._hlsElement.duration*e,this._isFragLoading=!0,this._showHLSLivePlayback(!0,this._hlsElement,this._view,this._container),this._view.paused||(si("[hlsvod:action] play (START) - (seekTo)"),this.play(!0))}catch(e){ri("[hlsvod:action] play (CATCH::FAULT) - "+e.message)}else this._hlsElement&&e>=1&&(this._isFragLoading=!1,this._showHLSLivePlayback(!1,this._hlsElement,this._view,this._container));else this._view.currentTime=t?e*t:e}toggleFullScreen(e){var t;this._container&&super.toggleFullScreen(null!==(t=this._container)&&void 0!==t?t:e)}getControls(){return this._playbackControls}get isSeekable(){return this._isSeekable}set isSeekable(e){this._isSeekable=e,this.getControls()&&this.getControls().setAsVOD(e)}get isHLSPlaybackActive(){return this._isHLSPlaybackActive}get url(){return this._url}}const{supportsHLS:li,supportsNonNativeHLS:di}=ie,hi="WHEPLiveSeekClient",ci=e=>O(hi,e);class ui extends Tt{constructor(e,t,i){super(e,t,i)}async init(e){const{liveSeek:t}=e;return t||(e.liveSeek=Nt),super.init(e)}_attachSourceHandler(e){var t;if((null===(t=this._playbackView)||void 0===t?void 0:t.view)&&!this._enableLiveSeek(this._playbackView.view))return I(hi,"LiveSeek is not enabled, using default source handler"),void super._attachSourceHandler(e);this._startSeekableIfSeekableEnabled(this._options)}_enableLiveSeek(e){const{liveSeek:t}=this._options;if(t){const{hlsjsRef:i,usePlaybackControlsUI:n,options:s}=t;if(li()||di(i))return this._sourceHandler=new ai(e,this.getType(),this._options,s,n),this._sourceHandler.addSource(),!0;ci("Could not utilize the 'LiveSeek' request. This feature requires either native HLS playback or hls.js as a depenency."),this.trigger(new ve(Xt.LIVE_SEEK_UNSUPPORTED,this,{feature:"Live Seek",message:"Live Seek requires integration with the HLS.JS plugin in order work properly. Most likely you are viewing this on a browser that does not support the use of HLS.JS."}))}return!1}_startSeekableIfSeekableEnabled(e){const{liveSeek:t,subscriptionId:i}=e;if(!t)return;const{hlsjsRef:n,hlsElement:s}=t;if(this._sourceHandler)try{if(!li()&&!di(n))throw new Error;{const t=ne(e);this._sourceHandler.enableLiveSeek(t,i,s,!di(n))}}catch(e){ci("Could not utilize the 'LiveSeek' request. This feature requires either native HLS playback or hls.js as a depenency.")}}_onUnpublish(){super._onUnpublish();const{liveSeek:e}=this._options;e||this.unsubscribe(!0)}_onStreamSwitchComplete(){const e=this._requestedStreamSwitch,{liveSeek:t}=this._options;if(t&&e){const{baseURL:i,fullURL:n}=t,s=e.split("/"),o=s.pop(),r=s.join("/"),a={...this._options,app:r,streamName:o};let l=n;if(n){const e=/.*\/(.*)\.m3u8/.exec(n);if(e&&e.length>1){const t=`${e[1]}.m3u8`;l=n.replace(t,`${o}.m3u8`)}}const d=ne(a,i,l);this._sourceHandler&&this._sourceHandler.switchLiveSeek(d)}super._onStreamSwitchComplete()}}const pi="NEW-15.0.0.11-release.b189";R(N.ERROR);const _i=(e,t=!1)=>{Object.prototype.hasOwnProperty.call(N,e.toUpperCase())&&(R(e,t),console&&console.log(`Red5 Pro SDK Version ${mi()}`))},mi=()=>pi;k("RED5",`Red5 Pro HTML SDK Version: ${pi}`);var gi={version:pi,LOG_LEVELS:N,getLogger:D,getRecordedLogs:H,setLogLevel:_i,getVersion:mi,PlaybackVideoEncoder:e.PlaybackVideoEncoder,PlaybackAudioEncoder:e.PlaybackAudioEncoder,PlaybackState:e.PlaybackState,PlaybackStateReadableMap:o,PublishVideoEncoder:e.PublishVideoEncoder,PublishAudioEncoder:e.PublishAudioEncoder,SubscriberEvent:ve,PublisherEvent:ge,MessageTransportStateEvent:Ee,PublisherEventTypes:e.PublisherEventTypes,SubscriberEventTypes:e.SubscriberEventTypes,RTCPublisherEventTypes:e.RTCPublisherEventTypes,RTCSubscriberEventTypes:e.RTCSubscriberEventTypes,MessageTransportStateEventTypes:e.MessageTransportStateEventTypes,WHIPClient:ot,WHEPClient:Tt,HLSSubscriber:Lt,LiveSeekClient:ui,defaultWhepSubscriberConfig:rt,defaultWhipPublisherConfig:pe};e.Event=me,e.EventEmitter=U,e.HLSSubscriber=Lt,e.LOG_LEVELS=N,e.LiveSeekClient=ui,e.MessageTransportStateEvent=Ee,e.PlaybackController=pt,e.PlaybackControls=Dt,e.PlaybackStateReadableMap=o,e.PublisherEvent=ge,e.SourceHandler=_t,e.SourceHandlerImpl=vt,e.SubscriberEvent=ve,e.WHEPClient=Tt,e.WHIPClient=ot,e.default=gi,e.defaultHLSSubscriberConfig=at,e.defaultLiveSeekConfig=Rt,e.defaultStatsConfig=ze,e.defaultWhepSubscriberConfig=rt,e.defaultWhipPublisherConfig=pe,e.getLogger=D,e.getRecordedLogs=H,e.getVersion=mi,e.setLogLevel=_i,Object.defineProperty(e,"__esModule",{value:!0})});
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).red5prosdk={})}(this,(function(e){"use strict";var t,i,n,s;e.PlaybackAudioEncoder=void 0,(t=e.PlaybackAudioEncoder||(e.PlaybackAudioEncoder={})).OPUS="OPUS",t.NONE="NONE",e.PlaybackVideoEncoder=void 0,(i=e.PlaybackVideoEncoder||(e.PlaybackVideoEncoder={})).VP8="VP8",i.H264="H264",i.H265="H265",i.NONE="NONE",e.PlaybackState=void 0,(n=e.PlaybackState||(e.PlaybackState={}))[n.UNAVAILABLE=1e3]="UNAVAILABLE",n[n.AVAILABLE=0]="AVAILABLE",n[n.IDLE=1]="IDLE",n[n.PLAYING=2]="PLAYING",n[n.PAUSED=3]="PAUSED",function(e){e.UNAVAILABLE="Playback.UNAVAILABLE",e.AVAILABLE="Playback.AVAILABLE",e.IDLE="Playback.IDLE",e.PLAYING="Playback.PLAYING",e.PAUSED="Playback.PAUSED"}(s||(s={}));const o={[e.PlaybackState.UNAVAILABLE]:s.UNAVAILABLE,[e.PlaybackState.AVAILABLE]:s.AVAILABLE,[e.PlaybackState.IDLE]:s.IDLE,[e.PlaybackState.PLAYING]:s.PLAYING,[e.PlaybackState.PAUSED]:s.PAUSED};var r,a,l;!function(e){e.RTMP="rtmp",e.RTC="rtc"}(r||(r={})),function(e){e.LIVE="live",e.RECORD="record",e.APPEND="append"}(a||(a={})),e.PublishAudioEncoder=void 0,(e.PublishAudioEncoder||(e.PublishAudioEncoder={})).OPUS="OPUS",e.PublishVideoEncoder=void 0,(l=e.PublishVideoEncoder||(e.PublishVideoEncoder={})).VP8="VP8",l.H264="H264",l.H265="H265";var d={trace:10,debug:20,info:30,warn:40,error:50,fatal:60},h={};function c(e){return"string"==typeof e?d[e.toLowerCase()]:e}function u(e,t){return u=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},u(e,t)}function p(e,t,i){return p=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}()?Reflect.construct:function(e,t,i){var n=[null];n.push.apply(n,t);var s=new(Function.bind.apply(e,n));return i&&u(s,i.prototype),s},p.apply(null,arguments)}function _(e){if(null==e)return e;if(Array.isArray(e))return e.slice();if("object"==typeof e){var t={};return Object.keys(e).forEach((function(i){t[i]=e[i]})),t}return e}function m(e){return void 0===e?"undefined":null===e?"null":Array.isArray(e)?"[ "+e.map((function(e){return m(e)})).join(", ")+" ]":"object"==typeof e?JSON.stringify(e):"function"==typeof e?"[Function: "+e.name+"]":"boolean"==typeof e||"number"==typeof e?e:"'"+e.toString()+"'"}function g(e){if("string"!=typeof e){for(var t=new Array(arguments.length),i=0;i=o)return e;switch(e){case"%s":return String(s[n++]);case"%d":return Number(s[n++]);case"%j":try{return JSON.stringify(s[n++])}catch(e){return"[Circular]"}default:return e}})),a=s[n];ne||(s=function(s){var o;s[0]instanceof Error?(i={err:t.serializers&&t.serializers.err?t.serializers.err(s[0]):f.err(s[0])},o={err:!0},n=1===s.length?[i.err.message]:Array.prototype.slice.call(s,1)):"object"!=typeof s[0]&&null!==s[0]||Array.isArray(s[0])?(i=null,n=Array.prototype.slice.call(s)):(i=s[0],n=1===s.length&&i.err&&i.err instanceof Error?[i.err.message]:Array.prototype.slice.call(s,1));var r=_(t.fields);r.level=e;var a=i?_(i):null;if(a&&(t.serializers&&t._applySerializers(a,o),Object.keys(a).forEach((function(e){r[e]=a[e]}))),r.levelName=h[e],r.msg=n.length?g.apply(t,n):"",r.time||(r.time=new Date),t.src&&!r.src)try{throw new Error("call-stack-error")}catch(e){var l=e.stack?function(e,t){var i=e.split("\n");i[0]&&i[0].indexOf("call-stack-error")>=0&&i.shift();var n=i[t],s=null;if(n){var o=/^\s*(at|.*@)\s*(.+)?$/.exec(n);s=Array.isArray(o)&&o[2]?o[2]:n}return s}(e.stack,2):"";l||function(e){return v[e]}("src")||E("Unable to determine src line info","src"),r.src=l||""}return r.v=1,r}(n),this._emit(s))}}function T(e){var t=e.stack||e.toString();if(e.cause&&"function"==typeof e.cause){var i=e.cause();i&&(t+="\nCaused by: "+T(i))}return t}C.prototype.trace=b(10),C.prototype.debug=b(20),C.prototype.info=b(30),C.prototype.warn=b(40),C.prototype.error=b(50),C.prototype.fatal=b(60);var f={err:function(e){return e&&e.stack?{message:e.message,name:e.name,stack:T(e),code:e.code,signal:e.signal}:e}};const y={10:"TRACE",20:"DEBUG",30:"INFO",40:"WARN",50:"ERROR",60:"FATAL"};class A{write(e){console.log("%s - [%s] %s: %s",e.time.toISOString(),e.name,y[e.level]||"UNKNOWN",e.msg)}}let w,P;const L=e=>(t,i)=>{var n;w&&"function"==typeof w[e]&&w[e]((n=t,e=>`(${n}) ${e}`)(i))},R={TRACE:"trace",INFO:"info",DEBUG:"debug",WARN:"warn",ERROR:"error",FATAL:"fatal"},N=(e,t=!1,i)=>{const n=[{level:e,stream:new A,type:"raw"}];if(i){const t=i.map((t=>({...t,level:e})));n.push(...t)}t&&(P=[],n.push({level:e,stream:{write:t=>{const i=`[${t.time.toISOString()}] ${e.toUpperCase()}: ${t.msg}`;null==P||P.push(i)}},type:"raw"}));w=function(){return p(C,[].slice.call(arguments))}({level:e,name:"red5pro-sdk",streams:n})},D=()=>(w||N(R.INFO),w),I=()=>P||[];L(R.TRACE),L(R.INFO);const O=L(R.DEBUG),H=L(R.WARN),k=L(R.ERROR);L(R.FATAL);const M="RED5PRO";class U{constructor(){this._callbacks={},this._callbacks[M]=[]}_notify(e,t){let i;const n=e.length;for(i=0;i1&&(s=V.exec(e),n[1]===t&&s&&s.length>1)?s[1]:void 0}}function W(e){const t=G(e,"orientation");if(t)return{orientation:parseInt(t)}}function x(e){const t=G(e,"streamingMode");if(t)return{streamingMode:t}}const j=e=>$.get(e),K=e=>{const t=e.textTracks;t&&(e.addTextTrack("metadata"),t.addEventListener("addtrack",(t=>{const i=t.track;i.mode="hidden",i.addEventListener("cuechange",(t=>{let n,s;for(t&&t.currentTarget?n=t.currentTarget.cues:(n=i.cues,n=n&&n.length>0?n:i.activeCues),n=n||[],s=0;s{e(n)})),s&&o&&o.streamingMode&&o.streamingMode.forEach((e=>{e(s)}))}}}))})))},z="BrowserEnvironment",J=e=>O(z,e),Y=e=>H(z,e);let q=[];const X=()=>{const e=screen.orientation?screen.orientation.angle:void 0,t=void 0===e?window.matchMedia("(orientation: portrait)").matches?0:90:e,i=q.length;J(`[window:onorientationchange]: orientation(${t}).`);for(let e=0;e{const e=document.createElement("video");return e.canPlayType("application/vnd.apple.mpegURL").length>0||e.canPlayType("application/x-mpegURL").length>0||e.canPlayType("audio/mpegurl").length>0||e.canPlayType("audio/x-mpegurl").length>0},te="undefined"!=typeof window&&window.adapter;var ie={gUM:async e=>navigator.mediaDevices.getUserMedia(e),createElement:e=>document.createElement(e),resolveElement:e=>document.getElementById(e),getElementId:e=>e.id,setVideoSource:(e,t,i)=>{if(e.srcObject=t,i)try{const t=e.play();t&&t.then((()=>J("[setVideoSource:action]: play (START)"))).catch((t=>{Y(`[setVideoSource:action]: play (CATCH::FAULT) ${t.message}`);try{e.setAttribute("autoplay","false"),e.pause()}catch(e){Y(`[setVideoSource:action]: pause (CATCH::FAULT) ${e.message}`)}}))}catch(e){Y(`[setVideoSource:action]: play (CATCH::FAULT) ${e.message}`)}},hasAttributeDefined:(e,t)=>e.hasAttribute(t),addOrientationChangeHandler:(e,t=!0)=>{"onorientationchange"in window&&(J("[window:orientation:addOrientationChangeHandler]: add"),q.push(e),t&&X()),1===q.length&&(J("[window:orientation:addOrientationChangeHandler]: add"),window.addEventListener("orientationchange",X))},removeOrientationChangeHandler:e=>{q=q.filter((t=>t!==e)),0===q.length&&window.removeEventListener("orientationchange",X)},toggleFullScreen:e=>{window.screenfull&&window.screenfull.enabled?window.screenfull.toggle(e):document.fullscreenEnabled&&(document.fullscreenElement&&document.fullscreenElement===e?document.exitFullscreen():e.requestFullscreen())},onFullScreenStateChange:e=>{var t;Z.push(e),t=window.screenfull,Q||(Q=!0,window.screenfull?window.screenfull.on("change",(()=>{Z.forEach((e=>e(t.isFullscreen)))})):document.fullscreenEnabled&&document.addEventListener("fullscreenchange",(()=>{Z.forEach((e=>e(null!==document.fullscreenElement)))})))},getOrGenerateFingerprint:()=>{const e=window.localStorage;if(e&&e.getItem("red5_fingerprint"))return e.getItem("red5_fingerprint");let t;try{t=window.crypto.randomUUID()}catch(e){t="10000000-1000-4000-8000-100000000000".replace(/[018]/g,(e=>(Number(e)^crypto.getRandomValues(new Uint8Array(1))[0]&15>>Number(e)/4).toString(16)))}return e.setItem("red5_fingerprint",t),t},getBrowserDetails:()=>{const e=void 0!==window.adapter,{navigator:t,adapter:i}=window,{appVersion:n,platform:s,userAgent:o,vendor:r}=t,a={appVersion:n,platform:s,userAgent:o,vendor:r};return e?{...i.browserDetails,...a}:a},supportsHLS:ee,onOrientationMetadata:(e,t)=>{const i=$.get(e);$.has(e)?Object.prototype.hasOwnProperty.call(i,"orientation")||($.get(e).orientation=[]):(K(e),$.set(e,{orientation:[]})),$.get(e).orientation.push(t)},onStreamingModeMetadata:(e,t)=>{const i=$.get(e);$.has(e)?Object.prototype.hasOwnProperty.call(i,"streamingMode")||($.get(e).streamingMode=[]):(K(e),$.set(e,{streamingMode:[]})),$.get(e).streamingMode.push(t)},isTouchEnabled:()=>"ontouchstart"in window,isPossiblySafari:()=>te?"safari"===window.adapter.browserDetails.browser.toLowerCase():ee(),findByQuerySelector:e=>document.querySelector(e),addGlobalEventListener:(e,t,i=document)=>{i.addEventListener(e,t)},removeGlobalEventListener:(e,t,i=document)=>{i.removeEventListener(e,t)},supportsNonNativeHLS:e=>{if(e)try{return e.isSupported()}catch(e){return Y("Could not access Hls.js."),!1}return!!window.Hls&&window.Hls.isSupported()},createHLSClient:(e={})=>new window.Hls(e),getHLSClientEventEnum:()=>window.Hls.Events,globalAssign:(e,t)=>{window[e]=t},globalUnassign:e=>{delete window[e]},getAssignedValue:e=>window[e]};const ne=(e,t,i)=>{const{liveSeek:{baseURL:n,fullURL:s}}=e,{host:o,protocol:r,port:a,app:l,streamName:d}=e;if(i||s)return i||s;const h=o,c="ws"===r?"http":"https",u=5080===a?5080:443,p=l,_=t||n;if(_){const e=_.length-1;return`${"/"===_.charAt(e)?_.substring(0,e):_}/${p}/${d}.m3u8`}return`${c}://${h}:${u}/${p}/${d}.m3u8`},se=e=>{const t=new URL(e),i=t.pathname.split("/").filter((e=>e.length>0)),n="https:"===t.protocol?"https":"http",s=t.hostname;return{protocol:n,port:t.port.length>0?t.port:443,app:i[0],host:s,streamName:i[i.length-1]}},oe=(e,t="whip")=>{var i;const{endpoint:n,proxy:s}=e;if(n)return n;{const{protocol:n,host:o,port:r,app:a,streamName:l}=e,d=n.match(/^http/)?n:"ws"===n?"http":"https";return(null==s?void 0:s.enabled)?`${d}://${o}:${r}/as/${null!==(i=s.version)&&void 0!==i?i:"v1"}/proxy/${t}/${a}/${l}`:`${d}://${o}:${r}/${a}/${t}/endpoint/${l}`}},re=e=>{const t={audio:!1,video:!1},i={audio:!1,video:!1};return e.getTracks().forEach((e=>{"video"===e.kind?(i.video=e.getSettings(),t.video=e.getConstraints()):"audio"===e.kind&&(i.audio=e.getSettings(),t.audio=e.getConstraints())})),{requested:t,accepted:i}},ae=e=>{const t=e.length;return function i(...n){return n.length>=t?e(...n):function(...e){return i(...n,...e)}}},le=ae(((e,t)=>{let i=0;const n=t.length,s=[];for(;i{this._responder.onDataChannelError(t,e.error.message)},t.onmessage=e=>{this._onDataChannelMessage(e)},t.onopen=()=>{this._responder.onDataChannelOpen(t)},t.onclose=i=>{this._responder.onDataChannelClose(t),this.trigger(new Ce(e.MessageTransportStateEventTypes.CLOSE,this._name,{socket:this,event:i}))}}_isErrorMessage(e){return!("error"!==(null==e?void 0:e.type)||!(null==e?void 0:e.message)&&!(null==e?void 0:e.code))}_isStatusMessage(e){return!("status"!==(null==e?void 0:e.type))}_onDataChannelMessage(e){if(this.handleMessageResponse(e))return!0;const t=this.getJsonFromSocketMessage(e);return t?(O(this._name,`[datachannel-response]: ${JSON.stringify(t,null,2)}`),this._handleMessageContent(t)):(H(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0)}_handleMessageContent(e){const{async:t,data:i,method:n,send:s,type:o,id:r}=e;if(this._isErrorMessage(i)){const e=(null==i?void 0:i.message)||(null==i?void 0:i.code);if(e)return this._responder.onDataChannelError(this._dataChannel,e),!0}if(n)return this._responder.onSendReceived(n,i),!0;if(s){const{senderName:t,dcLabel:i}=e,{data:n,method:o}=s,r={...n,senderName:t,dcLabel:i};return this._responder.onSendReceived(o,r),!0}return"metadata"===o&&i?(this._responder.onMetaData(i),!0):this._isStatusMessage(i)&&"NetConnection.Connect.Closed"===(null==i?void 0:i.code)?(this._responder.onConnectionClosed(),!0):!(!t||!r)&&this._handleAsyncResponse(r,e)}_handleAsyncResponse(e,t){const i=this._asyncTickets.find((t=>t.id===e));if(!i)return!1;const{promise:n}=i,{data:s}=t;if("error"===(null==s?void 0:s.type)){const e=s.message||s.code||"Unknown error";n.reject(new Error(e))}else n.resolve(s);return this._asyncTickets=this._asyncTickets.filter((t=>t.id!==e)),!0}async setUpWithPeerConfiguration(e,t){this.tearDown();(null==e?void 0:e.iceServers)&&e.iceServers.length>0||(e.iceServers=Pe);try{O(this._name,`[peerconnection:setUpWithPeerConfiguration]: ${JSON.stringify(e,null,2)}`);const i=new RTCPeerConnection(e);return t&&(this._dataChannel=i.createDataChannel(t.name,{ordered:!0}),this._addDataChannelHandlers(this._dataChannel)),this._addConnectionHandlers(i),this._peerConnection=i,i}catch(e){throw H(this._name,`Could not establish a PeerConnection. ${e.message}`),new Error(e.message)}}tearDown(){if(this._dataChannel){O(this._name,"[teardown:datachannel]"),this._removeDataChannelHandlers(this._dataChannel);try{this._dataChannel.close()}catch(e){H(this._name,`[datachannel.close] error: ${e.message}`)}finally{this._dataChannel=void 0}}if(this._peerConnection){O(this._name,"[teardown:peerconnection]"),this._removeConnectionHandlers(this._peerConnection);try{this._peerConnection.close()}catch(e){H(this._name,`[peerconnection.close] error: ${e.message}`)}finally{this._peerConnection=void 0}}}async setLocalDescription(e){var t;return O(this._name,"[setlocaldescription]"),null===(t=this._peerConnection)||void 0===t?void 0:t.setLocalDescription(e)}async setRemoteDescription(e){var t;return O(this._name,"[setremotedescription]"),null===(t=this._peerConnection)||void 0===t?void 0:t.setRemoteDescription(new RTCSessionDescription(e))}async addIceCandidate(e){var t;return O(this._name,"[addcandidate]"),null===(t=this._peerConnection)||void 0===t?void 0:t.addIceCandidate(e)}async waitToGatherIce(e=5e3){const t=this._peerConnection;return O(this._name,"[waittogatherice]"),new Promise((i=>{if("complete"===t.iceGatheringState)O(this._name,"[waittogatherice] ice gathering state complete."),t.addIceCandidate(null).then((()=>{i(t.localDescription)})).catch((e=>{H(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)}));else{O(this._name,"[waittogatherice] waiting...");const n=setTimeout((()=>{clearTimeout(n),t.addIceCandidate(null).then((()=>{i(t.localDescription)})).catch((e=>{H(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)}))}),e);t.onicegatheringstatechange=()=>{clearTimeout(n),O(this._name,"[waittogatherice] ice gathering state complete."),"complete"===t.iceGatheringState&&t.addIceCandidate(null).then((()=>{i(t.localDescription)})).catch((e=>{H(this._name,"Error adding null candidate: "+e.message||e),i(t.localDescription)}))}}}))}post(e){if(this._dataChannel){const t="string"==typeof e?e:JSON.stringify(e,null,2);O(this._name,`[datachannel.send] message: ${t}`);try{return this._dataChannel.send(t),Promise.resolve(!0)}catch(e){k(this._name,e.message)}}return Promise.resolve(!1)}get connection(){return this._peerConnection}get dataChannel(){return this._dataChannel}}const Re=[{label:"4K(UHD)",width:3840,height:2160},{label:"1080p(FHD)",width:1920,height:1080},{label:"UXGA",width:1600,height:1200},{label:"720p(HD)",width:1280,height:720},{label:"SVGA",width:800,height:600},{label:"VGA",width:640,height:480},{label:"360p(nHD)",width:640,height:360},{label:"CIF",width:352,height:288},{label:"QVGA",width:320,height:240},{label:"QCIF",width:176,height:144},{label:"QQVGA",width:160,height:120}],Ne=e=>"number"==typeof e?e:e.exact||e.ideal||e.max||e.min||e,De=ae(((e,t)=>{var i,n;if("boolean"==typeof e.video)return!0;const s=(null===(i=e.video)||void 0===i?void 0:i.width)?Ne(e.video.width):0,o=(null===(n=e.video)||void 0===n?void 0:n.height)?Ne(e.video.height):0,r=s===t.width&&o===t.height;return r&&O("[gum:isExact]",`Found matching resolution for ${t.width}, ${t.height}.`),r})),Ie=ae(((e,t)=>{const i=le(De(t))(e);return O("[gum:hasMatchingFormat]","Filtered list: "+JSON.stringify(i,null,2)),i.length>0})),Oe=ae(((e,t)=>{var i,n;if("boolean"==typeof e.video)return!0;const s=((null===(i=e.video)||void 0===i?void 0:i.width)?Ne(e.video.width):0)*((null===(n=e.video)||void 0===n?void 0:n.height)?Ne(e.video.height):0);return t.width*t.height{const i=Oe(t);return le(i)(e)})),ke=async e=>{O("[gum:determineSupportedResolution]","Determine next neighbor based on constraints: "+JSON.stringify(e,null,2));const t=He(Re)(e),i={...e};return await(async(e,t)=>{let i={...e};if(0==t.length)i.video;else{const n=t.shift();i={...e,video:{...e.video,width:{exact:n.width},height:{exact:n.height}}}}return{media:await ie.gUM(i),constraints:i}})(i,t)},Me=async e=>{let t;const i=Ie(Re),n=async t=>{if(t){const e="string"==typeof t?t:[t.name,t.message].join(": ");O("[gum:getUserMedia]",`Failure in getUserMedia: ${e}. Attempting other resolution tests...`)}return await ke(e)};if((e=>e.video&&"object"==typeof e.video&&(e.video.width||e.video.height))(e)){if(!i(e))return await n(void 0);{O("[gum:getUserMedia]","Found constraints in list. Checking quick support for faster setup with: "+JSON.stringify(e,null,2));const i=(e=>{var t,i;const n={...e};return"boolean"==typeof e.video||(n.video={...n.video},(null===(t=e.video)||void 0===t?void 0:t.width)&&(n.video.width={exact:Ne(e.video.width)}),(null===(i=e.video)||void 0===i?void 0:i.height)&&(n.video.height={exact:Ne(e.video.height)})),n})(e);try{return t=await ie.gUM(i),{media:t,constraints:i}}catch(e){return await n(e)}}}else try{return t=await ie.gUM(e),{media:t,constraints:e}}catch(e){return await n(e)}},Ue=(e,t,i)=>{const n="a=end-of-candidates",s=/^a=candidate:/,o=/^a=ice-ufrag:/,r=/^a=ice-pwd:/,a=/^m=(audio|video|application)\ /,l=e.split("\r\n");let d,h="",c="";const u=[];l.forEach((e=>{!d&&a.exec(e)?d=e:o.exec(e)?h=e:r.exec(e)?c=e:s.exec(e)&&(t&&-1!=e.indexOf(t)?u.push(e):t||u.push(e))})),i&&u[u.length-1]!==n&&u.push(n);return[h,c,d,"a=mid:0"].concat(u).join("\r\n")},Be="RTCPeerConnectionPublisher";class Ve extends Le{constructor(e){super(e,Be)}_removeConnectionHandlers(e){e.onconnectionstatechange=null,e.oniceconnectionstatechange=null,e.onsignalingstatechange=null,e.onicecandidate=null,e.ontrack=null}_addConnectionHandlers(e){let t;e.onsignalingstatechange=()=>{const t=e.signalingState;O(Be,`[peer.onsignalingstatechange] - State: ${t}`)},e.onconnectionstatechange=()=>{const{connectionState:t}=e;"connected"===t?(O(this._name,"[peerconnection:open]"),this._responder.onPeerConnectionOpen()):"failed"!==t&&"disconnected"!==t||(H(this._name,"[peerconnection:error]"),"failed"===t&&this._responder.onPeerConnectionFail())},e.oniceconnectionstatechange=i=>{const{iceConnectionState:n}=e;O(this._name,`[peer.oniceconnectionstatechange] - State: ${n}`),"failed"===n?(t&&clearTimeout(t),this._responder.onPeerConnectionClose(i)):"disconnected"===n?t=setTimeout((()=>{O(this._name,"[peer.oniceconnectionstatechange] - Reconnect timeout reached. Closing PeerConnection."),clearTimeout(t),this._responder.onPeerConnectionClose(i)}),3e3):t&&(O(this._name,"[peer.oniceconnectionstatechange] - Clearing timeout for reconnect."),clearTimeout(t))},e.onicecandidate=e=>{const{candidate:t}=e;O(this._name,`[peer.onicecandidate] - Peer Candidate: ${null==t?void 0:t.candidate}`),t&&this._responder.onIceCandidate(t)},e.ontrack=e=>{O(this._name,"[peer:ontrack]"),this._responder.onPeerConnectionTrackAdd(e.track)}}_onDataChannelMessage(e){const t=e;if(super._onDataChannelMessage(e))return!0;const i=this.getJsonFromSocketMessage(t);if(null===i)return H(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0;O(this._name,"[datachannel-response]: "+JSON.stringify(i,null,2));const{data:n}=i;return n&&"status"===n.type?"NetStream.Play.UnpublishNotify"===n.code?(this._responder.onUnpublish(),!0):"NetConnection.Publish.InsufficientBW"===n.code?(this._responder.onInsufficientBandwidth(n),!0):"NetConnection.Publish.SufficientBW"===n.code?(this._responder.onSufficientBandwidth(n),!0):"NetConnection.Publish.RecoveringBW"===n.code?(this._responder.onRecoveringBandwidth(n),!0):"Application.Statistics.Endpoint"===n.code?(this._responder.onStatisticsEndpointChange(n.statistics),!0):(O(Be,`[datachannel.message] status :: ${n.code}`),this._responder.onPublisherStatus(n),!0):(this._responder.onDataChannelMessage(this._dataChannel,t),!1)}addTrack(e){this._peerConnection?this._peerConnection.addTrack(e):H(Be,"PeerConnection not initialized. Cannot add track.")}async postUnpublish(e){const t=this.post({unpublish:e});return O(Be,`[peerconnection:unpublish] complete: ${t}`),t}async createOfferWithoutSetLocal(e=null){var t;O(Be,`[createoffer:withoutlocal]:: bandwidth request: ${JSON.stringify(e,null,2)}`);try{const i=await(null===(t=this._peerConnection)||void 0===t?void 0:t.createOffer());if(e){const t=((e,t)=>{const i=t.indexOf("m=audio");let n,s,o,r=t.indexOf("m=video"),a=t.indexOf("m=application");return i>-1&&e.audio&&(n=t.indexOf("\r\n",i),s=t.slice(0,n),o=t.slice(n+2,t.length),r=(t=[s,"b=AS:"+e.audio,o].join("\r\n")).indexOf("m=video"),a=t.indexOf("m=application")),r>-1&&e.video&&(n=t.indexOf("\r\n",r),s=t.slice(0,n),o=t.slice(n+2,t.length),a=(t=[s,"b=AS:"+e.video,o].join("\r\n")).indexOf("m=application")),a>-1&&e.dataChannel&&(n=t.indexOf("\r\n",a),s=t.slice(0,n),o=t.slice(n+2,t.length),t=[s,"b=AS:"+e.dataChannel,o].join("\r\n")),t})(e,i.sdp);i.sdp=t}return this._responder.onSDPSuccess(),i}catch(e){throw O(Be,"[createoffer:error]"),this._responder.onSDPError(e),e}}async updateBandwidthRequest(e=null){var t;O(Be,`[updatebandwidthrequest]:: bandwidth request: ${JSON.stringify(e,null,2)}`);try{const i=null===(t=this._peerConnection)||void 0===t?void 0:t.getSenders();if(e&&(null==i?void 0:i.length)&&i.length>0){const t=(e,t,i)=>new Promise(((n,s)=>{try{O(Be,`[updatebandwidthrequest:${i}]:: bandwidth(${t.encodings[0].maxBitrate})`),e.setParameters(t).then(n).catch(s)}catch(e){s(e)}})),n=[];null==i||i.forEach((async i=>{var s,o;if("video"===(null===(s=i.track)||void 0===s?void 0:s.kind)&&e.video){const e=i.getParameters();e.encodings||(e.encodings=[{}]),e.encodings[0].maxBitrate=75e4,e.encodings[0].maxFramerate=60,e.encodings[0].priority="high",n.push(t(i,e,"video"))}else if("audio"===(null===(o=i.track)||void 0===o?void 0:o.kind)&&e.audio){const e=i.getParameters();e.encodings||(e.encodings=[{}]),e.encodings[0].maxBitrate=128e3,n.push(t(i,e,"audio"))}})),await Promise.all(n).catch((e=>{k(Be,`[updatebandwidthrequest:error]:: ${e.message}`)}))}return!0}catch(e){k(Be,`[updatebandwidthrequest:error]:: ${e.message}`)}return!1}}class $e extends Error{constructor(e){super(e),this.name="InvalidNameError"}}const Fe="WhipWhepSignalingHelper",Ge=new Map;Ge.set(400,"Invalid offer SDP."),Ge.set(401,"Not authorized."),Ge.set(404,"Scope resolver failed for the publish name and / or scope."),Ge.set(405,"Remember to update the URL passed into the WHIP or WHEP client."),Ge.set(406,"Scope connection rejected."),Ge.set(409,"Session already initialized."),Ge.set(412,"Invalid request body."),Ge.set(417,"Session lookup or creation failure.");const We=new Map;We.set(400,"Offer already sent, double POST assumed."),We.set(401,"Not authorized."),We.set(404,"Scope resolver failed for the playback name and / or scope."),We.set(406,"Playback failed due to an exception during creation."),We.set(409,"Stream is not available to playback.");const xe=["transcode"];var je;!function(e){e.ICE_SERVER="ice-server",e.STATISTICS="statistics"}(je||(je={}));const Ke=e=>e&&(e=>{const t=/[?&](.*)=([^]*)/.exec(e);return t&&t.length>0})(e)?"&":"?",ze=e=>e.split(";").map((e=>e.trim())).map((e=>"<"===e.charAt(0)?["url",e.substring(1,e.length-1)]:e.split("="))).reduce(((e,t)=>e.set(t[0].replaceAll('"',""),t[1].replaceAll('"',""))),new Map);class Je{constructor(e,t=!1,i=!0){O(Fe,`[whipwhep] ${e}`),this._url=e,this._origin=void 0,this._forceHost=i,this._resource=void 0,this._enableSignalingChannel=t}async getOptions(e={}){let t=`${this._url}${Ke(this._url)}signal=${this._enableSignalingChannel}`;e&&Object.keys(e).forEach((i=>{t+=`&${i}=${e[i]}`})),O(Fe,`[whipwhep-options] ${t}`);try{const e=await fetch(t,{method:"OPTIONS",mode:"cors"}),{status:i,headers:n}=e;if(200===i||204===i){const e=/^(L|l)ink/,t=/^(S|s)ession-(H|h)ost/,i=[];let s;return n.forEach(((n,o)=>{if(t.exec(o)&&(this._origin=n),e.exec(o))if(n.indexOf(`rel="${je.ICE_SERVER}"`)>-1){const e=ze(n),t=e.get("url"),{protocol:s,host:o}=(e=>{const t=e.split(":");return t.length>1?{protocol:t[0],host:t[1]}:{protocol:void 0,host:e}})(t),r=e.get("username"),a=e.get("credential");s&&o&&r&&a?i.push({username:r,credential:a,urls:t}):t&&i.push({urls:t})}else if(n.indexOf(`rel="${je.STATISTICS}"`)>-1){const e=ze(n).get("url");e&&(s=e)}})),O(Fe,`[whipwhep-links]: ${JSON.stringify(i)}`),O(Fe,`[whipwhep-origin]: ${this._origin}`),{links:i.length>0?i:void 0,origin:this._origin,statisticsEndpoint:s}}throw new Error(`Failed to get options: ${i}`)}catch(e){throw k(Fe,e.message),e}}async postSDPOffer(e,t={},i=!0){let n=`${this._url}${Ke(this._url)}signal=${this._enableSignalingChannel}`;t&&Object.keys(t).forEach((e=>{-1===xe.indexOf(e)&&(n+=`&${e}=${t[e]}`)})),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n+=`&host=${this._origin}`),O(Fe,`[whipwhep:post-offer] ${n}: `+JSON.stringify(e,null,2));try{const t={method:"POST",mode:"cors",headers:{"Content-Type":"application/sdp"}};e&&e.length>0&&(t.body=e);const s=await fetch(n,t),{status:o,headers:r}=s;if(r&&r.forEach(((e,t)=>{O(Fe,`[header] ${t}: ${e}`)})),o>=200&&o<300){const e=await s.text(),t=r.get("Location")||r.get("location");if(t){if(t.match(/^(http|https)/))this._resource=t;else{O(Fe,`[whipwhep-response] Location provided as relative path: ${t}`);const e=new URL(this._url);e.pathname=t.split("?")[0],this._resource=e.toString().replace(/\/endpoint\//,"/resource/")}return O(Fe,`[whipwhep-response] ${this._resource}: ${e}`),{sdp:e,location:this._resource}}return H(Fe,"Location not provided in header response to Offer."),this._resource=new URL(this._url).toString().replace(/\/endpoint\//,"/resource/"),{sdp:e,location:this._resource}}if(i&&Ge.get(o)){if(O(Fe,Ge.get(o)),404===o||409===o)throw new $e(Ge.get(o));throw new Error(Ge.get(o))}if(!i&&We.get(o)){if(O(Fe,We.get(o)),404===o||409===o)throw new $e(We.get(o));throw new Error(We.get(o))}{const e=await s.text();throw Error(e)}}catch(e){throw k(Fe,e.message),e}}async postSDPAnswer(e,t={}){O(Fe,`[whipwhep:post-answer] ${this._resource}: `+JSON.stringify(e,null,2));let i=this._resource,n=Ke(i);t&&Object.keys(t).forEach((e=>{-1===xe.indexOf(e)&&(n=Ke(i),i+=`${n}${e}=${t[e]}`)})),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n=i.indexOf("?")>-1?"&":"?",i+=`${n}host=${this._origin}`);try{const t=await fetch(i,{method:"PATCH",mode:"cors",headers:{"Content-Type":"application/sdp"},body:e}),{status:n}=t;if(n>=200&&n<300)return{success:!0,code:n};if(We.get(n))throw O(Fe,We.get(n)),new Error(We.get(n));{const e=await t.text();throw Error(e)}}catch(e){throw k(Fe,e.message),e}}async trickle(e,t={}){O(Fe,`[whipwhep-trickle] ${this._resource}: `+JSON.stringify(e,null,2));let i=this._resource,n=Ke(i);t&&Object.keys(t).forEach((e=>{-1===xe.indexOf(e)&&(n=Ke(i),i+=`${n}${e}=${t[e]}`)})),this._forceHost&&this._origin&&!(null==t?void 0:t.host)&&(n=Ke(i),i+=`${n}host=${this._origin}`);try{const t=await fetch(i,{method:"PATCH",mode:"cors",headers:{"Content-Type":"application/trickle-ice-sdpfrag"},body:e}),{status:n}=t;if(n>=200&&n<300){const e=await t.text();return O(Fe,`[whipwhep-response] ${this._resource}: ${e}`),{candidate:e}}if(405===n)throw O(Fe,"Remember to update the URL passed into the WHIP or WHEP client"),new Error("Remember to update the URL passed into the WHIP or WHEP client");{const e=await t.text();throw Error(e)}}catch(e){throw k(Fe,e.message),e}}async tearDown(e={},t=!1){if(!this._resource)return;let i=this._resource,n=Ke(i);e&&Object.keys(e).forEach((t=>{-1===xe.indexOf(t)&&(n=Ke(i),i+=`${n}${t}=${e[t]}`)})),this._forceHost&&this._origin&&!(null==e?void 0:e.host)&&(n=Ke(i),i+=`${n}host=${this._origin}`),O(Fe,"[whipwhep-teardown]");try{await fetch(i,{method:"DELETE",mode:"cors"})}catch(e){if(k(Fe,e.message),!t)throw e}this._url=void 0,this._origin=void 0,this._resource=void 0,this._forceHost=!1,this._enableSignalingChannel=!1}async post(){return O(Fe,"[whipwhep:post] transport called."),Promise.resolve(!1)}async postAsync(){return O(Fe,"[whipwhep:postAsync] transport called."),Promise.resolve(null)}getUrl(){return this._url}}const Ye="R5ProPublishView";class qe{constructor(e="red5pro-publisher"){try{this._targetElement=ie.resolveElement(e)}catch(e){throw k(Ye,`Could not instantiate a new instance of PublishView. Reason: ${e.message}`),e}}preview(e){const t=this.isAutoplay;O(Ye,`[preview]: autoplay(${t})`),ie.setVideoSource(this._targetElement,e,t)}unpreview(){ie.setVideoSource(this._targetElement,null,this.isAutoplay)}get isAutoplay(){return ie.hasAttributeDefined(this._targetElement,"autoplay")}get view(){return this._targetElement}}var Xe,Qe;!function(e){e.INBOUND="inbound-rtp",e.OUTBOUND="outbound-rtp",e.CODEC="codec",e.MEDIA_SOURCE="media-source",e.CANDIDATE_PAIR="candidate-pair",e.CERTIFICATE="certificate",e.DATA_CHANNEL="data-channel",e.LOCAL_CANDIDATE="local-candidate",e.REMOTE_CANDIDATE="remote-candidate",e.PEER_CONNECTION="peer-connection",e.REMOTE_INBOUND="remote-inbound-rtp",e.REMOTE_OUTBOUND="remote-outbound-rtp",e.TRANSPORT="transport"}(Xe||(Xe={})),function(e){e.STALE_STATS="STALE_STATS",e.STATE_REGRESSION="STATE_REGRESSION",e.EXCESSIVE_RTT="EXCESSIVE_RTT",e.ICE_TIMEOUT="ICE_TIMEOUT"}(Qe||(Qe={}));class Ze{constructor(e,t,i,n){this._name="RTCStatsMonitor",this._queue=[],this._startTime=0,this._stopped=!1,this._interval=0,this._candidatePairHealth=new Map,this._name=e,this._renegotiationPolicy=n,this._config={...pe,...t},this._client=i,this._identifier={name:this._name,created:(new Date).getTime(),fingerprint:ie.getOrGenerateFingerprint(),device:ie.getBrowserDetails(),client:t}}_emptyStatsReportQueue(){for(;this._queue.length>0;){const e=this._client.getMessageTransport();if(e){const t=this._queue.shift();e.post(t)}else H(this._name,"Failed to post stats data to message transport. Message transport is not available.")}}_getStats(){const{_connection:e}=this;if(e)try{e.getStats(null).then((e=>{e.forEach((e=>{this._handleStatsReport(e)}))})).catch((e=>{k(this._name,`Failed to get stats report. ${e.message||e}`)}))}catch(e){k(this._name,`Failed to get stats report. ${e.message||e}`)}}_handleStatsReport(e){console.log(`[${this._name}]: ${JSON.stringify(e,null,2)}`)}_appendClientDetails(e){this._identifier.client={...this._identifier.client,...e}}async start(e){this._startTime=(new Date).getTime(),this._stopped=!1,this._connection=e,this.postAction("started"),this._getStats(),this._interval=setInterval((()=>{this._stopped||this._getStats()}),this._config.interval)}stop(){this._stopped=!0,clearInterval(this._interval),this.postAction("ended")}async post(t){const i={...this._identifier,type:"stats-report",timestamp:(new Date).getTime(),data:t},{endpoint:n,additionalHeaders:s}=this._config;if(n===_e.DEV_NULL)return;if(this._client&&this._client.onStatsReport&&null===n)return void this._client.onStatsReport(this._connection,i);let o={"Content-Type":"application/json"};if(s&&(o={...o,...s}),n)try{const e=await fetch(n,{method:"POST",headers:o,body:JSON.stringify(i)});e.status>=200&&e.status<300?O(this._name,`Posted stats data to endpoint: ${n}.`):k(this._name,`Failed to post stats data to endpoint: ${n}. ${e.status}`)}catch(e){k(this._name,`Failed to post stats data to endpoint: ${n}. ${e.message||e}`)}else if(this._client&&this._client.getMessageTransport())try{let t=!1;const n=this._client.getMessageTransport();n&&(t=await n.post(i)),t||(this._queue.push(i),this._client.on(e.MessageTransportStateEventTypes.CHANGE,(()=>{this._client.off(e.MessageTransportStateEventTypes.CHANGE),this._emptyStatsReportQueue()})),H(this._name,"Failed to post stats data to message transport. Message transport is not available. Pushed to Queue."))}catch(e){k(this._name,`Failed to post stats data to message transport. ${e.message||e}`)}}async postAction(e,t=void 0){return this.post({action:{type:e,data:t,timestamp:(new Date).getTime()}})}async postEvent(e,t){return this.post({event:{type:e,data:t||void 0,timestamp:(new Date).getTime()}})}updateEndpoint(e,t=!0){const{endpoint:i}=this._config;t?this._config.endpoint=e:t||i||(this._config.endpoint=e)}_checkCandidatePairHealth(e){var t;const{id:i,state:n,currentRoundTripTime:s,totalRoundTripTime:o}=e,r=(new Date).getTime();this._candidatePairHealth.has(i)||this._candidatePairHealth.set(i,{id:i,staleSampleCount:0,stateTransitionTime:r,inProgressStartTime:"in-progress"===n?r:void 0});const a=this._candidatePairHealth.get(i);if(void 0!==a.previousRTT&&void 0!==a.previousTotalRTT&&void 0!==s&&void 0!==o&&(s===a.previousRTT&&o===a.previousTotalRTT?(a.staleSampleCount++,a.staleSampleCount>=3&&a.lastIssueReported!==Qe.STALE_STATS&&(this._client.emit(we.CONNECTION_HEALTH_STALE_STATS,{candidatePairId:i,frozenRTT:s,frozenTotalRTT:o,staleDurationSeconds:a.staleSampleCount,message:"RTT values frozen - connection may be dead"}),a.lastIssueReported=Qe.STALE_STATS)):(a.staleSampleCount=0,a.lastIssueReported===Qe.STALE_STATS&&(a.lastIssueReported=void 0))),"succeeded"===a.previousState&&"succeeded"!==n&&(this._client.emit(we.CONNECTION_HEALTH_STATE_REGRESSION,{candidatePairId:i,previousState:a.previousState,currentState:n,message:`ICE candidate pair regressed from '${a.previousState}' to '${n}' - connection lost`}),a.lastIssueReported=Qe.STATE_REGRESSION,a.stateTransitionTime=r),void 0!==s&&s>1&&a.lastIssueReported!==Qe.EXCESSIVE_RTT?(this._client.emit(we.CONNECTION_HEALTH_EXCESSIVE_RTT,{candidatePairId:i,currentRTT:s,message:`Excessive RTT detected: ${(1e3*s).toFixed(0)}ms - possible network issues`}),a.lastIssueReported=Qe.EXCESSIVE_RTT):void 0!==s&&s<=1&&a.lastIssueReported===Qe.EXCESSIVE_RTT&&(a.lastIssueReported=void 0),"in-progress"===n){a.inProgressStartTime||(a.inProgressStartTime=r);const e=r-a.inProgressStartTime;e>((null===(t=this._renegotiationPolicy)||void 0===t?void 0:t.iceTimeoutInterval)||5e3)&&a.lastIssueReported!==Qe.ICE_TIMEOUT&&(this._client.emit(we.CONNECTION_HEALTH_ICE_TIMEOUT,{candidatePairId:i,durationSeconds:Math.floor(e/1e3),message:`ICE negotiation timeout - candidate pair stuck in 'in-progress' for ${Math.floor(e/1e3)}s`}),a.lastIssueReported=Qe.ICE_TIMEOUT)}else a.inProgressStartTime=void 0,a.lastIssueReported===Qe.ICE_TIMEOUT&&(a.lastIssueReported=void 0);a.previousState=n,a.previousRTT=s,a.previousTotalRTT=o,n!==a.previousState&&(a.stateTransitionTime=r)}dispose(){this.stop(),this._candidatePairHealth.clear(),this._connection=void 0,this._client=void 0}}const et=/(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b) \d+ typ srflx/,tt=e=>{const t=e.match(et);return t&&t.length>1?t[1]:null},it=[e.PublisherEventTypes.PUBLISH_START,e.PublisherEventTypes.PUBLISH_FAIL,e.PublisherEventTypes.PUBLISH_INSUFFICIENT_BANDWIDTH,e.PublisherEventTypes.PUBLISH_SUFFICIENT_BANDWIDTH,e.PublisherEventTypes.PUBLISH_RECOVERING_BANDWIDTH,e.PublisherEventTypes.STATISTICS_ENDPOINT_CHANGE];class nt extends Ze{constructor(t,i){if(super("RTCPublisherStats",t,i),this.estimatedAudioBitrate=0,this.estimatedVideoBitrate=0,this.lastAudioReport=null,this.lastVideoReport=null,this._eventHandler=t=>{const{type:i,data:n}=t;if(it.indexOf(i)>-1){if(i===e.PublisherEventTypes.STATISTICS_ENDPOINT_CHANGE){const{statisticsEndpoint:e}=n;this.updateEndpoint(e,!1)}this.postEvent(i)}},this._candidateCreateHandler=({data:{candidate:e}})=>{const{candidate:t}=e,i=tt(t);i&&(this._identifier.publicIP=i)},this._hostEndpointChangedHandler=({data:{endpoint:e,iceServers:t}})=>{this._appendClientDetails({node:e,iceServers:t})},this._client.on("*",this._eventHandler),this._client.on(e.RTCPublisherEventTypes.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.on(e.RTCPublisherEventTypes.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),this._client.getPeerConnection())this.start(this._client.getPeerConnection());else{const t=({data:i})=>{this._client.off(e.RTCPublisherEventTypes.PEER_CONNECTION_AVAILABLE,t),this.start(i)};this._client.on(e.RTCPublisherEventTypes.PEER_CONNECTION_AVAILABLE,t)}}_handleStatsReport(e){const{type:t}=e,{include:i}=this._config,n=i&&i.length>0;if(n&&i.indexOf(t)>=-1)this.post(e);else if(!n)if(t===Xe.CODEC){const{id:i,clockRate:n,mimeType:s,payloadType:o}=e;this.post({id:i,type:t,clockRate:n,mimeType:s,payloadType:o})}else if(t===Xe.CANDIDATE_PAIR){const{availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o}=e;this._checkCandidatePairHealth(e),this.post({type:t,availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o})}else if(t===Xe.MEDIA_SOURCE){const{kind:i}=e;if("audio"===i)this.post({type:t,kind:i});else if("video"===i){const{framesPerSecond:n,height:s,width:o}=e;this.post({type:t,kind:i,framesPerSecond:n,height:s,width:o})}}else if([Xe.OUTBOUND,"outboundrtp"].indexOf(t)>-1){const{timestamp:i,kind:n,codecId:s,mediaType:o,active:r,bytesSent:a,packetsSent:l,totalPacketsSendDelay:d}=e,h={type:t,kind:n,codecId:s,mediaType:o,active:r,bytesSent:a,packetsSent:l,totalPacketsSendDelay:d};if("audio"===n){if(this.lastAudioReport){const{bytesSent:e,timestamp:t}=this.lastAudioReport,n=8*(a-e)/(i-t);this.estimatedAudioBitrate=n}this.post({...h,estimatedBitrate:Math.floor(this.estimatedAudioBitrate)}),this.lastAudioReport=e}else if("video"===n){const{firCount:t,pliCount:n,frameWidth:s,frameHeight:o,framesEncoded:r,framesPerSecond:l,framesSent:d,keyFramesEncoded:c,qualityLimitationReason:u,qualityLimitationDurations:p}=e;let _={...h,firCount:t,pliCount:n,frameWidth:s,frameHeight:o,framesEncoded:r,framesPerSecond:l,framesSent:d,keyFramesEncoded:c,qualityLimitationReason:"none"!==u?u:void 0,qualityLimitationDurations:"none"!==u?p:void 0};if(this.lastVideoReport){const{bytesSent:e,timestamp:t}=this.lastVideoReport,n=8*(a-e)/(i-t);this.estimatedVideoBitrate=n}this.post({..._,estimatedBitrate:Math.floor(this.estimatedVideoBitrate)}),this.lastVideoReport=e}}}dispose(){this._client.off("*",this._eventHandler),this._client.off(e.RTCPublisherEventTypes.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.off(e.RTCPublisherEventTypes.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),super.dispose()}}const st="WHIPClient",ot=me,rt=e=>O(st,e),at=e=>k(st,e),lt=e=>H(st,e);class dt extends U{constructor(e,t,i){super();const n=e?se(e):ot,s=i||ot,o={...s,...n,endpoint:e,mediaElementId:t?t.id:s.mediaElementId};e&&this.internalInit(o),this._onOrientationChange=this._onOrientationChange.bind(this)}async internalInit(e){await this.init(e),await this.publish()}async generateMediaStream(t){var i,n;const{onGetUserMedia:s}=t;if(s){rt("Requesting gUM from user-defined configuration:onGetUserMedia.");const t=await s();return this.trigger(new Ee(e.RTCPublisherEventTypes.CONSTRAINTS_ACCEPTED,this,re(t))),t}{const{mediaConstraints:s}=t;let o;rt(`Requesting gUM using mediaConstraints: ${JSON.stringify(s,null,2)}`);let r=s;const a=await Me(r);return a&&a.media||(o=await ie.gUM(r)),o=null!==(i=null==a?void 0:a.media)&&void 0!==i?i:o,r=null!==(n=null==a?void 0:a.constraints)&&void 0!==n?n:s,rt(`Constraints accepted: ${JSON.stringify(r,null,2)}`),this.trigger(new Ee(e.RTCPublisherEventTypes.CONSTRAINTS_ACCEPTED,this,{constraints:r,...re(o)})),o}}async getAndPreviewStreamIfAvailable(){var t;let i=this._mediaStream;if(!i){try{i=null!=i?i:await this.generateMediaStream(this._options)}catch(i){const n=null!==(t=i.message)&&void 0!==t?t:"Could not generate media stream.";throw this.trigger(new Ee(e.RTCPublisherEventTypes.CONSTRAINTS_REJECTED,this,{constraints:this._options.mediaConstraints})),new Error(n)}if(!i)throw new Error("Could not generate media stream.")}return this.trigger(new Ee(e.RTCPublisherEventTypes.MEDIA_STREAM_AVAILABLE,this,i)),this.preview(i),i}reorderCodecPreferences(e,t,i){e.getTransceivers().forEach((e=>{if(e.sender&&e.sender.track){const{kind:n}=e.sender.track;if(t&&"video"===n&&e.setCodecPreferences)try{const{codecs:i}=RTCRtpSender.getCapabilities("video"),n=i.findIndex((e=>e.mimeType===`video/${t}`));if(n>-1){const t=i.slice(0),s=i[n];t.splice(n,1),t.unshift(s),e.setCodecPreferences(t)}}catch(e){lt(`[videoEncoding] Could not set codec preferences for ${t}. ${e.message||e}`)}else if(i&&"audio"===n&&e.setCodecPreferences)try{const{codecs:t}=RTCRtpSender.getCapabilities("audio"),n=t.findIndex((e=>e.mimeType===`audio/${i}`));if(n>-1){const i=t[n];t.splice(n,1),t.unshift(i),e.setCodecPreferences(t)}}catch(e){lt(`[audioEncoding] Could not set codec preferences for ${i}. ${e.message||e}`)}}}))}async postOffer(t){var i;try{const{sdp:n}=t;let{videoEncoding:s}=this._options;const{mungeOffer:o,streamMode:r,keyFramerate:a,iceTransport:l,connectionParams:d,mediaConstraints:h,forceVP8:c,audioEncoding:u,offerSDPResolution:p}=this._options;c&&!s&&(s=e.PublishVideoEncoder.VP8);let _=n;o&&(rt(`[MUNGE:before] offer: ${_}`),_=o(_),rt(`[MUNGE:after] offer: ${_}`)),p&&(rt(`[MUNGE] Setting resolution on offer: ${_}`),_=((e,t)=>{if(!t)return e;const{width:i,height:n}=t;if(!i||!n)return e;const s=`a=framesize:${i}-${n}`,o=e.split("\r\n");let r=o.length;const a=/^m=video/;for(;--r>-1;)if(a.exec(o[r])){for(;++r-1){o.splice(r+1,0,s);break}break}return o.join("\r\n")})(_,((e,t)=>{let i;if(e)try{const t=e.getVideoTracks()&&e.getVideoTracks()[0];if(t){const e=t.getSettings();i={width:e.width,height:e.height}}}catch(e){H("[determineMediaResolution]",`Could not determine resolution from MediaStream. ${e.message||e}`)}if(!i)try{const e=t.video,{width:n,height:s}=e;if(n&&s)if("number"==typeof n&&"number"==typeof s)i={width:n,height:s};else{i={width:n.exact||n.min||n.max||n.ideal||640,height:s.exact||s.min||s.max||s.ideal||480}}}catch(e){H("[determineMediaResolution]",`Could not determine resolution from MediaConstraints. ${e.message||e}`)}return i&&O("[determineMediaResolution]",`constraints: ${JSON.stringify(i,null,2)}`),i})(this._mediaStream,h)),rt(`[MUNGE:after] offer: ${_}`));const m={...d,mode:r,transport:l,keyFramerate:a};return s&&(m.videoEncoding=s),u&&(m.audioEncoding=u),await(null===(i=this._whipWhepService)||void 0===i?void 0:i.postSDPOffer(_,m))}catch(t){throw at(t.message||t),t instanceof $e?this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_INVALID_NAME,this)):(this.trigger(new Ee(e.PublisherEventTypes.CONNECT_FAILURE,this,t)),this.unpublish()),t}}async postCandidateFragments(e){var t;const{connectionParams:i}=this._options,n=Ue(e,void 0,!0);return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.trickle(n,i))}async init(e){var t;this._options={...ot,...e};const i=oe(this._options),{includeDataChannel:n,disableProxy:s}=this._options;return this._whipWhepService=new Je(i,n,s),this._messageTransport=this._whipWhepService,(null===(t=this._options)||void 0===t?void 0:t.stats)&&this.monitorStats(this._options.stats),this._mediaStream=await this.getAndPreviewStreamIfAvailable(),this}async initWithStream(e,t){return this._mediaStream=t,this.init(e)}async publish(t){var i,n,s,o,r;t&&(this._options.streamName=t);const{forceVP8:a,audioEncoding:l,rtcConfiguration:d,dataChannelConfiguration:h,includeDataChannel:c,signalingSocketOnly:u,enableChannelSignaling:p,connectionParams:_,bandwidth:m,mungeAnswer:g}=this._options;let{videoEncoding:v}=this._options;a&&(v=e.PublishVideoEncoder.VP8,this._options.videoEncoding=v),this._mediaStream||(this._mediaStream=await this.getAndPreviewStreamIfAvailable());try{const t=null!=_?_:{};if(_){const{transcode:e}=_;e&&(t.transcode=e)}const r=await(null===(i=this._whipWhepService)||void 0===i?void 0:i.getOptions(t)),a=!!(null===(n=this._options)||void 0===n?void 0:n.rtcConfiguration)&&Array.isArray(this._options.rtcConfiguration.iceServers)&&this._options.rtcConfiguration.iceServers.length>0;(null==r?void 0:r.links)&&!a&&(this._options.rtcConfiguration={...d,iceServers:r.links}),(null==r?void 0:r.origin)&&this.trigger(new Ee(e.RTCPublisherEventTypes.HOST_ENDPOINT_CHANGED,this,{endpoint:r.origin})),(null==r?void 0:r.statisticsEndpoint)&&this._onStatisticsEndpointChange(r.statisticsEndpoint);const E=c||p||u?h:void 0;this._peerConnectionHelper=new Ve({onDataChannelError:this._onDataChannelError.bind(this),onSendReceived:this._onSendReceived.bind(this),onMetaData:this._onMetaData.bind(this),onConnectionClosed:this._onConnectionClosed.bind(this),onDataChannelOpen:this._onDataChannelOpen.bind(this),onDataChannelClose:this._onDataChannelClose.bind(this),onDataChannelMessage:this._onDataChannelMessage.bind(this),onPeerConnectionOpen:this._onPeerConnectionOpen.bind(this),onPeerConnectionFail:this._onPeerConnectionFail.bind(this),onPeerConnectionClose:this._onPeerConnectionClose.bind(this),onIceCandidate:this._onIceCandidate.bind(this),onSDPSuccess:this._onSDPSuccess.bind(this),onSDPError:this._onSDPError.bind(this),onStatisticsEndpointChange:this._onStatisticsEndpointChange.bind(this),onPublisherStatus:this._onPublisherStatus.bind(this),onPeerConnectionTrackAdd:this._onPeerConnectionTrackAdd.bind(this),onInsufficientBandwidth:this._onInsufficientBandwidth.bind(this),onSufficientBandwidth:this._onSufficientBandwidth.bind(this),onRecoveringBandwidth:this._onRecoveringBandwidth.bind(this),onUnpublish:this._onUnpublish.bind(this)}),await this._peerConnectionHelper.setUpWithPeerConfiguration(this._options.rtcConfiguration,E),this.trigger(new Ee(e.RTCPublisherEventTypes.PEER_CONNECTION_AVAILABLE,this,this.getPeerConnection())),this._mediaStream.getTracks().forEach((e=>{var t;null===(t=this.getPeerConnection())||void 0===t||t.addTransceiver(e,{direction:"sendonly"})})),this.reorderCodecPreferences(this.getPeerConnection(),v,l);const S=await(null===(s=this._peerConnectionHelper)||void 0===s?void 0:s.createOfferWithoutSetLocal(m));await this._peerConnectionHelper.setLocalDescription(S),this.trigger(new Ee(e.RTCPublisherEventTypes.OFFER_START,this,S));const{sdp:C}=await this.postOffer(S);let b=C;g&&(rt(`[MUNGE:before] answer: ${b}`),b=g(b),rt(`[MUNGE:after] answer: ${b}`)),await this._peerConnectionHelper.setRemoteDescription({type:"answer",sdp:b}),this.trigger(new Ee(e.RTCPublisherEventTypes.OFFER_END,this,b));const T=await this._peerConnectionHelper.waitToGatherIce(),{sdp:f}=T;return await this.postCandidateFragments(f),this.trigger(new Ee(e.RTCPublisherEventTypes.ICE_TRICKLE_COMPLETE,this)),ie.addOrientationChangeHandler(this._onOrientationChange),(null===(o=this._options)||void 0===o?void 0:o.includeDataChannel)||this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_START,this)),this}catch(t){throw at(null!==(r=t.message)&&void 0!==r?r:"Could not publish."),this.trigger(new Ee(e.PublisherEventTypes.CONNECT_FAILURE,this,t)),this.unpublish(!0),t}}async unpublish(t=!1){var i;rt("[unpublish]"),this._peerConnectionHelper&&await this._peerConnectionHelper.tearDown(),this._whipWhepService&&await this._whipWhepService.tearDown(null,t),(null===(i=this._options)||void 0===i?void 0:i.clearMediaOnUnpublish)&&this.unpreview(),this._mediaStream=void 0,this._peerConnectionHelper=void 0,this._whipWhepService=void 0,this._messageTransport=void 0,this._publishView=void 0,this.trigger(new Ee(e.PublisherEventTypes.UNPUBLISH_SUCCESS,this)),ie.removeOrientationChangeHandler(this._onOrientationChange)}preview(e){rt("[preview]");const{mediaElementId:t}=this._options;t&&(this._publishView=new qe(t),this._publishView.preview(e))}unpreview(){rt("[unpreview]"),this._mediaStream&&this._mediaStream.getTracks().forEach((e=>{e.stop()})),this._publishView&&this._publishView.unpreview(),this._publishView=void 0}monitorStats(e){rt("[monitorStats]");const{host:t,endpoint:i,app:n,streamName:s,connectionParams:o}=this._options,r=null!=e?e:pe;return this._statisticsConfiguration={...r,host:t,hostEndpoint:i,app:n,streamName:s,connectionParams:o},this._statsMonitor?lt("Cannot monitor stats without a Peer Connection. Please call `init` before calling `monitorStats`."):this._statsMonitor=new nt(this._statisticsConfiguration,{onStatsReport:this._onStatsReport.bind(this),getPeerConnection:this.getPeerConnection.bind(this),getMessageTransport:this.getMessageTransport.bind(this),on:this.on.bind(this),off:this.off.bind(this),trigger:this.trigger.bind(this),emit:this.emit.bind(this)}),this}unmonitorStats(){return this._statsMonitor&&this._statsMonitor.dispose(),this._statsMonitor=void 0,this._statisticsConfiguration=void 0,this}muteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0}})}unmuteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1}})}muteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!0}})}unmuteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!1}})}send(e,t){var i;return null===(i=this.getMessageTransport())||void 0===i?void 0:i.post({send:{method:e,data:"string"==typeof t?JSON.parse(t):t}})}async callServer(e,t){var i;try{if(!this.getMessageTransport())throw new Error("Message transport not available");return null===(i=this.getMessageTransport())||void 0===i?void 0:i.postAsync({callAdapter:{method:e,arguments:t}})}catch(e){at(e.message||e)}}sendLog(e,t){var i;try{const n=Object.keys(R).find((t=>t.toLowerCase()===e.toLowerCase()))?e:R.DEBUG,s="string"==typeof t?t:JSON.stringify(t);null===(i=this.getMessageTransport())||void 0===i||i.post({log:n.toUpperCase(),message:s})}catch(e){const t=e.message||e;at("Could not send log to server. Message parameter expected to be String or JSON-serializable object."),at(t)}}get options(){return this._options}getOptions(){return this._options}getPeerConnection(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.connection}getDataChannel(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.dataChannel}getMediaStream(){return this._mediaStream}getMessageTransport(){return this._messageTransport}_onDataChannelError(t,i){at(`Data channel error: ${i}`),this.trigger(new Ee(e.RTCPublisherEventTypes.DATA_CHANNEL_ERROR,this,{dataChannel:t,error:i}))}_onSendReceived(t,i){rt(`Send received: ${t} ${JSON.stringify(i)}`),"onMetaData"===t?this._onMetaData(i):this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_SEND_INVOKE,this,{methodName:t,data:i}))}_onMetaData(t){rt(`Metadata received: ${JSON.stringify(t)}`),this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_METADATA,this,t))}_onConnectionClosed(){rt("Connection closed"),this.unpublish(),this.trigger(new Ee(e.PublisherEventTypes.CONNECTION_CLOSED,this))}_onDataChannelOpen(t){rt(`Data channel opened: ${t.label}`),this.trigger(new Ee(e.RTCPublisherEventTypes.DATA_CHANNEL_OPEN,this,{dataChannel:t})),this.trigger(new Ee(e.RTCPublisherEventTypes.DATA_CHANNEL_AVAILABLE,this,{name:t.label,dataChannel:t})),this._messageTransport=this._peerConnectionHelper,this.trigger(new Ce(e.MessageTransportStateEventTypes.CHANGE,this,{controller:this,transport:this._messageTransport})),this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_START,this))}_onDataChannelClose(t){rt(`Data channel closed: ${t.label}`),this.trigger(new Ee(e.RTCPublisherEventTypes.DATA_CHANNEL_CLOSE,this,{dataChannel:t}))}_onDataChannelMessage(t,i){rt(`Data channel message: ${i.data}`),this.trigger(new Ee(e.RTCPublisherEventTypes.DATA_CHANNEL_MESSAGE,this,{dataChannel:t,message:i}))}_onPeerConnectionTrackAdd(t){rt(`Peer connection track added: ${t.id}`),this.trigger(new Ee(e.RTCPublisherEventTypes.TRACK_ADDED,this,{track:t}))}_onPeerConnectionOpen(){rt("Peer connection opened"),this.trigger(new Ee(e.RTCPublisherEventTypes.PEER_CONNECTION_OPEN,this,this.getPeerConnection()))}_onPeerConnectionFail(){at("Peer connection failed"),this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_FAIL,this))}_onPeerConnectionClose(t){rt(`Peer connection closed: ${t.type}`),this._peerConnectionHelper&&this._peerConnectionHelper.tearDown(),this.trigger(new Ee(e.PublisherEventTypes.CONNECTION_CLOSED,this,t))}_onIceCandidate(t){rt(`ICE candidate: ${JSON.stringify(t,null,2)}`),this.trigger(new Ee(e.RTCPublisherEventTypes.CANDIDATE_CREATE,this,{candidate:t}))}_onUnpublish(){rt("Unpublish received")}_onPublisherStatus(t){rt("[publisherstatus] - "+JSON.stringify(t,null,2)),t.code&&"NetStream.Publish.IsAvailable"===t.code?this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_AVAILABLE,this,t)):this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_STATUS,this,t))}_onInsufficientBandwidth(t){this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_INSUFFICIENT_BANDWIDTH,this,t))}_onSufficientBandwidth(t){this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_SUFFICIENT_BANDWIDTH,this,t))}_onRecoveringBandwidth(t){this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_RECOVERING_BANDWIDTH,this,t))}_onSDPSuccess(e=void 0){const t=e?": "+JSON.stringify(e,null,2):"";rt(`[onsdpsuccess]:: ${t}`)}_onSDPError(t=void 0){this.trigger(new Ee(e.PublisherEventTypes.PUBLISH_FAIL,this));const i=t?": "+JSON.stringify(t,null,2):"";at(`[onsdperror]:: ${i}`)}_onOrientationChange(e){const t=this.getMessageTransport();t&&t.post({send:{method:"onMetaData",data:{deviceOrientation:e}}})}_onStatisticsEndpointChange(t){rt(`Statistics endpoint changed: ${t}`),this._statsMonitor&&this._statsMonitor.updateEndpoint(t),this.trigger(new Ee(e.PublisherEventTypes.STATISTICS_ENDPOINT_CHANGE,this,{statisticsEndpoint:t}))}_onStatsReport(t,i){this.trigger(new Ee(e.RTCPublisherEventTypes.STATS_REPORT,this,{connection:t,report:i}))}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}trigger(e){super.trigger(e)}emit(e,t){this.trigger(new Ee(e,this,t))}getType(){return"RTC"}}const ht={...{protocol:"https",port:443,app:"live",autoLayoutOrientation:!0,mediaElementId:"red5pro-subscriber",rtcConfiguration:{iceCandidatePoolSize:2,bundlePolicy:"max-bundle"},iceTransport:de.UDP,muteOnAutoplayRestriction:!0,maintainConnectionOnSubscribeErrors:!1,dataChannelConfiguration:{name:"red5pro"},signalingSocketOnly:!1,includeDataChannel:!0,maintainStreamVariant:!1,buffer:0,stats:void 0,renegotiationPolicy:void 0},signalingSocketOnly:!1,enableChannelSignaling:!1,includeDataChannel:!0,disableProxy:!0,trickleIce:!0,postEmptyOffer:!1,mungeOffer:void 0,mungeAnswer:void 0},ct={protocol:"https",port:443,app:"live",mediaElementId:"red5pro-subscriber",muteOnAutoplayRestriction:!0},ut={endpoint:_e.DEV_NULL,interval:3e3},pt="R5ProPlaybackView";class _t{constructor(e="red5pro-subscriber"){try{this._targetElement=ie.resolveElement(e)}catch(e){throw k(pt,`Could not instantiate a new instance of Red5ProSubscriber. Reason: ${e.message||e}`),e}}attachStream(e){const t=this.isAutoplay;O(pt,"[attachstream]"),ie.setVideoSource(this._targetElement,e,t)}detachStream(){O(pt,"[detachstream]"),ie.setVideoSource(this._targetElement,null,this.isAutoplay)}get isAutoplay(){return ie.hasAttributeDefined(this._targetElement,"autoplay")}get view(){return this._targetElement}}const mt="RTCPeerConnectionSubscriber";class gt extends Le{constructor(e){super(e,mt)}_removeConnectionHandlers(e){e.onconnectionstatechange=null,e.oniceconnectionstatechange=null,e.onicegatheringstatechange=null,e.onsignalingstatechange=null,e.onicecandidate=null,e.ontrack=null,e.onnegotiationneeded=null}_addConnectionHandlers(e){let t;e.onsignalingstatechange=()=>{const t=e.signalingState;O(mt,`[peer.onsignalingstatechange] - State: ${t}`)},e.onconnectionstatechange=()=>{const{connectionState:t}=e;"connected"===t?(O(this._name,"[peerconnection:open]"),this._responder.onPeerConnectionOpen()):"failed"===t||"disconnected"===t?(H(this._name,`[peerconnection:error]:: ${t}`),"failed"===t&&this._responder.onPeerConnectionFail()):O(this._name,`[peerconnection:state]:: ${t}`)},e.oniceconnectionstatechange=i=>{const{iceConnectionState:n}=e;O(this._name,`[peer.oniceconnectionstatechange] - State: ${n}`),"failed"===n?(t&&clearTimeout(t),this._responder.onPeerConnectionFail(),this._responder.onPeerConnectionClose(i)):"disconnected"===n?t=setTimeout((()=>{O(this._name,"[peer.oniceconnectionstatechange] - Reconnect timeout reached."),clearTimeout(t),this._responder.onPeerConnectionClose(i)}),3e3):t&&(O(this._name,"[peer.oniceconnectionstatechange] - Clearing timeout for reconnect."),clearTimeout(t))},e.onicecandidate=e=>{const{candidate:t}=e;O(this._name,`[peer.onicecandidate] - Peer Candidate: ${null==t?void 0:t.candidate}`),t&&this._responder.onIceCandidate(t)},e.onnegotiationneeded=()=>{O(this._name,"[peer.onnegotiationneeded]")},e.onicegatheringstatechange=()=>{const{iceGatheringState:t}=e;O(this._name,`[peer.onicegatheringstatechange] - State: ${t}`)}}_onDataChannelMessage(e){const t=e;if(super._onDataChannelMessage(e))return!0;const i=this.getJsonFromSocketMessage(t);if(null===i)return H(this._name,"Determined websocket response not in correct format. Aborting message handle."),!0;O(this._name,"[datachannel-response]: "+JSON.stringify(i,null,2));const{data:n}=i;if(n&&"status"===n.type)return"NetStream.Play.UnpublishNotify"===n.code?(this._responder.onUnpublish(),this._responder.onConnectionClosed(),!0):"Application.Statistics.Endpoint"===n.code?(this._responder.onStatisticsEndpointChange(n.statistics),!0):(O(mt,`[datachannel.message] status :: ${n.code}`),this._responder.onSubscriberStatus(n),!0);if(n&&n.status&&"NetStream.Play.UnpublishNotify"===n.status)return this._responder.onUnpublish(),this._responder.onConnectionClosed(),!0;if(n&&"result"===n.type){const{message:e}=n;if("Stream switch: Success"===e)try{return this._responder.onStreamSwitchComplete(),!0}catch(e){}}return this._responder.onDataChannelMessage(this._dataChannel,t),!1}}var vt;!function(e){e.EMPTY="Empty",e.VIDEO="Video",e.AUDIO="Audio",e.FULL="Video/Audio"}(vt||(vt={}));class Et extends U{trigger(e){super.trigger(e)}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}}class St extends Et{}const Ct=[e.SubscriberEventTypes.SUBSCRIBE_START,e.SubscriberEventTypes.SUBSCRIBE_STOP,e.SubscriberEventTypes.SUBSCRIBE_FAIL,e.SubscriberEventTypes.SUBSCRIBE_PUBLISHER_CONGESTION,e.SubscriberEventTypes.SUBSCRIBE_PUBLISHER_RECOVERY,e.SubscriberEventTypes.PLAY_UNPUBLISH,e.SubscriberEventTypes.STREAMING_MODE_CHANGE,e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,e.SubscriberEventTypes.STATISTICS_ENDPOINT_CHANGE];class bt extends Ze{constructor(t,i,n){if(super("RTCSubscriberStats",t,i,n),this.estimatedAudioBitrate=0,this.estimatedVideoBitrate=0,this.lastAudioReport=null,this.lastVideoReport=null,this._eventHandler=t=>{const{type:i,data:n}=t;if(Ct.indexOf(i)>-1)if(i===e.SubscriberEventTypes.STREAMING_MODE_CHANGE){const{streamingMode:e,previousStreamingMode:t}=n;this.postEvent(i,{data:{streamingMode:e,previousStreamingMode:t}})}else if(i===e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE){const{code:t}=n;let i;t===e.PlaybackState.AVAILABLE&&(i={timeToFirstFrameMS:(new Date).getTime()-this._startTime}),this.postEvent(o[t],i)}else{if(i===e.SubscriberEventTypes.STATISTICS_ENDPOINT_CHANGE){const{statisticsEndpoint:e}=n;this.updateEndpoint(e,!1)}this.postEvent(i)}},this._candidateCreateHandler=({data:{candidate:e}})=>{const{candidate:t}=e,i=tt(t);i&&(this._identifier.publicIP=i)},this._hostEndpointChangedHandler=({data:{endpoint:e,iceServers:t}})=>{this._appendClientDetails({node:e,iceServers:t})},this._client.on("*",this._eventHandler),this._client.on(e.RTCSubscriberEventTypes.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.on(e.RTCSubscriberEventTypes.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),this._client.getPeerConnection())this.start(this._client.getPeerConnection());else{const t=({data:i})=>{this._client.off(e.RTCSubscriberEventTypes.PEER_CONNECTION_AVAILABLE,t),this.start(i)};this._client.on(e.RTCSubscriberEventTypes.PEER_CONNECTION_AVAILABLE,t)}}_handleStatsReport(e){const{type:t}=e,{include:i}=this._config,n=i&&i.length>0;if(n&&i.indexOf(t)>=-1)this.post(e);else if(!n)if(t===Xe.CODEC){const{id:i,clockRate:n,mimeType:s,payloadType:o}=e;this.post({id:i,type:t,clockRate:n,mimeType:s,payloadType:o})}else if(t===Xe.CANDIDATE_PAIR){const{availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o}=e;this._checkCandidatePairHealth(e),this.post({type:t,availableOutgoingBitrate:i,currentRoundTripTime:n,totalRoundTripTime:s,state:o})}else if([Xe.INBOUND,"inboundrtp"].indexOf(t)>-1){const{timestamp:i,kind:n,codecId:s,jitter:o,packetsLost:r,packetsReceived:a,bytesReceived:l}=e,d={type:t,kind:n,codecId:s,jitter:o,packetsLost:r,packetsReceived:a,bytesReceived:l};if("audio"===n){const{packetsDiscarded:t}=e;if(this.lastAudioReport){const{bytesReceived:e,timestamp:t}=this.lastAudioReport,n=8*(l-e)/(i-t);this.estimatedAudioBitrate=n}this.post({...d,packetsDiscarded:t,estimatedBitrate:Math.floor(this.estimatedAudioBitrate)}),this.lastAudioReport=e}else if("video"===n){const{firCount:t,frameWidth:n,frameHeight:s,framesDecoded:o,framesDropped:r,framesPerSecond:a,framesReceived:h,freezeCount:c,keyFramesDecoded:u,nackCount:p,pauseCount:_,pliCount:m,totalFreezesDuration:g,totalPausesDuration:v}=e,E={...d,firCount:t,frameWidth:n,frameHeight:s,framesDecoded:o,framesDropped:r,framesPerSecond:a,framesReceived:h,freezeCount:c,keyFramesDecoded:u,nackCount:p,pauseCount:_,pliCount:m,totalFreezesDuration:g,totalPausesDuration:v};if(this.lastVideoReport){const{bytesReceived:e,timestamp:t}=this.lastVideoReport,n=8*(l-e)/(i-t);this.estimatedVideoBitrate=n}this.post({...E,estimatedBitrate:Math.floor(this.estimatedVideoBitrate)}),this.lastVideoReport=e}}}dispose(){this._client.off("*",this._eventHandler),this._client.off(e.RTCSubscriberEventTypes.CANDIDATE_CREATE,this._candidateCreateHandler),this._client.off(e.RTCSubscriberEventTypes.HOST_ENDPOINT_CHANGED,this._hostEndpointChangedHandler),super.dispose()}}class Tt extends St{constructor(e,t){super(),this._isVOD=!1,this._name=`SourceHandler-${t}`,this._view=e,this._playbackNotificationCenter=this._view,this.onCanPlay=this._onCanPlay.bind(this),this.onDurationChange=this._onDurationChange.bind(this),this.onEnded=this._onEnded.bind(this),this.onTimeUpdate=this._onTimeUpdate.bind(this),this.onPlay=this._onPlay.bind(this),this.onPause=this._onPause.bind(this),this.onVolumeChange=this._onVolumeChange.bind(this),this.onLoadedData=this._onLoadedData.bind(this),this.onLoadedMetadata=this._onLoadedMetadata.bind(this),this.onResize=this._onResize.bind(this),this.onLoadStart=this._onLoadStart.bind(this),this.onSuspend=this._onSuspend.bind(this),this.onStalled=this._onStalled.bind(this),this.onWaiting=this._onWaiting.bind(this),this.onError=this._onError.bind(this),this.onEncrypted=this._onEncrypted.bind(this),this._addPlaybackNotificationCenterHandlers(this._playbackNotificationCenter),ie.onFullScreenStateChange(this._handleFullScreenChange.bind(this))}_addPlaybackNotificationCenterHandlers(e){e.addEventListener("canplay",this.onCanPlay),e.addEventListener("durationchange",this.onDurationChange),e.addEventListener("ended",this.onEnded),e.addEventListener("timeupdate",this.onTimeUpdate),e.addEventListener("play",this.onPlay),e.addEventListener("pause",this.onPause),e.addEventListener("volumechange",this.onVolumeChange),e.addEventListener("loadeddata",this.onLoadedData),e.addEventListener("loadedmetadata",this.onLoadedMetadata),e.addEventListener("resize",this.onResize),e.addEventListener("loadstart",this.onLoadStart),e.addEventListener("suspend",this.onSuspend),e.addEventListener("stalled",this.onStalled),e.addEventListener("waiting",this.onWaiting),e.addEventListener("error",this.onError),e.addEventListener("encrypted",this.onEncrypted)}_removePlaybackNotificationCenterHandlers(e){e.removeEventListener("canplay",this.onCanPlay),e.removeEventListener("durationchange",this.onDurationChange),e.removeEventListener("ended",this.onEnded),e.removeEventListener("timeupdate",this.onTimeUpdate),e.removeEventListener("play",this.onPlay),e.removeEventListener("pause",this.onPause),e.removeEventListener("volumechange",this.onVolumeChange),e.removeEventListener("loadeddata",this.onLoadedData),e.removeEventListener("loadedmetadata",this.onLoadedMetadata),e.removeEventListener("resize",this.onResize),e.removeEventListener("loadstart",this.onLoadStart),e.removeEventListener("suspend",this.onSuspend),e.removeEventListener("stalled",this.onStalled),e.removeEventListener("waiting",this.onWaiting),e.removeEventListener("error",this.onError)}_handleFullScreenChange(t){var i,n;t?null===(i=this._view)||void 0===i||i.classList.add("red5pro-media-container-full-screen"):null===(n=this._view)||void 0===n||n.classList.remove("red5pro-media-container-full-screen"),this.trigger(new Se(e.SubscriberEventTypes.FULL_SCREEN_STATE_CHANGE,void 0,t))}_cleanup(){this._playbackNotificationCenter&&this._removePlaybackNotificationCenterHandlers(this._playbackNotificationCenter),this._playbackNotificationCenter=void 0,this._view=void 0}_onCanPlay(t){var i;O(this._name,"[videoelement:event] canplay");const n=null!==(i=this._playbackNotificationCenter)&&void 0!==i?i:t.target,o=this.getControls();o&&o.enable(!0),this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.AVAILABLE,state:s.AVAILABLE})),this.trigger(new Se(e.SubscriberEventTypes.VOLUME_CHANGE,void 0,{volume:n.volume}))}_onDurationChange(e){var t;O(this._name,"[videoelement:event] durationchange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();n&&n.setPlaybackDuration(i.duration),!isNaN(i.duration)&&Number.isFinite(i.duration)&&(this._isVOD=!0)}_onEnded(){O(this._name,"[videoelement:event] ended");const t=this.getControls();t&&t.setState(e.PlaybackState.IDLE),this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.IDLE,state:s.IDLE}))}_onTimeUpdate(t){var i;const n=null!==(i=this._playbackNotificationCenter)&&void 0!==i?i:t.target,s=this.getControls();s&&s.setSeekTime(n.currentTime,this.isVOD()?n.duration:void 0),this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:n.currentTime,duration:n.duration}))}_onPlay(){O(this._name,"[videoelement:event] play");const t=this.getControls();t&&t.setState(e.PlaybackState.PLAYING),this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.PLAYING,state:s.PLAYING}))}_onPause(){O(this._name,"[videoelement:event] pause");const t=this.getControls();t&&t.setState(e.PlaybackState.PAUSED),this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.PAUSED,state:s.PAUSED}))}_onVolumeChange(t){var i;O(this._name,"[videoelement:event] volumechange");const n=null!==(i=this._playbackNotificationCenter)&&void 0!==i?i:t.target,s=this.getControls();s&&s.getVolume()!==n.volume&&s.setVolume(n.volume),this.trigger(new Se(e.SubscriberEventTypes.VOLUME_CHANGE,void 0,{volume:n.volume}))}_onLoadedData(t){var i,n,s;O(this._name,"[videoelement:event] loadeddata");const o=null!==(i=this._view)&&void 0!==i?i:t.target;this.trigger(new Se(e.SubscriberEventTypes.VIDEO_DIMENSIONS_CHANGE,void 0,{width:null!==(n=o.videoWidth)&&void 0!==n?n:0,height:null!==(s=o.videoHeight)&&void 0!==s?s:0}))}_onLoadedMetadata(t){var i,n;O(this._name,"[videoelement:event] loadedmetadata");const s=null!==(i=this._view)&&void 0!==i?i:t.target;this.trigger(new Se(e.SubscriberEventTypes.LOADED_METADATA,void 0,{duration:null!==(n=s.duration)&&void 0!==n?n:0}))}_onResize(t){var i,n,s;O(this._name,"[videoelement:event] resize");const o=null!==(i=this._view)&&void 0!==i?i:t.target;this.trigger(new Se(e.SubscriberEventTypes.VIDEO_DIMENSIONS_CHANGE,void 0,{width:null!==(n=o.videoWidth)&&void 0!==n?n:0,height:null!==(s=o.videoHeight)&&void 0!==s?s:0}))}_onLoadStart(){O(this._name,"[videoelement:event] loadstart")}_onSuspend(){O(this._name,"[videoelement:event] suspend")}_onStalled(){O(this._name,"[videoelement:event] stalled")}_onWaiting(){O(this._name,"[videoelement:event] waiting")}_onEncrypted(){O(this._name,"[videoelement:event] encrypted")}_onError(t){O(this._name,"[videoelement:event] error"),this.trigger(new Se(e.SubscriberEventTypes.CONNECT_FAILURE,void 0,{error:t.message}))}async attemptAutoplay(t=!1){try{await this.play(),this.isMuted()&&this.trigger(new Se(e.SubscriberEventTypes.AUTO_PLAYBACK_MUTED,void 0,{element:this._view}))}catch(i){t?(this.mute(),this.attemptAutoplay(t)):this.trigger(new Se(e.SubscriberEventTypes.AUTO_PLAYBACK_FAILURE,void 0,{error:i.message?i.message:i,element:this._view}))}}async play(){var e,t;if(O(this._name,"[videoelement:action] play"),!(null===(e=this._view)||void 0===e?void 0:e.paused))return O(this._name,"[videoelement:action] play (ALREADY PLAYING)"),!0;try{return await(null===(t=this._view)||void 0===t?void 0:t.play()),!0}catch(e){throw k(this._name,"[videoelement:action] play (FAULT) - "+e.message),e}}async pause(){var e;O(this._name,"[videoelement:action] pause");try{return await(null===(e=this._view)||void 0===e?void 0:e.pause()),!0}catch(e){H(this._name,"[videoelement:action] pause (CATCH::FAULT) - "+e.message)}return!1}async resume(){var e;O(this._name,"[videoelement:action] resume");try{return await(null===(e=this._view)||void 0===e?void 0:e.play()),!0}catch(e){H(this._name,"[videoelement:action] resume (CATCH::FAULT) - "+e.message)}return!1}async stop(){var e;O(this._name,"[videoelement:action] stop");try{return await(null===(e=this._view)||void 0===e?void 0:e.pause()),!0}catch(e){H(this._name,"[videoelement:action] stop (CATCH::FAULT) - "+e.message)}return!1}mute(){this._view&&(this._view.muted=!0);const e=this.getControls();e&&e.setMutedState(!0)}unmute(){this._view&&(this._view.muted=!1);const e=this.getControls();e&&e.setMutedState(!1)}setVolume(e){this.unmute(),this._view&&(this._view.volume=e)}getVolume(){var e,t;return null!==(t=null===(e=this._view)||void 0===e?void 0:e.volume)&&void 0!==t?t:0}seekTo(e,t=void 0){this._view&&(this._view.currentTime=t?e*t:e)}toggleFullScreen(e){try{(e||this._view)&&ie.toggleFullScreen(null!=e?e:this._view)}catch(e){}}async unpublish(){var e;try{await this.stop(),null===(e=this._view)||void 0===e||e.dispatchEvent(new Event("ended"))}catch(e){}}disconnect(){this._cleanup()}isVOD(){return this._isVOD}isMuted(){var e,t;return null!==(t=null===(e=this._view)||void 0===e?void 0:e.muted)&&void 0!==t&&t}getControls(){}}const ft="WHEPClient",yt=ht,At=e=>O(ft,e),wt=e=>k(ft,e),Pt=e=>H(ft,e);class Lt extends Et{constructor(e,t,i){super(),this._videoMuted=!0,this._audioMuted=!0;const n=e?se(e):yt,s=i||yt,o={...s,...n,endpoint:e,mediaElementId:t?t.id:s.mediaElementId};this._videoUnmuteHandler=this._onVideoUnmute.bind(this),this._audioUnmuteHandler=this._onAudioUnmute.bind(this),e&&this.internalInit(o)}async internalInit(e){await this.init(e),await this.subscribe()}async _runMuteCheck(){var e,t,i;if(this.getPeerConnection())try{let n=this._videoMuted,s=this._audioMuted;const o=await(null===(e=this.getPeerConnection())||void 0===e?void 0:e.getStats());if(null==o||o.forEach((e=>{const{type:t,kind:i,bytesReceived:o}=e;"inbound-rtp"!==t&&"inboundrtp"!==t||("video"===i?n=o<=0:"audio"===i&&(s=o<=0))})),n===this._videoMuted&&s===this._audioMuted)return;this._videoMuted=n,this._audioMuted=s;const r={data:{streamingMode:(t=!this._videoMuted,i=!this._audioMuted,t&&i?vt.FULL:t?vt.VIDEO:i?vt.AUDIO:vt.EMPTY),method:"onMetaData"},type:"metadata",method:"onMetaData",eventTimestamp:(new Date).getTime()};this._onMetaData(r)}catch(e){wt(e.message||e)}}_onVideoUnmute(e){const t=e.target;null==t||t.removeEventListener("unmute",this._videoUnmuteHandler);const i=setTimeout((async()=>{clearTimeout(i),this._runMuteCheck()}),1e3)}_onAudioUnmute(e){const t=e.target;null==t||t.removeEventListener("unmute",this._audioUnmuteHandler);const i=setTimeout((async()=>{clearTimeout(i),this._runMuteCheck()}),1e3)}_attachSourceHandler(e){this._sourceHandler=new Tt(e,this.getType())}_glomTrigger(e){e.on("*",(e=>{const{type:t,data:i}=e;this.trigger(new Se(t,this,i))}))}_playIfAutoplaySet(e,t){var i;if(e&&t){const{muteOnAutoplayRestriction:n}=e;ie.hasAttributeDefined(t,"autoplay")&&(null===(i=this._sourceHandler)||void 0===i||i.attemptAutoplay(n))}}addMediaStreamToPlayback(e,t){var i;!this._playbackView&&e&&(this._playbackView=new _t(e)),null===(i=this._playbackView)||void 0===i||i.attachStream(t)}async requestOffer(t){var i;At("[requestoffer]");const{iceTransport:n,maintainStreamVariant:s,videoEncoding:o,audioEncoding:r,connectionParams:a,mungeOffer:l}=this._options;t.addTransceiver("video",{direction:"recvonly"}),t.addTransceiver("audio",{direction:"recvonly"});const d={transport:n,doNotSwitch:s};o&&o!==e.PlaybackVideoEncoder.NONE&&(d.videoEncoding=o),r&&r!==e.PlaybackAudioEncoder.NONE&&(d.audioEncoding=r);const h=null!=a?a:{},c=await t.createOffer(),u=await(null===(i=this._whipWhepService)||void 0===i?void 0:i.postSDPOffer(c.sdp,{...h,...d},!1));if(!u)throw wt("Failed to get offer from WHEP"),new Error("Failed to get offer from WHEP");const{sdp:p}=u;let _=p;return l&&(At(`[MUNGE:before] offer: ${_}`),_=l(_),At(`[MUNGE:after] offer: ${_}`)),_}async requestAnswer(e){const{mungeAnswer:t}=this._options;let i=(await e.createAnswer()).sdp;return t&&(At(`[MUNGE:before] answer: ${i}`),i=t(i),At(`[MUNGE:after] answer: ${i}`)),i}async sendAnswer(e){var t;const{connectionParams:i}=this._options;return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.postSDPAnswer(e,i))}async postCandidateFragments(e){var t;const{connectionParams:i}=this._options,n=Ue(e,void 0,!0);return await(null===(t=this._whipWhepService)||void 0===t?void 0:t.trickle(n,i))}_evaluateRenegotiationPolicy(t){const{renegotiationPolicy:i}=this._options;if(i){const{type:n}=i,s=n.toLowerCase();At(`[evaluateRenegotiationPolicy] - Type: ${t}, Renegotiation Policy: ${i.type}`),(t===we.CONNECTION_HEALTH_STATE_REGRESSION&&"regression"===s||t===we.CONNECTION_HEALTH_ICE_TIMEOUT&&"timeout"===s||t===e.SubscriberEventTypes.CONNECTION_CLOSED&&"disconnect"===s)&&this._reconnect()}}async _reconnect(){var t,i;At("[reconnect]"),this.trigger(new Se(e.SubscriberEventTypes.RECONNECT_START,this));try{await this.unsubscribe(!0),await this.init(this._options),await this.subscribe()}catch(n){wt(null!==(t=n.message)&&void 0!==t?t:"Could not reconnect."),this.trigger(new Se(e.SubscriberEventTypes.RECONNECT_FAILURE,this,{error:null!==(i=n.message)&&void 0!==i?i:"Could not reconnect."}))}}async init(e){var t,i;this._options={...yt,...e},this._options.subscriptionId=this._options.subscriptionId||`subscriber-${Math.floor(65536*Math.random()).toString(16)}`;const n=oe(this._options,"whep"),{includeDataChannel:s,disableProxy:o}=this._options;return this._whipWhepService=new Je(`${n}?requestId=${this._options.subscriptionId}`,s,o),this._messageTransport=this._whipWhepService,((null===(t=this._options)||void 0===t?void 0:t.stats)||(null===(i=this._options)||void 0===i?void 0:i.renegotiationPolicy))&&(!this._options.stats&&this._options.renegotiationPolicy&&(this._options.stats=ut),this.monitorStats(this._options.stats,this._options.renegotiationPolicy)),this}async subscribe(){var t,i,n,s,o,r,a,l,d;const{connectionParams:h,rtcConfiguration:c,includeDataChannel:u,signalingSocketOnly:p,enableChannelSignaling:_,dataChannelConfiguration:m}=this._options;try{const d=h||{},v=await(null===(t=this._whipWhepService)||void 0===t?void 0:t.getOptions(d));this.trigger(new Se(e.SubscriberEventTypes.CONNECT_SUCCESS,this,null===(i=this._whipWhepService)||void 0===i?void 0:i.getUrl()));const E=!!(null===(n=this._options)||void 0===n?void 0:n.rtcConfiguration)&&Array.isArray(this._options.rtcConfiguration.iceServers)&&this._options.rtcConfiguration.iceServers.length>0;(null==v?void 0:v.links)&&!E&&(this._options.rtcConfiguration={...c,iceServers:v.links}),(null==v?void 0:v.origin)&&this.trigger(new Se(e.RTCSubscriberEventTypes.HOST_ENDPOINT_CHANGED,this,{endpoint:v.origin})),(null==v?void 0:v.statisticsEndpoint)&&this._onStatisticsEndpointChange(v.statisticsEndpoint);const S=u||_||p?m:void 0;this._peerConnectionHelper=new gt({onUnpublish:this._onUnpublish.bind(this),onStreamUnavailable:this._onStreamUnavailable.bind(this),onSubscriberStatus:this._onSubscriberStatus.bind(this),onStreamSwitchComplete:this._onStreamSwitchComplete.bind(this),onDataChannelError:this._onDataChannelError.bind(this),onSendReceived:this._onSendReceived.bind(this),onMetaData:this._onMetaData.bind(this),onConnectionClosed:this._onConnectionClosed.bind(this),onDataChannelOpen:this._onDataChannelOpen.bind(this),onDataChannelClose:this._onDataChannelClose.bind(this),onDataChannelMessage:this._onDataChannelMessage.bind(this),onPeerConnectionOpen:this._onPeerConnectionOpen.bind(this),onPeerConnectionFail:this._onPeerConnectionFail.bind(this),onPeerConnectionClose:this._onPeerConnectionClose.bind(this),onIceCandidate:this._onIceCandidate.bind(this),onSDPSuccess:this._onSDPSuccess.bind(this),onSDPError:this._onSDPError.bind(this),onStatisticsEndpointChange:this._onStatisticsEndpointChange.bind(this)}),await this._peerConnectionHelper.setUpWithPeerConfiguration(this._options.rtcConfiguration,S),null===(s=this.getPeerConnection())||void 0===s||s.addEventListener("track",(t=>{const{buffer:i}=this._options;At("[peerconnection.ontrack]");const{streams:n,track:s,receiver:o,transceiver:r}=t;o.playoutDelayHint=i,o.jitterBufferDelayHint=i,this.trigger(new Se(e.RTCSubscriberEventTypes.TRACK_ADDED,this,{streams:n,track:s,receiver:o,transceiver:r})),this._mediaStream=n&&n.length>0?n[0]:void 0,"video"===s.kind?(this._videoMuted=s.muted,s.muted&&s.addEventListener("unmute",this._videoUnmuteHandler)):"audio"===s.kind&&(this._audioMuted=s.muted,s.muted&&s.addEventListener("unmute",this._audioUnmuteHandler)),this._runMuteCheck()})),this.trigger(new Se(e.RTCSubscriberEventTypes.PEER_CONNECTION_AVAILABLE,this,this.getPeerConnection())),this.trigger(new Se(e.RTCSubscriberEventTypes.OFFER_START,this));const C=await this.requestOffer(this.getPeerConnection()),b=new RTCSessionDescription({type:"offer",sdp:C});await(null===(o=this.getPeerConnection())||void 0===o?void 0:o.setRemoteDescription(b)),this.trigger(new Se(e.RTCSubscriberEventTypes.OFFER_END,this)),this.trigger(new Se(e.RTCSubscriberEventTypes.ANSWER_START,this));const T=await this.requestAnswer(this.getPeerConnection()),f=(g=T).includes("stereo=1")?g:g.replace("useinbandfec=1","useinbandfec=1;stereo=1;sprop-stereo=1"),y=new RTCSessionDescription({type:"answer",sdp:f});await(null===(r=this.getPeerConnection())||void 0===r?void 0:r.setLocalDescription(y)),await this.sendAnswer(f),this.trigger(new Se(e.RTCSubscriberEventTypes.ANSWER_END,this));const A=await this._peerConnectionHelper.waitToGatherIce(),{sdp:w}=A;return await this.postCandidateFragments(w),this.trigger(new Se(e.RTCSubscriberEventTypes.ICE_TRICKLE_COMPLETE,this)),this._mediaStream&&(this.trigger(new Se(e.RTCSubscriberEventTypes.ON_ADD_STREAM,this,this._mediaStream)),this.addMediaStreamToPlayback(this._options.mediaElementId,this._mediaStream)),(null===(a=this._playbackView)||void 0===a?void 0:a.view)&&this._attachSourceHandler(this._playbackView.view),this._sourceHandler&&this._glomTrigger(this._sourceHandler),this._playIfAutoplaySet(this._options,null===(l=this._playbackView)||void 0===l?void 0:l.view),this}catch(t){throw wt(null!==(d=t.message)&&void 0!==d?d:"Could not subscribe."),t instanceof $e?this._onStreamUnavailable(t):this.trigger(new Se(e.SubscriberEventTypes.CONNECT_FAILURE,this,t)),this._options.maintainConnectionOnSubscribeErrors||this.unsubscribe(!0),t}var g}async unsubscribe(t=!1){var i;At("[unsubscribe]"),this._peerConnectionHelper&&await this._peerConnectionHelper.tearDown(),this._whipWhepService&&await this._whipWhepService.tearDown(null,t),this._sourceHandler&&this._sourceHandler.disconnect(),this.unmonitorStats(),null===(i=this._playbackView)||void 0===i||i.detachStream(),this._playbackView=void 0,this._whipWhepService=void 0,this._messageTransport=void 0,this._peerConnectionHelper=void 0,this._sourceHandler=void 0,this._mediaStream=void 0,this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_STOP,this))}send(e,t){var i;return null===(i=this.getMessageTransport())||void 0===i?void 0:i.post({send:{method:e,data:"string"==typeof t?JSON.parse(t):t}})}async callServer(e,t){var i;const n="switchStreams"===e,{app:s,streamName:o}=this._options;if(n){const{path:i}=t[0];this._requestedStreamSwitch=i,At(`[callServer:switch]:: ${e}, ${s}/${o} -> ${i}`)}return null===(i=this.getMessageTransport())||void 0===i?void 0:i.postAsync({callAdapter:{method:e,arguments:t}})}sendLog(e,t){var i;try{const n=Object.keys(R).find((t=>t.toLowerCase()===e.toLowerCase()))?e:R.DEBUG,s="string"==typeof t?t:JSON.stringify(t);null===(i=this.getMessageTransport())||void 0===i||i.post({log:n.toUpperCase(),message:s})}catch(e){const t=e.message||e;wt("Could not send log to server. Message parameter expected to be String or JSON-serializable object."),wt(t)}}enableStandby(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0,muteVideo:!0}})}disableStandby(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1,muteVideo:!1}})}muteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!0}})}unmuteAudio(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteAudio:!1}})}muteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!0}})}unmuteVideo(){var e;null===(e=this.getMessageTransport())||void 0===e||e.post({mute:{muteVideo:!1}})}get options(){return this._options}getOptions(){return this._options}getPeerConnection(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.connection}getDataChannel(){var e;return null===(e=this._peerConnectionHelper)||void 0===e?void 0:e.dataChannel}getMediaStream(){return this._mediaStream}getMessageTransport(){return this._messageTransport}getPlayer(){var e;return null===(e=this._playbackView)||void 0===e?void 0:e.view}play(){At("[play]"),this._sourceHandler?this._sourceHandler.play():Pt("Cannot play without a Source Handler.")}pause(){At("[pause]"),this._sourceHandler?this._sourceHandler.pause():Pt("Cannot pause without a Source Handler.")}resume(){At("[resume]"),this._sourceHandler?this._sourceHandler.resume():Pt("Cannot resume without a Source Handler.")}stop(){At("[stop]"),this._sourceHandler?this._sourceHandler.stop():Pt("Cannot stop without a Source Handler.")}setVolume(e){At("[setVolume]"),this._sourceHandler?this._sourceHandler.setVolume(e):Pt("Cannot set volume without a Source Handler.")}getVolume(){var e,t,i;return At("[getVolume]"),this._sourceHandler?this._sourceHandler.getVolume():(Pt("Cannot get volume without a Source Handler."),null!==(i=null===(t=null===(e=this._playbackView)||void 0===e?void 0:e.view)||void 0===t?void 0:t.volume)&&void 0!==i?i:0)}mute(){At("[mute]"),this._sourceHandler?this._sourceHandler.mute():Pt("Cannot mute without a Source Handler.")}unmute(){At("[unmute]"),this._sourceHandler?this._sourceHandler.unmute():Pt("Cannot unmute without a Source Handler.")}seekTo(e){At("[seekTo]"),this._sourceHandler?this._sourceHandler.seekTo(e):Pt("Cannot seek without a Source Handler.")}toggleFullScreen(){At("[toggleFullScreen]"),this._sourceHandler?this._sourceHandler.toggleFullScreen():Pt("Cannot toggle full screen without a Source Handler.")}monitorStats(e,t){At(`[monitorStats]:: Stats: ${e?JSON.stringify(e):"undefined"}`),At(`[monitorStats]:: Renegotiation Policy: ${t?JSON.stringify(t):"undefined"}`);const{host:i,endpoint:n,app:s,streamName:o,subscriptionId:r,connectionParams:a}=this._options,l=null!=e?e:pe;return this._statisticsConfiguration={...l,host:i,app:s,hostEndpoint:n,streamName:o,subscriptionId:r,connectionParams:a},this._statsMonitor?Pt("Cannot monitor stats without a Peer Connection. Please call `init` before calling `monitorStats`."):this._statsMonitor=new bt(this._statisticsConfiguration,{onStatsReport:this._onStatsReport.bind(this),getPeerConnection:this.getPeerConnection.bind(this),getMessageTransport:this.getMessageTransport.bind(this),on:this.on.bind(this),off:this.off.bind(this),trigger:this.trigger.bind(this),emit:this.emit.bind(this)},t),this}unmonitorStats(){return this._statsMonitor&&this._statsMonitor.dispose(),this._statsMonitor=void 0,this._statisticsConfiguration=void 0,this}_onUnpublish(){At("[unpublish]"),this.trigger(new Se(e.SubscriberEventTypes.PLAY_UNPUBLISH,this)),this._sourceHandler&&this._sourceHandler.unpublish()}_onStreamUnavailable(t){At(`Stream ${this._options.streamName} does not exist.`),At("[onstreamunavailable]: "+JSON.stringify(t,null,2)),this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_INVALID_NAME,this))}_onDataChannelError(t,i){wt(`Data channel error: ${i}`),this.trigger(new Se(e.RTCSubscriberEventTypes.DATA_CHANNEL_ERROR,this,{dataChannel:t,error:i}))}_onSendReceived(t,i){At(`Send received: ${t} ${JSON.stringify(i)}`),"onMetaData"===t?this._onMetaData(i):this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_SEND_INVOKE,this,{methodName:t,data:i}))}_onStreamSwitchComplete(){At("[streamswitch::complete]");const t=this._requestedStreamSwitch;this.trigger(new Se(e.RTCSubscriberEventTypes.SUBSCRIBE_STREAM_SWITCH,this,{path:t})),this._requestedStreamSwitch=void 0}_onMetaData(t){const{orientation:i,streamingMode:n}=t,s=this._streamingMode;void 0!==i&&i!==this._orientation&&(this._orientation=i,this.trigger(new Se(e.SubscriberEventTypes.ORIENTATION_CHANGE,this,{orientation:parseInt(i,10),viewElement:this._playbackView?this._playbackView.view:void 0}))),n&&void 0!==n&&n!==s&&(this._streamingMode=n,this.trigger(new Se(e.SubscriberEventTypes.STREAMING_MODE_CHANGE,this,{streamingMode:n,previousStreamingMode:s,viewElement:this._playbackView?this._playbackView.view:void 0}))),this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_METADATA,this,t))}_onConnectionClosed(){At("Connection closed"),this.unsubscribe(!0),this.trigger(new Se(e.SubscriberEventTypes.CONNECTION_CLOSED,this))}_onDataChannelOpen(t){At(`Data channel opened: ${t.label}`),this.trigger(new Se(e.RTCSubscriberEventTypes.DATA_CHANNEL_OPEN,this,{dataChannel:t})),this.trigger(new Se(e.RTCSubscriberEventTypes.DATA_CHANNEL_AVAILABLE,this,{name:t.label,dataChannel:t})),this._messageTransport=this._peerConnectionHelper,this.trigger(new Ce(e.MessageTransportStateEventTypes.CHANGE,this,{controller:this,transport:this._messageTransport})),this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_START,this))}_onDataChannelClose(t){At(`Data channel closed: ${t.label}`),this.trigger(new Se(e.RTCSubscriberEventTypes.DATA_CHANNEL_CLOSE,this,{dataChannel:t}))}_onDataChannelMessage(t,i){At(`Data channel message: ${i.data}`),this.trigger(new Se(e.RTCSubscriberEventTypes.DATA_CHANNEL_MESSAGE,this,{dataChannel:t,message:i}))}_onPeerConnectionOpen(){var t;At("Peer connection opened"),this.trigger(new Se(e.RTCSubscriberEventTypes.PEER_CONNECTION_OPEN,this,this.getPeerConnection())),(null===(t=this._options)||void 0===t?void 0:t.includeDataChannel)||this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_START,this))}_onPeerConnectionFail(){wt("Peer connection failed"),this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_FAIL,this))}_onPeerConnectionClose(t){At(`Peer connection closed: ${t.type}`),this._evaluateRenegotiationPolicy(e.SubscriberEventTypes.CONNECTION_CLOSED)}_onIceCandidate(t){At(`ICE candidate: ${t.candidate}`),this.trigger(new Se(e.RTCSubscriberEventTypes.CANDIDATE_CREATE,this,{candidate:t}))}_onPeerConnectionTrackAdd(e){At(`Peer connection track added: ${e.id}`)}_onSubscriberStatus(e){At(`Subscriber status: ${JSON.stringify(e)}`)}_onSDPSuccess(){At("SDP success")}_onSDPError(e){wt(`SDP error: ${e}`)}_onStatisticsEndpointChange(t){At(`Statistics endpoint changed: ${t}`),this._statsMonitor&&this._statsMonitor.updateEndpoint(t),this.trigger(new Se(e.SubscriberEventTypes.STATISTICS_ENDPOINT_CHANGE,this,{statisticsEndpoint:t}))}_onStatsReport(t,i){this.trigger(new Se(e.RTCSubscriberEventTypes.STATS_REPORT,this,{connection:t,report:i}))}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}trigger(e){super.trigger(e)}emit(e,t){this.trigger(new Se(e,this,t)),this._evaluateRenegotiationPolicy(e)}getType(){return"RTC"}}class Rt extends Tt{constructor(e,t){super(e,t),this._playingStarted=!1,this.onOrientation=this._onOrientationMetadata.bind(this),this.onStreamingMode=this._onStreamingModeMetadata.bind(this),ie.onOrientationMetadata(this._view,this.onOrientation),ie.onStreamingModeMetadata(this._view,this.onStreamingMode),this.onPlaying=this._onPlaying.bind(this),this.onSourceError=this._onSourceError.bind(this),this._view.addEventListener("playing",this.onPlaying)}addSource(e){this._source=ie.createElement("source"),this._source.type="application/x-mpegURL",this._source.src=e,this._view.firstChild?this._view.insertBefore(this._source,this._view.firstChild):this._view.appendChild(this._source),this._source.addEventListener("error",this.onSourceError)}_onPlaying(){this._playingStarted||this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_START,this._view)),this._playingStarted=!0}_onSourceError(t){O(this._name,"[source:event] error"),this.trigger(new Se(e.SubscriberEventTypes.CONNECT_FAILURE,void 0,t))}_onOrientationMetadata(t){const{orientation:i}=t,n=parseInt(i,10);i&&this._orientation!==n&&(O(this._name,"Metadata received: "+JSON.stringify(t,null,2)),this._orientation=n,this.trigger(new Se(e.SubscriberEventTypes.ORIENTATION_CHANGE,{orientation:this._orientation,viewElement:this._view})),this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_METADATA,void 0,t)))}_onStreamingModeMetadata(t){const{streamingMode:i}=t,n=this._streamingMode;i&&n!==i&&(O(this._name,"Metadata received: "+JSON.stringify(t,null,2)),this._streamingMode=i,this.trigger(new Se(e.SubscriberEventTypes.STREAMING_MODE_CHANGE,void 0,{streamingMode:this._streamingMode,previousStreamingMode:n,viewElement:this._view})),this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_METADATA,void 0,t)))}_cleanup(){this._view&&this._view.removeEventListener("playing",this.onPlaying),this._source&&(this._source.removeEventListener("error",this.onSourceError),this._view.removeChild(this._source),this._source=void 0),super._cleanup()}}const Nt="HLSSubscriber",Dt=e=>O(Nt,e),It=e=>H(Nt,e);class Ot extends Et{constructor(){super()}_glomTrigger(e){e.on("*",(e=>{const{type:t,data:i}=e;this.trigger(new Se(t,this,i))}))}_playIfAutoplaySet(e,t){var i;if(e&&t){const{muteOnAutoplayRestriction:n}=e;ie.hasAttributeDefined(t,"autoplay")&&(null===(i=this._sourceHandler)||void 0===i||i.attemptAutoplay(n))}}async init(e){if(!ie.supportsHLS())throw new Error("Native HLS playback is not supported on this browser.");return this._options={...ct,...e},this}async subscribe(){var t;try{const i=/^http(|s).*\.m3u8/g,{endpoint:n,mediaElementId:s}=this._options;return this._fileURL=n&&n.match(i)?n:(e=>{const{host:t,protocol:i,port:n,app:s,streamName:o,connectionParams:r}=e,a="ws"===i||"http"===i?"http":"https",l=`${a}://${t}:${n||("http"===a?5080:443)}/${s}/${o}.m3u8`;if(r)return`${l}?${Object.entries(r).map((([e,t])=>`${e}=${t}`)).join("&")}`;return l})(this._options),!this._playbackView&&s&&(this._playbackView=new _t(s),this._sourceHandler=new Rt(this._playbackView.view,this.getType()),this._sourceHandler.addSource(this._fileURL),this._glomTrigger(this._sourceHandler)),this.trigger(new Se(e.SubscriberEventTypes.CONNECT_SUCCESS,this,this._fileURL)),this._playIfAutoplaySet(this._options,null===(t=this._playbackView)||void 0===t?void 0:t.view),this}catch(t){throw t(t.message),this.trigger(new Se(e.SubscriberEventTypes.CONNECT_FAILURE,this,t.message)),t}}async unsubscribe(){var t;return this._sourceHandler&&this._sourceHandler.disconnect(),null===(t=this._playbackView)||void 0===t||t.detachStream(),this._playbackView=void 0,this._sourceHandler=void 0,this.trigger(new Se(e.SubscriberEventTypes.SUBSCRIBE_STOP,this)),this}play(){Dt("[play]"),this._sourceHandler?this._sourceHandler.play():It("Cannot play without a Source Handler.")}pause(){Dt("[pause]"),this._sourceHandler?this._sourceHandler.pause():It("Cannot pause without a Source Handler.")}resume(){Dt("[resume]"),this._sourceHandler?this._sourceHandler.resume():It("Cannot resume without a Source Handler.")}stop(){Dt("[stop]"),this._sourceHandler?this._sourceHandler.stop():It("Cannot stop without a Source Handler.")}setVolume(e){Dt("[setVolume]"),this._sourceHandler?this._sourceHandler.setVolume(e):It("Cannot set volume without a Source Handler.")}getVolume(){var e,t,i;return Dt("[getVolume]"),this._sourceHandler?this._sourceHandler.getVolume():(It("Cannot get volume without a Source Handler."),null!==(i=null===(t=null===(e=this._playbackView)||void 0===e?void 0:e.view)||void 0===t?void 0:t.volume)&&void 0!==i?i:0)}mute(){Dt("[mute]"),this._sourceHandler?this._sourceHandler.mute():It("Cannot mute without a Source Handler.")}unmute(){Dt("[unmute]"),this._sourceHandler?this._sourceHandler.unmute():It("Cannot unmute without a Source Handler.")}seekTo(e){Dt("[seekTo]"),this._sourceHandler?this._sourceHandler.seekTo(e):It("Cannot seek without a Source Handler.")}toggleFullScreen(){Dt("[toggleFullScreen]"),this._sourceHandler?this._sourceHandler.toggleFullScreen():It("Cannot toggle full screen without a Source Handler.")}getPlayer(){var e;return null===(e=this._playbackView)||void 0===e?void 0:e.view}get options(){return this._options}getOptions(){return this._options}get fileURL(){return this._fileURL}getFileURL(){return this._fileURL}getType(){return"HLS"}}const Ht={baseURL:void 0,fullURL:void 0,hlsjsRef:void 0,hlsElement:void 0,usePlaybackControlsUI:!0,options:{debug:!1,backBufferLength:0}},kt={...ht,liveSeek:Ht};class Mt extends U{trigger(e){super.trigger(e)}on(e,t){super.on(e,t)}off(e,t){super.off(e,t)}}var Ut,Bt;!function(e){e.SEEK_START="Seek.Start",e.SEEK_END="Seek.End"}(Ut||(Ut={})),function(e){e.CHANGE="Slider.Change",e.CHANGE_START="Slider.Change.Start",e.CHANGE_COMPLETE="Slider.Change.Complete"}(Bt||(Bt={}));class Vt extends ve{constructor(e,t,i){super(e,i),this._slider=t}get slider(){return this._slider}}const{createElement:$t,addGlobalEventListener:Ft,removeGlobalEventListener:Gt,globalUnassign:Wt,getAssignedValue:xt,globalAssign:jt}=ie,Kt="ControlSlider",zt="r5_liveseek_event_owner";class Jt extends U{constructor(e){super(),this._value=0,this._disabled=!1,this._eventStartPosition=0,this.debug=e=>O(Kt,e),this.warn=e=>H(Kt,e),this.name=[Kt,e].join("::"),this.debug("[init]"),this._container=$t("div"),this._button=this.createButton(),this._track=this.createTrack(),this._progressBar=this.createProgressBar(),this._container.appendChild(this._track),this._container.appendChild(this._progressBar),this._container.appendChild(this._button),this._layout(),this._mouseupHandler=this._mouseup.bind(this),this._mousedownHandler=this._mousedown.bind(this),this._mousemoveHandler=this._mousemove.bind(this),this._touchupHandler=this._touchproxy.bind(this),this._touchdownHandler=this._touchproxy.bind(this),this._touchmoveHandler=this._touchproxy.bind(this),this._updateHandlers(this._disabled)}_touchproxy(e){var t,i,n,s;const o=e;this.debug(`${o.type} touches: ${(null===(t=o.changedTouches)||void 0===t?void 0:t.length)||0}`);try{o.preventDefault()}catch(e){this.warn("Failed to prevent default on touch event.")}if(!o.touches||o.touches.length>1||"touchend"===o.type&&o.touches.length>0)return;let r,a="";const l=o.target||document.body;switch(o.type){case"touchstart":a="mousedown",r=null===(i=o.changedTouches)||void 0===i?void 0:i[0];break;case"touchmove":a="mousemove",r=null===(n=o.changedTouches)||void 0===n?void 0:n[0];break;case"touchend":a="mouseup",r=null===(s=o.changedTouches)||void 0===s?void 0:s[0]}if(r&&a){const e=new MouseEvent(a,{bubbles:!0,cancelable:!0,view:l.ownerDocument.defaultView,screenX:r.screenX,screenY:r.screenY,clientX:r.clientX,clientY:r.clientY,ctrlKey:o.ctrlKey,altKey:o.altKey,shiftKey:o.shiftKey,metaKey:o.metaKey,button:0,relatedTarget:null});l.dispatchEvent(e)}}_mouseup(){this._eventStartPosition=0,Wt(zt),Gt("mousemove",this._mousemoveHandler),Gt("mouseup",this._mouseupHandler),Gt("touchmove",this._touchmoveHandler),Gt("touchend",this._touchupHandler),this.trigger(new Vt(Bt.CHANGE_COMPLETE,this))}_mousemove(e){if(xt(zt)!==this.name)return;this.debug(`[mousemove] ${this.name}`);const t=e.clientX-this._eventStartPosition,i=this._button.parentNode.getBoundingClientRect();let n=this._eventStartPosition+t-i.left;n=Math.max(0,n),n=Math.min(n,i.width);const s=n/i.width;this.trigger(new Vt(Bt.CHANGE,this,s))}_mousedown(e){this._eventStartPosition=e.clientX,this.trigger(new Vt(Bt.CHANGE_START,this)),jt(zt,this.name),Ft("mousemove",this._mousemoveHandler),Ft("mouseup",this._mouseupHandler),Ft("touchmove",this._touchmoveHandler),Ft("touchend",this._touchupHandler)}_updateHandlers(e){this._eventStartPosition=0,e?(this._track.removeEventListener("click",this._mousemoveHandler),this._progressBar.removeEventListener("click",this._mousemoveHandler),this._button.removeEventListener("mousedown",this._mousedownHandler),Gt("mousemove",this._mousemoveHandler),Gt("mouseup",this._mouseupHandler),Gt("touchmove",this._touchmoveHandler),Gt("touchend",this._touchupHandler),this._track.classList.add("red5pro-media-slider-disabled"),this._progressBar.classList.add("red5pro-media-slider-disabled"),this._button.classList.add("red5pro-media-slider-disabled")):(this._track.addEventListener("click",this._mousemoveHandler),this._progressBar.addEventListener("click",this._mousemoveHandler),this._button.addEventListener("mousedown",this._mousedownHandler),this._button.addEventListener("touchstart",this._touchdownHandler),this._track.classList.remove("red5pro-media-slider-disabled"),this._progressBar.classList.remove("red5pro-media-slider-disabled"),this._button.classList.remove("red5pro-media-slider-disabled"))}_layout(){const e=this._progressBar.parentNode.clientWidth*this._value;this._progressBar.style.width=e+"px",this._button.style.left=e-.5*this._button.clientWidth+"px"}createButton(){const e=$t("span");return e.classList.add("red5pro-media-slider-button"),e}createProgressBar(){const e=$t("span");return e.classList.add("red5pro-media-slider-progress"),e}createTrack(){const e=$t("span");return e.classList.add("red5pro-media-slider-track"),e}get value(){return this._value}set value(e){this._value=e,this._layout()}get disabled(){return this._disabled}set disabled(e){this._disabled=e,this._updateHandlers(e)}get view(){return this._container}}const{createElement:Yt,isTouchEnabled:qt,isPossiblySafari:Xt}=ie,Qt=e=>O("PlaybackControls",e);class Zt extends Mt{constructor(t,i){super(),this._state=e.PlaybackState.IDLE,this._mutedState=!1,this._resumeAfterSeek=!1,this._playbackDuration=0,this._volumeValue=1,this._player=t,this._container=i,this._onPlayPauseClickBound=this._onPlayPauseClick.bind(this),this._decorate(this._container)}_decorate(t){if(!t)return;Qt("[decorate]");const i=Yt("div");let n;i.classList.add("red5pro-media-control-bar"),this._playPauseButton=this._createPlayPauseButton(),this._muteButton=this._createMuteButton(),this._volumeField=this._createVolumeControl(),this._seekTimeField=this._createSeekControl(),this._timeField=this._createPlaybackTime(),this._fullScreenButton=this._createFullScreenToggle(),i.appendChild(this._playPauseButton),i.appendChild(this._timeField),i.appendChild(this._seekTimeField.view),i.appendChild(this._muteButton),i.appendChild(this._volumeField.view),i.appendChild(this._fullScreenButton),t.appendChild(i),this._controlbar=i;const s=()=>{clearTimeout(n),n=setTimeout((()=>{i.classList.remove("red5pro-media-control-bar-show")}),6e3)};qt()?(i.classList.add("red5pro-media-control-bar-show"),t.addEventListener("touchend",(()=>{i.classList.toggle("red5pro-media-control-bar-show"),s()})),s()):(t.addEventListener("mouseover",(()=>{i.classList.add("red5pro-media-control-bar-show")})),t.addEventListener("mouseout",(()=>{i.classList.remove("red5pro-media-control-bar-show")}))),this.setState(e.PlaybackState.IDLE).onFullScreenChange(!1).setSeekTime(0).enable(!1)}_onPlayPauseClick(){return this.getState()===e.PlaybackState.PLAYING?this._player.pause(!0):this.getState()===e.PlaybackState.PAUSED?this._player.resume(!0):this._player.play(!0),this}_createPlayPauseButton(){const e=Yt("button");return e.setAttribute("aria-label","Toggle Playback"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-playpause-button"),e}_createMuteButton(){const e=Yt("button");return e.setAttribute("aria-label","Toggle Mute Audio"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-muteunmute-button"),e.addEventListener("click",(()=>{this.getMutedState()?(this._player.unmute(),this.setMutedState(!1)):(this._player.mute(),this.setMutedState(!0))})),e}_createVolumeControl(){const e=new Jt("volume");return e.view.classList.add("red5pro-media-control-element"),e.view.classList.add("red5pro-media-volume-slider"),e.view.classList.add("red5pro-media-slider"),e.on(Bt.CHANGE,(e=>{const t=Number(e.data);this._player.setVolume(t)})),e}_createSeekControl(){const t=new Jt("seek");return t.view.classList.add("red5pro-media-control-element"),t.view.classList.add("red5pro-media-seektime-slider"),t.view.classList.add("red5pro-media-slider"),t.on(Bt.CHANGE_START,(()=>{this.getState()===e.PlaybackState.PLAYING&&(this._resumeAfterSeek=!0,this._player.pause(!0,!0)),this.trigger(new ve(Ut.SEEK_START))})),t.on(Bt.CHANGE,(e=>{const t=Number(e.data);this._player.seekTo(t,0===this._playbackDuration?void 0:this._playbackDuration),this.setSeekTime(t*this._playbackDuration,this._playbackDuration)})),t.on(Bt.CHANGE_COMPLETE,(()=>{this._resumeAfterSeek&&this.getState()===e.PlaybackState.PAUSED&&(this._resumeAfterSeek=!1,this._player.resume(!0)),this.trigger(new ve(Ut.SEEK_END))})),t}_createPlaybackTime(){const e=Yt("span"),t=Yt("text");return t.textContent="00:00",e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-time-field"),e.appendChild(t),e}_createFullScreenToggle(){const e=Yt("button");return e.setAttribute("aria-label","Toggle Fullscreen"),e.classList.add("red5pro-media-control-element"),e.classList.add("red5pro-media-element-button"),e.classList.add("red5pro-media-fullscreen-button"),e.addEventListener("click",(()=>{this._player.toggleFullScreen()})),e}_formatTime(e){const t=new Date(1e3*e);return`${String(t.getUTCHours()).padStart(2,"0")}:${String(t.getUTCMinutes()).padStart(2,"0")}:${String(t.getUTCSeconds()).padStart(2,"0")}`}onStateChange(t){var i,n,s,o;return t===e.PlaybackState.PLAYING?(null===(i=this._playPauseButton)||void 0===i||i.classList.remove("red5pro-media-play-button"),null===(n=this._playPauseButton)||void 0===n||n.classList.add("red5pro-media-pause-button")):(null===(s=this._playPauseButton)||void 0===s||s.classList.add("red5pro-media-play-button"),null===(o=this._playPauseButton)||void 0===o||o.classList.remove("red5pro-media-pause-button")),this}onMutedStateChange(e){var t,i,n,s;return e?(null===(t=this._muteButton)||void 0===t||t.classList.add("red5pro-media-mute-button"),null===(i=this._muteButton)||void 0===i||i.classList.remove("red5pro-media-unmute-button"),this._volumeField&&(this._volumeField.value=0)):(null===(n=this._muteButton)||void 0===n||n.classList.remove("red5pro-media-mute-button"),null===(s=this._muteButton)||void 0===s||s.classList.add("red5pro-media-unmute-button"),this._volumeField&&(this._volumeField.value=this._volumeValue)),this}onFullScreenChange(e){var t,i,n,s;return e?(null===(t=this._fullScreenButton)||void 0===t||t.classList.add("red5pro-media-exit-fullscreen-button"),null===(i=this._fullScreenButton)||void 0===i||i.classList.remove("red5pro-media-fullscreen-button")):(null===(n=this._fullScreenButton)||void 0===n||n.classList.remove("red5pro-media-exit-fullscreen-button"),null===(s=this._fullScreenButton)||void 0===s||s.classList.add("red5pro-media-fullscreen-button")),this}enable(e){var t,i,n,s;return e?(null===(t=this._playPauseButton)||void 0===t||t.classList.remove("red5pro-media-element-button-disabled"),null===(i=this._playPauseButton)||void 0===i||i.addEventListener("click",this._onPlayPauseClickBound)):(null===(n=this._playPauseButton)||void 0===n||n.classList.add("red5pro-media-element-button-disabled"),null===(s=this._playPauseButton)||void 0===s||s.removeEventListener("click",this._onPlayPauseClickBound)),this}getVolume(){return this._volumeValue}setVolume(e){return this._volumeField&&(this._volumeField.value=e),this._volumeValue=e,0===e?this.setMutedState(!0):this.getMutedState()&&this.setMutedState(!1),this}setSeekTime(e,t=0){return this._seekTimeField&&(this._seekTimeField.value=0===t?0:e/t,0!==this._playbackDuration&&this._playbackDuration<=e&&(this._seekTimeField.value=1)),this._timeField&&(!isFinite(this._playbackDuration)&&Xt()?this._timeField.innerText="Live Broadcast":this._timeField.innerText=this._formatTime(Math.floor(e))),this}setPlaybackDuration(e){return this._playbackDuration=e,this}getPlaybackDuration(){return this._playbackDuration}getState(){return this._state}setState(e){return Qt(`[setState]: ${o[e]}`),this._state=e,this.onStateChange(this._state),this}setMutedState(e){return this._mutedState=e,this.onMutedStateChange(this._mutedState),this}getMutedState(){return"muted"in this._player?this._player.muted:this._mutedState}setAsVOD(e){return Qt(`[setAsVOD]: ${e}`),this._seekTimeField&&(e?this._seekTimeField.disabled=!1:(this._seekTimeField.value=0,this._seekTimeField.disabled=!0)),this}detach(){this.enable(!1),this._controlbar&&this._controlbar.parentNode&&this._controlbar.parentNode.removeChild(this._controlbar),this._controlbar=void 0,this._container=void 0}}var ei,ti;!function(e){e[e.LIVE=0]="LIVE",e[e.VOD=1]="VOD"}(ei||(ei={})),function(e){e.LIVE="LiveSeek.LIVE",e.VOD="LiveSeek.VOD"}(ti||(ti={}));const ii={[ei.LIVE]:ti.LIVE,[ei.VOD]:ti.VOD};var ni;!function(e){e.LIVE_SEEK_UNSUPPORTED="WebRTC.LiveSeek.Unsupported",e.LIVE_SEEK_ERROR="WebRTC.LiveSeek.Error",e.LIVE_SEEK_ENABLED="WebRTC.LiveSeek.Enabled",e.LIVE_SEEK_DISABLED="WebRTC.LiveSeek.Disabled",e.LIVE_SEEK_LOADING="WebRTC.LiveSeek.FragmentLoading",e.LIVE_SEEK_LOADED="WebRTC.LiveSeek.FragmentLoaded",e.LIVE_SEEK_CHANGE="WebRTC.LiveSeek.Change"}(ni||(ni={}));const{createElement:si,findByQuerySelector:oi,createHLSClient:ri,getHLSClientEventEnum:ai}=ie,li="SourceHandlerSeekable",di=e=>O(li,e),hi=e=>k(li,e),ci=e=>H(li,e);class ui extends Tt{constructor(e,t,i,n,s=!0){super(e,`${t}-Seekable`),this._hlsElementGenerated=!1,this._hlsRecoverFlop=!1,this._hlsRecoverAttempts=0,this._isFragLoading=!1,this._wallOffset=NaN,this._lastDurationUpdate=0,this._averageSegmentDuration=6,this._isSeekable=!1,this._isHLSPlaybackActive=!1,this._container=s?this._determineContainer(e):void 0,this._liveSeekConfig=i,this._hlsOptions=n,this._usePlaybackControls=s,this.onHLSDurationChange=this._onHLSDurationChange.bind(this),this.onHLSTimeUpdate=this._onHLSTimeUpdate.bind(this),this.onHLSPlay=this._onHLSPlay.bind(this),this.onHLSPause=this._onHLSPause.bind(this)}_determineContainer(e){if(e.parentNode&&e.parentNode.classList.contains("red5pro-media-container"))return e.classList.add("red5pro-media"),e.parentNode;{const t=e.parentNode,i=si("div");return i.classList.add("red5pro-media-container"),e.classList.add("red5pro-media"),t.insertBefore(i,e),t.removeChild(e),i.appendChild(e),i}}_generateHLSLivePlayback(e,t,i){const n=`${i}-hls-vod`;let s=oi(`#${n}`);return s||(s=si("video"),s.id=n,s.classList.add("red5pro-hls-vod"),s.classList.add("red5pro-media-background"),s.setAttribute("playsinline","playsinline"),s.style.width="100%",s.style.height="100%",s.style.display="none",e.insertBefore(s,t),this._hlsElementGenerated=!0),s}_onDurationChange(e){var t;di("[videoelement:event] durationchange");const i=null!==(t=this._playbackNotificationCenter)&&void 0!==t?t:e.target,n=this.getControls();!this.isSeekable&&n&&n.setPlaybackDuration(i.duration)}_onTimeUpdate(t){var i;const n=null!==(i=this._playbackNotificationCenter)&&void 0!==i?i:t.target,s=this.getControls();if(this.isSeekable){if(!this._isHLSPlaybackActive){const t=this._hlsElement.duration,i=n.currentTime-this._lastDurationUpdate,o=isNaN(t)||0===t?n.currentTime:t+this._averageSegmentDuration+i;s&&s.setSeekTime(o,o),this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:o,duration:o,action:"rtc time update (1)"}))}}else super._onTimeUpdate(t)}_onEnded(){this.isHLSPlaybackActive||super._onEnded()}_onHLSDurationChange(t){const i=t.target,n=t.duration||i.duration;isNaN(this._wallOffset)&&(this._wallOffset=n-this._view.currentTime),this._lastDurationUpdate=this._view.currentTime;const s=n+this._averageSegmentDuration;di(`[HLS:videoelement:duration] ${n}, ${this._averageSegmentDuration}`);const o=this.getControls();o&&o.setPlaybackDuration(s),this._isHLSPlaybackActive?this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:i.currentTime,duration:s,action:"hls time update"})):this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:s,duration:s,action:"hls time update"}))}_onHLSTimeUpdate(t){const i=t.target,n=this.getControls();n&&n.setSeekTime(i.currentTime,n.getPlaybackDuration()),i.currentTime>=i.duration?this._showHLSLivePlayback(!1,this._hlsElement,this._view,this._container):!isNaN(i.duration)&&this._isHLSPlaybackActive&&this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_TIME_UPDATE,void 0,{time:i.currentTime,duration:i.duration+this._averageSegmentDuration,action:"hls time update"}))}_onHLSPlay(){di("[HLS:videoelement:event] play");const t=this.getControls();t&&t.setState(e.PlaybackState.PLAYING),this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.PLAYING,state:o[e.PlaybackState.PLAYING]}))}_onHLSPause(){di("[HLS:videoelement:event] pause");const t=this.getControls();t&&t.setState(e.PlaybackState.PAUSED),this.trigger(new Se(e.SubscriberEventTypes.PLAYBACK_STATE_CHANGE,void 0,{code:e.PlaybackState.PAUSED,state:o[e.PlaybackState.PAUSED]}))}_addSeekableHandlers(e,t,i){if(t){const i=ai();t.on(i.ERROR,((i,n)=>{const{type:s,details:o,fatal:r,url:a}=n;if("networkerror"===s.toLowerCase()){if("levelemptyerror"===o.toLowerCase()){this.trigger(new Se(ni.LIVE_SEEK_DISABLED,void 0,{hlsElement:e,hlsControl:t})),this.isSeekable=!1,t.destroy();const i=setTimeout((()=>{clearTimeout(i),this.enableLiveSeek(a,this._subscriptionId,this._hlsElement,!1)}),3e3);return}this.trigger(new Se(ni.LIVE_SEEK_ERROR,void 0,{hlsElement:e,hlsControl:t,error:n}))}else this.trigger(new Se(ni.LIVE_SEEK_ERROR,void 0,{hlsElement:e,hlsControl:t,error:n}));"mediaerror"===s.toLowerCase()&&(this._hlsRecoverFlop&&t.swapAudioCodec(),this._hlsRecoverFlop=!this._hlsRecoverFlop,this._hlsRecoverAttempts=this._hlsRecoverAttempts+1,t.recoverMediaError()),r&&"networkerror"===s.toLowerCase()&&t.startLoad()})),t.on(i.MANIFEST_PARSED,(()=>{try{e.pause()}catch(e){di(`Could not pause seekable live stream: ${e.message}`)}this.isSeekable=!0,this.trigger(new Se(ni.LIVE_SEEK_ENABLED,void 0,{hlsElement:e,hlsControl:t}))})),t.on(i.FRAG_LOADING,((i,n)=>{const{frag:{stats:{loaded:s,total:o}}}=n;this.trigger(new Se(ni.LIVE_SEEK_LOADING,void 0,{hlsElement:e,hlsControl:t,progress:s/o*100})),(this._isHLSPlaybackActive||this._isFragLoading)&&(this._isFragLoading=s/o>=1)})),t.on(i.FRAG_LOADED,((i,n)=>{this._isFragLoading=!1;const{frag:{endDTS:s,loader:o}}=n;if(!this._isHLSPlaybackActive&&!s)return;let r=6,a=0;if(o&&o.stats&&o.stats.segments){const e=o.stats.segments;for(let t=0;t{this._isFragLoading=!1;const{frag:{endDTS:s,loader:o}}=n;if(!this._isHLSPlaybackActive&&!s)return;let r=6,a=0;if(o&&o.stats&&o.stats.segments){const e=o.stats.segments;for(let t=0;tn.test(e)));if(!r)return void ci(`Could not find last segment in manifest: ${e}`);const a=o.find((e=>i.test(e)));if(!a)return void ci(`Could not find duration line in manifest: ${e}`);const l=a.match(i);if(!l)return void ci(`Could not find duration in manifest: ${e}`);const d=l[1],h=parseFloat(d),c=r.match(n);if(!c)return void ci(`Could not find segment length in manifest: ${e}`);const u=c[1];let p=parseInt(u,10);isNaN(p)&&(p=1),p=p>1?p-1:p,this._averageSegmentDuration=h,this.isSeekable=!0,this.trigger(new Se(ni.LIVE_SEEK_ENABLED,void 0,{hlsElement:this._hlsElement,hlsControl:void 0})),this.onHLSDurationChange({target:t,duration:h*p}),this._manifestLoadTimeout=setTimeout((()=>{clearTimeout(this._manifestLoadTimeout),this._loadManifest(e,t)}),1e3*h)}catch(e){hi(`Could not load manifest: ${e.message}.`),this.trigger(new Se(ni.LIVE_SEEK_DISABLED,void 0,{hlsElement:t,hlsControl:void 0})),this.isSeekable=!1}}_cleanup(){this._removeSeekableHandlers(this._hlsElement,this._hlsjsRef),this._hlsjsRef&&(this._hlsjsRef.detachMedia(),this._hlsjsRef=void 0),this._hlsElement&&(this._hlsElement.parentNode&&this._hlsElementGenerated&&this._hlsElement.parentNode.removeChild(this._hlsElement),this._hlsElement=void 0),this._playbackControls&&(this._playbackControls.detach(),this._playbackControls=void 0),this._isVOD=!1,this._isSeekable=!1,this._isHLSPlaybackActive=!1,this._isFragLoading=!1,this._hlsRecoverFlop=!1,this._hlsRecoverAttempts=0,this._averageSegmentDuration=6,this._hlsElementGenerated=!1,this._wallOffset=NaN,this._lastDurationUpdate=0,this._manifestLoadTimeout&&(clearTimeout(this._manifestLoadTimeout),this._manifestLoadTimeout=void 0),super._cleanup()}addSource(){di("[addSource]"),this._view.controls=!0,this._view.classList.add("red5pro-media");this._view.hasAttribute("controls")&&this._view.classList.contains("red5pro-media")&&(this._container=this._determineContainer(this._view));const e=this._view.hasAttribute("muted");this._usePlaybackControls?(this._playbackControls=new Zt(this,this._container),this._view.controls=!1,this._playbackControls.setAsVOD(this.isSeekable),this._playbackControls.setMutedState(e)):this._view.controls=!1}enableLiveSeek(e,t,i,n=!1){if(this.getControls()&&this.getControls().setSeekTime(1,1),this._url=e,this._subscriptionId=t,this._hlsElement=i||this._generateHLSLivePlayback(this._container,this._view,t),this._showHLSLivePlayback(this._isHLSPlaybackActive,this._hlsElement,this._view,this._container),n){this._addSeekableHandlers(this._hlsElement,void 0,!1);const t=si("source");t.src=e,this._hlsElement.appendChild(t),this._loadManifest(e,this._hlsElement)}else{const t=this._hlsOptions,{liveSeek:{hlsjsRef:i}}=this._liveSeekConfig,n=i?new i(t):ri(t);this._addSeekableHandlers(this._hlsElement,n,!0),n.attachMedia(this._hlsElement,e),n.on(ai().MEDIA_ATTACHED,(()=>{n.loadSource(e)})),this._hlsjsRef=n}}switchLiveSeek(e){this._hlsjsRef&&(this._hlsjsRef.destroy(),this._hlsjsRef=void 0),this.enableLiveSeek(e,this._subscriptionId,this._hlsElement),this.seekTo(1);try{this._view.play()}catch(e){ci("[videoelement:action] play (FAULT) - "+e.message)}this._url=e}async play(e=!1){di("[videoelement:action] play");try{return e&&this._hlsElement&&this._hlsElement.paused?(await this._hlsElement.play(),!0):super.play()}catch(e){ci("[videoelement:action] play (CATCH::FAULT) - "+e.message)}return!1}async pause(e=!1,t=!1){di("[videoelement:action] pause");try{return e&&t&&this._hlsElement?(this._hlsElement.pause(),super.pause()):e&&this._hlsElement&&!this._hlsElement.paused?(this._hlsElement.pause(),!0):super.pause()}catch(e){ci("[videoelement:action] pause (CATCH::FAULT) - "+e.message)}return!1}async resume(e=!1){var t,i;di("[videoelement:action] resume");try{const n=this._isHLSPlaybackActive&&this._hlsElement?this._hlsElement.play():null===(t=this._view)||void 0===t?void 0:t.play();if(e&&this._isHLSPlaybackActive)return await(null===(i=this._view)||void 0===i?void 0:i.play()),!0;n&&n.then((()=>di("[videoelement:action] play (START)"))).catch((e=>ci("[videoelement:action] play (CATCH::FAULT) "+(e.message?e.message:e))))}catch(e){ci("[videoelement:action] resume (CATCH::FAULT) - "+e.message)}return!1}async stop(){di("[videoelement:action] stop");try{return this._hlsElement&&this._hlsElement.pause(),super.stop()}catch(e){ci("[videoelement:action] stop (CATCH::FAULT) - "+e.message)}return!1}mute(){this._hlsElement&&(this._hlsElement.muted=this._isHLSPlaybackActive),this._view&&(this._view.muted=!0);const e=this.getControls();e&&e.setMutedState(!0)}unmute(){this._hlsElement&&(this._hlsElement.muted=!this._isHLSPlaybackActive,this._view&&(this._view.muted=this._isHLSPlaybackActive)),this._view&&(this._view.muted=!1);const e=this.getControls();e&&e.setMutedState(!1)}setVolume(e){this.unmute(),this._hlsElement&&this._isHLSPlaybackActive?this._hlsElement.volume=e:this._view?this._view.volume=e:hi("[videoelement:action] setVolume (CATCH::FAULT) - "+e)}seekTo(e,t=void 0){if(this.isSeekable)if(this.getControls()&&this.getControls().setSeekTime(e,t),this.trigger(new Se(ni.LIVE_SEEK_CHANGE,void 0,{seek:e,duration:t})),this._hlsElement&&e<1)try{this._hlsElement.classList.remove("hidden"),this._hlsElement.currentTime=this._hlsElement.duration*e,this._isFragLoading=!0,this._showHLSLivePlayback(!0,this._hlsElement,this._view,this._container),this._view.paused||(di("[hlsvod:action] play (START) - (seekTo)"),this.play(!0))}catch(e){ci("[hlsvod:action] play (CATCH::FAULT) - "+e.message)}else this._hlsElement&&e>=1&&(this._isFragLoading=!1,this._showHLSLivePlayback(!1,this._hlsElement,this._view,this._container));else this._view.currentTime=t?e*t:e}toggleFullScreen(e){var t;this._container&&super.toggleFullScreen(null!==(t=this._container)&&void 0!==t?t:e)}getControls(){return this._playbackControls}get isSeekable(){return this._isSeekable}set isSeekable(e){this._isSeekable=e,this.getControls()&&this.getControls().setAsVOD(e)}get isHLSPlaybackActive(){return this._isHLSPlaybackActive}get url(){return this._url}}const{supportsHLS:pi,supportsNonNativeHLS:_i}=ie,mi="WHEPLiveSeekClient",gi=e=>k(mi,e);class vi extends Lt{constructor(e,t,i){super(e,t,i)}async init(e){const{liveSeek:t}=e;return t||(e.liveSeek=Ht),super.init(e)}_attachSourceHandler(e){var t;if((null===(t=this._playbackView)||void 0===t?void 0:t.view)&&!this._enableLiveSeek(this._playbackView.view))return H(mi,"LiveSeek is not enabled, using default source handler"),void super._attachSourceHandler(e);this._startSeekableIfSeekableEnabled(this._options)}_enableLiveSeek(e){const{liveSeek:t}=this._options;if(t){const{hlsjsRef:i,usePlaybackControlsUI:n,options:s}=t;if(pi()||_i(i))return this._sourceHandler=new ui(e,this.getType(),this._options,s,n),this._sourceHandler.addSource(),!0;gi("Could not utilize the 'LiveSeek' request. This feature requires either native HLS playback or hls.js as a depenency."),this.trigger(new Se(ni.LIVE_SEEK_UNSUPPORTED,this,{feature:"Live Seek",message:"Live Seek requires integration with the HLS.JS plugin in order work properly. Most likely you are viewing this on a browser that does not support the use of HLS.JS."}))}return!1}_startSeekableIfSeekableEnabled(e){const{liveSeek:t,subscriptionId:i}=e;if(!t)return;const{hlsjsRef:n,hlsElement:s}=t;if(this._sourceHandler)try{if(!pi()&&!_i(n))throw new Error;{const t=ne(e);this._sourceHandler.enableLiveSeek(t,i,s,!_i(n))}}catch(e){gi("Could not utilize the 'LiveSeek' request. This feature requires either native HLS playback or hls.js as a depenency.")}}_onUnpublish(){super._onUnpublish();const{liveSeek:e}=this._options;e||this.unsubscribe(!0)}_onStreamSwitchComplete(){const e=this._requestedStreamSwitch,{liveSeek:t}=this._options;if(t&&e){const{baseURL:i,fullURL:n}=t,s=e.split("/"),o=s.pop(),r=s.join("/"),a={...this._options,app:r,streamName:o};let l=n;if(n){const e=/.*\/(.*)\.m3u8/.exec(n);if(e&&e.length>1){const t=`${e[1]}.m3u8`;l=n.replace(t,`${o}.m3u8`)}}const d=ne(a,i,l);this._sourceHandler&&this._sourceHandler.switchLiveSeek(d)}super._onStreamSwitchComplete()}}const Ei="15.2.0";N(R.ERROR);const Si=(e,t=!1)=>{Object.prototype.hasOwnProperty.call(R,e.toUpperCase())&&(N(e,t),console&&console.log(`Red5 Pro SDK Version ${Ci()}`))},Ci=()=>Ei;O("RED5",`Red5 Pro HTML SDK Version: ${Ei}`);var bi={version:Ei,LOG_LEVELS:R,getLogger:D,getRecordedLogs:I,setLogLevel:Si,getVersion:Ci,PlaybackVideoEncoder:e.PlaybackVideoEncoder,PlaybackAudioEncoder:e.PlaybackAudioEncoder,PlaybackState:e.PlaybackState,PlaybackStateReadableMap:o,PublishVideoEncoder:e.PublishVideoEncoder,PublishAudioEncoder:e.PublishAudioEncoder,SubscriberEvent:Se,PublisherEvent:Ee,MessageTransportStateEvent:Ce,PublisherEventTypes:e.PublisherEventTypes,SubscriberEventTypes:e.SubscriberEventTypes,RTCPublisherEventTypes:e.RTCPublisherEventTypes,RTCSubscriberEventTypes:e.RTCSubscriberEventTypes,MessageTransportStateEventTypes:e.MessageTransportStateEventTypes,WHIPClient:dt,WHEPClient:Lt,HLSSubscriber:Ot,LiveSeekClient:vi,defaultWhepSubscriberConfig:ht,defaultWhipPublisherConfig:me};e.Event=ve,e.EventEmitter=U,e.HLSSubscriber=Ot,e.LOG_LEVELS=R,e.LiveSeekClient=vi,e.MessageTransportStateEvent=Ce,e.PlaybackController=Et,e.PlaybackControls=Mt,e.PlaybackStateReadableMap=o,e.PublisherEvent=Ee,e.SourceHandler=St,e.SourceHandlerImpl=Tt,e.SubscriberEvent=Se,e.WHEPClient=Lt,e.WHIPClient=dt,e.default=bi,e.defaultHLSSubscriberConfig=ct,e.defaultLiveSeekConfig=kt,e.defaultStatsConfig=pe,e.defaultWhepSubscriberConfig=ht,e.defaultWhipPublisherConfig=me,e.getLogger=D,e.getRecordedLogs=I,e.getVersion=Ci,e.setLogLevel=Si,Object.defineProperty(e,"__esModule",{value:!0})}));