openvidu-browser: update dependencies

v2
pabloFuente 2025-11-19 14:22:45 +01:00
parent a14cd70b09
commit 5cf0cf0e11
37 changed files with 5037 additions and 935 deletions

View File

@ -0,0 +1,76 @@
module.exports = {
root: true,
ignorePatterns: ['lib/**', 'ts4.4/**', 'node_modules/**', 'static/**', 'openvidu-browser-*.tgz'],
env: {
browser: true,
es2020: true,
node: true
},
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module'
},
plugins: ['@typescript-eslint', 'import'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:import/recommended', 'plugin:import/typescript'],
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.ts']
},
typescript: {
project: ['./tsconfig.json', './src/OpenVidu/tsconfig.json']
}
}
},
rules: {
'@typescript-eslint/array-type': ['error', { default: 'array' }],
'@typescript-eslint/ban-types': [
'error',
{
extendDefaults: true,
types: {
Object: {
message: 'Avoid using the `Object` type. Did you mean `object`?',
fixWith: 'object'
},
Function: {
message: 'Avoid using the `Function` type. Prefer a specific function type.'
},
Boolean: {
message: 'Avoid using the `Boolean` type. Did you mean `boolean`?',
fixWith: 'boolean'
},
Number: {
message: 'Avoid using the `Number` type. Did you mean `number`?',
fixWith: 'number'
},
String: {
message: 'Avoid using the `String` type. Did you mean `string`?',
fixWith: 'string'
}
}
}
],
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-inferrable-types': 'error',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/type-annotation-spacing': 'error',
curly: ['error', 'multi-line', 'consistent'],
eqeqeq: ['error', 'always'],
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: ['config/**', '**/*.spec.ts', '**/*.test.ts']
}
],
'no-trailing-spaces': ['error', { skipBlankLines: false, ignoreComments: false }],
'no-var': 'error',
'object-shorthand': ['error', 'always'],
'prefer-const': 'error',
quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: false }],
semi: ['error', 'always'],
'space-in-parens': 'off'
}
};

View File

@ -0,0 +1,5 @@
lib
node_modules
static
ts4.4
openvidu-browser-*.tgz

View File

@ -1,10 +1,10 @@
{ {
"singleQuote": true, "singleQuote": true,
"printWidth": 140, "printWidth": 140,
"trailingComma": "none", "trailingComma": "none",
"semi": true, "semi": true,
"bracketSpacing": true, "bracketSpacing": true,
"useTabs": false, "useTabs": false,
"jsxSingleQuote": true, "jsxSingleQuote": true,
"tabWidth": 4 "tabWidth": 4
} }

View File

@ -0,0 +1,5 @@
{
"singleQuote": true,
"printWidth": 120,
"trailingComma": "es5"
}

View File

@ -1,6 +1,6 @@
{ {
"include": ["../src"], "include": ["../src"],
"exclude": ["../config", "../docs", "../lib", "../node_modules", "../ts4.4"], "exclude": ["../config", "../docs", "../lib", "../node_modules", "../ts4.4"],
"typedocOptions": { "typedocOptions": {
"name": "OpenVidu Browser", "name": "OpenVidu Browser",
"entryPoints": ["../src/index.ts"], "entryPoints": ["../src/index.ts"],
@ -17,4 +17,4 @@
"excludeProtected": true, "excludeProtected": true,
"excludeInternal": true "excludeInternal": true
} }
} }

View File

@ -1,81 +1,37 @@
{ {
"extends": "tslint:recommended", "extends": "tslint:recommended",
"rules": { "rules": {
"array-type": [ "array-type": [true, "array"],
true,
"array"
],
"ban-types": { "ban-types": {
"options": [ "options": [
[ ["Object", "Avoid using the `Object` type. Did you mean `object`?"],
"Object",
"Avoid using the `Object` type. Did you mean `object`?"
],
[ [
"Function", "Function",
"Avoid using the `Function` type. Prefer a specific function type, like `() => void`, or use `ts.AnyFunction`." "Avoid using the `Function` type. Prefer a specific function type, like `() => void`, or use `ts.AnyFunction`."
], ],
[ ["Boolean", "Avoid using the `Boolean` type. Did you mean `boolean`?"],
"Boolean", ["Number", "Avoid using the `Number` type. Did you mean `number`?"],
"Avoid using the `Boolean` type. Did you mean `boolean`?" ["String", "Avoid using the `String` type. Did you mean `string`?"]
],
[
"Number",
"Avoid using the `Number` type. Did you mean `number`?"
],
[
"String",
"Avoid using the `String` type. Did you mean `string`?"
]
] ]
}, },
"class-name": true, "class-name": true,
"comment-format": [ "comment-format": [true, "check-space"],
true, "curly": [true, "ignore-same-line"],
"check-space" "indent": [true, "spaces", 2],
], "interface-name": [true, "never-prefix"],
"curly": [
true,
"ignore-same-line"
],
"indent": [
true,
"spaces",
2
],
"interface-name": [
true,
"never-prefix"
],
"interface-over-type-literal": true, "interface-over-type-literal": true,
"jsdoc-format": true, "jsdoc-format": true,
"no-inferrable-types": true, "no-inferrable-types": true,
"no-internal-module": true, "no-internal-module": true,
"no-null-keyword": false, "no-null-keyword": false,
"no-switch-case-fall-through": true, "no-switch-case-fall-through": true,
"no-trailing-whitespace": [ "no-trailing-whitespace": [true, "ignore-template-strings"],
true,
"ignore-template-strings"
],
"no-var-keyword": true, "no-var-keyword": true,
"object-literal-shorthand": true, "object-literal-shorthand": true,
"one-line": [ "one-line": [true, "check-open-brace", "check-whitespace"],
true,
"check-open-brace",
"check-whitespace"
],
"prefer-const": true, "prefer-const": true,
"quotemark": [ "quotemark": [true, "single", "avoid-escape", "avoid-template"],
true, "semicolon": [true, "always", "ignore-bound-class-methods"],
"single",
"avoid-escape",
"avoid-template"
],
"semicolon": [
true,
"always",
"ignore-bound-class-methods"
],
"space-within-parens": true, "space-within-parens": true,
"triple-equals": true, "triple-equals": true,
"typedef-whitespace": [ "typedef-whitespace": [
@ -95,29 +51,10 @@
"variable-declaration": "onespace" "variable-declaration": "onespace"
} }
], ],
"whitespace": [ "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type"],
true, "no-implicit-dependencies": [true, "dev"],
"check-branch", "object-literal-key-quotes": [true, "consistent-as-needed"],
"check-decl", "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"],
"check-operator",
"check-module",
"check-separator",
"check-type"
],
"no-implicit-dependencies": [
true,
"dev"
],
"object-literal-key-quotes": [
true,
"consistent-as-needed"
],
"variable-name": [
true,
"ban-keywords",
"check-format",
"allow-leading-underscore"
],
"arrow-parens": false, "arrow-parens": false,
"arrow-return-shorthand": false, "arrow-return-shorthand": false,
"forin": false, "forin": false,
@ -151,4 +88,4 @@
"one-variable-per-declaration": false, "one-variable-per-declaration": false,
"unified-signatures": false "unified-signatures": false
} }
} }

View File

@ -0,0 +1,74 @@
const tseslint = require('@typescript-eslint/eslint-plugin');
const tsParser = require('@typescript-eslint/parser');
const importPlugin = require('eslint-plugin-import');
const globals = require('globals');
module.exports = [
{
ignores: ['lib/**', 'ts4.4/**', 'node_modules/**', 'static/**', 'openvidu-browser-*.tgz']
},
{
files: ['**/*.ts'],
languageOptions: {
parser: tsParser,
ecmaVersion: 2020,
sourceType: 'module',
parserOptions: {
project: ['./tsconfig.json', './src/OpenVidu/tsconfig.json'],
tsconfigRootDir: __dirname,
noWarnOnMultipleProjects: true
},
globals: {
...globals.browser,
...globals.node
}
},
plugins: {
'@typescript-eslint': tseslint,
import: importPlugin
},
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.ts']
},
typescript: {
project: ['./tsconfig.json', './src/OpenVidu/tsconfig.json'],
noWarnOnMultipleProjects: true
}
}
},
linterOptions: {
reportUnusedDisableDirectives: 'off'
},
rules: {
'@typescript-eslint/array-type': 'off',
'@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-wrapper-object-types': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-var-requires': 'off',
curly: 'off',
eqeqeq: 'off',
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: ['config/**', '**/*.spec.ts', '**/*.test.ts']
}
],
'import/no-unresolved': 'off',
'no-trailing-spaces': ['error', { skipBlankLines: false, ignoreComments: false }],
'no-var': 'off',
'object-shorthand': 'off',
'prefer-const': 'off',
quotes: 'off',
semi: ['error', 'always'],
'no-unused-vars': 'off',
'no-extra-boolean-cast': 'off',
'no-undef': 'off'
}
}
];

File diff suppressed because it is too large Load Diff

View File

@ -6,22 +6,29 @@
"hark": "1.2.3", "hark": "1.2.3",
"inherits": "2.0.4", "inherits": "2.0.4",
"jsnlog": "2.30.0", "jsnlog": "2.30.0",
"mime": "3.0.0", "mime": "2.6.0",
"platform": "1.3.6", "platform": "1.3.6",
"semver": "7.6.2", "semver": "7.7.3",
"uuid": "9.0.1", "uuid": "^8.3.2",
"wolfy87-eventemitter": "5.2.9" "wolfy87-eventemitter": "5.2.9"
}, },
"description": "OpenVidu Browser", "description": "OpenVidu Browser",
"devDependencies": { "devDependencies": {
"@types/node": "18.11.9", "@types/node": "24.10.1",
"@types/platform": "1.3.4", "@types/platform": "1.3.6",
"browserify": "17.0.0", "@typescript-eslint/eslint-plugin": "8.47.0",
"terser": "5.15.1", "@typescript-eslint/parser": "8.47.0",
"browserify": "17.0.1",
"eslint": "9.39.1",
"eslint-import-resolver-typescript": "4.4.4",
"eslint-plugin-import": "2.32.0",
"patch-package": "^8.0.1",
"prettier": "3.6.2",
"terser": "5.44.1",
"tsify": "5.0.4", "tsify": "5.0.4",
"tslint": "6.1.3", "typedoc": "0.28.14",
"typedoc": "0.23.21", "typescript": "5.9.3",
"typescript": "4.9.3" "undici-types": "7.16.0"
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "lib/index.js", "main": "lib/index.js",
@ -33,8 +40,10 @@
"scripts": { "scripts": {
"browserify": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/openvidu-browser-$VERSION.js -v", "browserify": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/openvidu-browser-$VERSION.js -v",
"browserify-prod": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js --debug Main.ts -p [ tsify ] --exclude kurento-browser-extensions | ../node_modules/terser/bin/terser --source-map content=inline --output ../static/js/openvidu-browser-$VERSION.min.js", "browserify-prod": "VERSION=${VERSION:-dev}; mkdir -p static/js/ && cd src && ../node_modules/browserify/bin/cmd.js --debug Main.ts -p [ tsify ] --exclude kurento-browser-extensions | ../node_modules/terser/bin/terser --source-map content=inline --output ../static/js/openvidu-browser-$VERSION.min.js",
"build": "cd src/OpenVidu && ./../../node_modules/typescript/bin/tsc && cd ../.. && ./node_modules/typescript/bin/tsc --declaration src/index.ts --outDir ./lib --sourceMap --target es5 --lib dom,es5,es2015.promise,scripthost && rm -rf ./ts4.4 && mkdir -p ./ts4.4/lib && cp -r ./lib ./ts4.4 && find ./ts4.4/lib -type f ! -iname '*.d.ts' -delete && ./config/replace_for_ts44.sh", "build": "npm run lint && npm run beautify && cd src/OpenVidu && ./../../node_modules/typescript/bin/tsc && cd ../.. && ./node_modules/typescript/bin/tsc --declaration src/index.ts --outDir ./lib --sourceMap --target es2015 --module commonjs --moduleResolution node --lib dom,es2015,scripthost && rm -rf ./ts4.4 && mkdir -p ./ts4.4/lib && cp -r ./lib ./ts4.4 && find ./ts4.4/lib -type f ! -iname '*.d.ts' -delete && ./config/replace_for_ts44.sh",
"docs": "./generate-docs.sh" "docs": "./generate-docs.sh",
"lint": "eslint . --ext .ts",
"beautify": "prettier --write ."
}, },
"types": "lib/index.d.ts", "types": "lib/index.d.ts",
"typesVersions": { "typesVersions": {

View File

@ -95,7 +95,10 @@ export class Connection {
/** /**
* @hidden * @hidden
*/ */
constructor(private session: Session, connectionOptions: LocalConnectionOptions | RemoteConnectionOptions) { constructor(
private session: Session,
connectionOptions: LocalConnectionOptions | RemoteConnectionOptions
) {
let msg = "'Connection' created "; let msg = "'Connection' created ";
if (!!(<LocalConnectionOptions>connectionOptions).role) { if (!!(<LocalConnectionOptions>connectionOptions).role) {
// Connection is local // Connection is local
@ -129,7 +132,6 @@ export class Connection {
* @hidden * @hidden
*/ */
sendIceCandidate(candidate: RTCIceCandidate): void { sendIceCandidate(candidate: RTCIceCandidate): void {
if (!this.disposed) { if (!this.disposed) {
logger.debug((!!this.stream!.outboundStreamOpts ? 'Local' : 'Remote') + 'candidate for' + this.connectionId, candidate); logger.debug((!!this.stream!.outboundStreamOpts ? 'Local' : 'Remote') + 'candidate for' + this.connectionId, candidate);

View File

@ -19,7 +19,7 @@ import { Stream } from './Stream';
import { LocalRecorderState } from '../OpenViduInternal/Enums/LocalRecorderState'; import { LocalRecorderState } from '../OpenViduInternal/Enums/LocalRecorderState';
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
import Mime = require('mime/lite'); import mime from 'mime';
/** /**
* @hidden * @hidden
@ -288,7 +288,7 @@ export class LocalRecorder {
const url = globalThis.URL.createObjectURL(<any>this.blob); const url = globalThis.URL.createObjectURL(<any>this.blob);
a.href = url; a.href = url;
a.download = this.id + '.' + Mime.getExtension(this.blob!.type); a.download = this.id + '.' + mime.getExtension(this.blob!.type);
a.click(); a.click();
globalThis.URL.revokeObjectURL(url); globalThis.URL.revokeObjectURL(url);
@ -383,7 +383,7 @@ export class LocalRecorder {
} }
const sendable = new FormData(); const sendable = new FormData();
sendable.append('file', this.blob!, this.id + '.' + Mime.getExtension(this.blob!.type)); sendable.append('file', this.blob!, this.id + '.' + mime.getExtension(this.blob!.type));
http.onreadystatechange = () => { http.onreadystatechange = () => {
if (http.readyState === 4) { if (http.readyState === 4) {

View File

@ -220,8 +220,8 @@ export class OpenVidu {
typeof MediaStreamTrack !== 'undefined' && properties.videoSource instanceof MediaStreamTrack typeof MediaStreamTrack !== 'undefined' && properties.videoSource instanceof MediaStreamTrack
? undefined ? undefined
: typeof properties.frameRate !== 'undefined' : typeof properties.frameRate !== 'undefined'
? properties.frameRate ? properties.frameRate
: undefined, : undefined,
insertMode: insertMode:
typeof properties.insertMode !== 'undefined' typeof properties.insertMode !== 'undefined'
? typeof properties.insertMode === 'string' ? typeof properties.insertMode === 'string'
@ -235,8 +235,8 @@ export class OpenVidu {
typeof MediaStreamTrack !== 'undefined' && properties.videoSource instanceof MediaStreamTrack typeof MediaStreamTrack !== 'undefined' && properties.videoSource instanceof MediaStreamTrack
? undefined ? undefined
: typeof properties.resolution !== 'undefined' : typeof properties.resolution !== 'undefined'
? properties.resolution ? properties.resolution
: '640x480', : '640x480',
videoSource: typeof properties.videoSource !== 'undefined' ? properties.videoSource : undefined, videoSource: typeof properties.videoSource !== 'undefined' ? properties.videoSource : undefined,
videoSimulcast: properties.videoSimulcast, videoSimulcast: properties.videoSimulcast,
filter: properties.filter filter: properties.filter
@ -567,7 +567,10 @@ export class OpenVidu {
if (navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) { if (navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) {
// getDisplayMedia supported // getDisplayMedia supported
try { try {
const mediaStream = await navigator.mediaDevices['getDisplayMedia']({ video: true, audio: options.audioSource === 'screen' }); const mediaStream = await navigator.mediaDevices['getDisplayMedia']({
video: true,
audio: options.audioSource === 'screen'
});
this.addAlreadyProvidedTracks(myConstraints, mediaStream); this.addAlreadyProvidedTracks(myConstraints, mediaStream);
if (mustAskForAudioTrackLater) { if (mustAskForAudioTrackLater) {
return await askForAudioStreamOnly(mediaStream, <MediaStreamConstraints>myConstraints.constraints); return await askForAudioStreamOnly(mediaStream, <MediaStreamConstraints>myConstraints.constraints);
@ -587,9 +590,7 @@ export class OpenVidu {
} }
} }
// Use already calculated constraints // Use already calculated constraints
const constraintsAux = mustAskForAudioTrackLater const constraintsAux = mustAskForAudioTrackLater ? { video: myConstraints.constraints!.video } : myConstraints.constraints;
? { video: myConstraints.constraints!.video }
: myConstraints.constraints;
try { try {
const mediaStream = await navigator.mediaDevices.getUserMedia(constraintsAux); const mediaStream = await navigator.mediaDevices.getUserMedia(constraintsAux);
this.addAlreadyProvidedTracks(myConstraints, mediaStream); this.addAlreadyProvidedTracks(myConstraints, mediaStream);
@ -614,14 +615,12 @@ export class OpenVidu {
} }
} }
/* tslint:disable:no-empty */
/** /**
* Disable all logging except error level * Disable all logging except error level
*/ */
enableProdMode(): void { enableProdMode(): void {
logger.enableProdMode(); logger.enableProdMode();
} }
/* tslint:enable:no-empty */
/** /**
* Set OpenVidu advanced configuration options. `configuration` is an object of type {@link OpenViduAdvancedConfiguration}. Call this method to override previous values at any moment. * Set OpenVidu advanced configuration options. `configuration` is an object of type {@link OpenViduAdvancedConfiguration}. Call this method to override previous values at any moment.
@ -642,7 +641,12 @@ export class OpenVidu {
/** /**
* @hidden * @hidden
*/ */
sendNewVideoDimensionsIfRequired(publisher: Publisher, reason: StreamPropertyChangedEventReason, WAIT_INTERVAL: number, MAX_ATTEMPTS: number) { sendNewVideoDimensionsIfRequired(
publisher: Publisher,
reason: StreamPropertyChangedEventReason,
WAIT_INTERVAL: number,
MAX_ATTEMPTS: number
) {
let attempts = 0; let attempts = 0;
const oldWidth = publisher?.stream?.videoDimensions?.width || 0; const oldWidth = publisher?.stream?.videoDimensions?.width || 0;
const oldHeight = publisher?.stream?.videoDimensions?.height || 0; const oldHeight = publisher?.stream?.videoDimensions?.height || 0;
@ -1025,7 +1029,9 @@ export class OpenVidu {
if (!this.isScreenShare(videoSource)) { if (!this.isScreenShare(videoSource)) {
this.setVideoSource(myConstraints, videoSource); this.setVideoSource(myConstraints, videoSource);
if (audioSource === 'screen') { if (audioSource === 'screen') {
logger.warn('Parameter "audioSource" is set to "screen", which means rquesting audio from screen sharing source. But "videoSource" is not set to "screen". No audio source will be requested'); logger.warn(
'Parameter "audioSource" is set to "screen", which means rquesting audio from screen sharing source. But "videoSource" is not set to "screen". No audio source will be requested'
);
myConstraints.constraints!.audio = false; myConstraints.constraints!.audio = false;
} }
} else { } else {
@ -1035,9 +1041,9 @@ export class OpenVidu {
const error = new OpenViduError( const error = new OpenViduError(
OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED,
'You can only screen share in desktop Chrome, Firefox, Opera, Safari (>=13.0), Edge (>= 80) or Electron. Detected client: ' + 'You can only screen share in desktop Chrome, Firefox, Opera, Safari (>=13.0), Edge (>= 80) or Electron. Detected client: ' +
platform.getName() + platform.getName() +
' ' + ' ' +
platform.getVersion() platform.getVersion()
); );
logger.error(error); logger.error(error);
return reject(error); return reject(error);

View File

@ -63,7 +63,7 @@ export class Publisher extends StreamManager {
private accessDenied = false; private accessDenied = false;
protected properties: PublisherProperties; protected properties: PublisherProperties;
private permissionDialogTimeout: NodeJS.Timer; private permissionDialogTimeout: ReturnType<typeof setTimeout>;
/** /**
* @hidden * @hidden
@ -76,7 +76,7 @@ export class Publisher extends StreamManager {
/** /**
* @hidden * @hidden
*/ */
screenShareResizeInterval: NodeJS.Timer; screenShareResizeInterval: ReturnType<typeof setInterval>;
/** /**
* @hidden * @hidden
@ -172,11 +172,11 @@ export class Publisher extends StreamManager {
* *
* @param enabled `true` to publish the video stream, `false` to unpublish it * @param enabled `true` to publish the video stream, `false` to unpublish it
* @param resource * @param resource
* *
* If parameter **`enabled`** is `false`, this optional parameter is of type boolean. It can be set to `true` to forcibly free the hardware resource associated to the video track, or can be set to `false` to keep the access to the hardware resource. * If parameter **`enabled`** is `false`, this optional parameter is of type boolean. It can be set to `true` to forcibly free the hardware resource associated to the video track, or can be set to `false` to keep the access to the hardware resource.
* Not freeing the resource makes the operation much more efficient, but depending on the platform two side-effects can be introduced: the video device may not be accessible by other applications and the access light of * Not freeing the resource makes the operation much more efficient, but depending on the platform two side-effects can be introduced: the video device may not be accessible by other applications and the access light of
* webcams may remain on. This is platform-dependent: some browsers will not present the side-effects even when not freeing the resource. * webcams may remain on. This is platform-dependent: some browsers will not present the side-effects even when not freeing the resource.
* *
* If parameter **`enabled`** is `true`, this optional parameter is of type [MediaStreamTrack](https://developer.mozilla.org/docs/Web/API/MediaStreamTrack). It can be set to force the restoration of the video track with a custom track. This may be * If parameter **`enabled`** is `true`, this optional parameter is of type [MediaStreamTrack](https://developer.mozilla.org/docs/Web/API/MediaStreamTrack). It can be set to force the restoration of the video track with a custom track. This may be
* useful if the Publisher was unpublished freeing the hardware resource, and openvidu-browser is not able to successfully re-create the video track as it was before unpublishing. In this way previous track settings will be ignored and this MediaStreamTrack * useful if the Publisher was unpublished freeing the hardware resource, and openvidu-browser is not able to successfully re-create the video track as it was before unpublishing. In this way previous track settings will be ignored and this MediaStreamTrack
* will be used instead. * will be used instead.
@ -470,8 +470,7 @@ export class Publisher extends StreamManager {
}; };
if (this.stream.isSendScreen()) { if (this.stream.isSendScreen()) {
if (this.stream.isSendAudio() && mediaStream.getAudioTracks().length === 0) {
if(this.stream.isSendAudio() && mediaStream.getAudioTracks().length === 0){
// If sending audio is enabled and there are no audio tracks in the mediaStream, disable audio for screen sharing. // If sending audio is enabled and there are no audio tracks in the mediaStream, disable audio for screen sharing.
this.stream.audioActive = false; this.stream.audioActive = false;
this.stream.hasAudio = false; this.stream.hasAudio = false;
@ -653,7 +652,10 @@ export class Publisher extends StreamManager {
try { try {
if (this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) { if (this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) {
const mediaStream = await navigator.mediaDevices['getDisplayMedia']({ video: true, audio: this.properties.audioSource === 'screen' }); const mediaStream = await navigator.mediaDevices['getDisplayMedia']({
video: true,
audio: this.properties.audioSource === 'screen'
});
this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream); this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream);
await getMediaSuccess(mediaStream, definedAudioConstraint); await getMediaSuccess(mediaStream, definedAudioConstraint);
} else { } else {
@ -709,7 +711,8 @@ export class Publisher extends StreamManager {
getVideoDimensions(): Promise<{ width: number; height: number }> { getVideoDimensions(): Promise<{ width: number; height: number }> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Ionic iOS and Safari iOS supposedly require the video element to actually exist inside the DOM // Ionic iOS and Safari iOS supposedly require the video element to actually exist inside the DOM
const requiresDomInsertion: boolean = (platform.isIonicIos() || platform.isIOSWithSafari()) && (this.videoReference.readyState < 1); const requiresDomInsertion: boolean =
(platform.isIonicIos() || platform.isIOSWithSafari()) && this.videoReference.readyState < 1;
let loadedmetadataListener; let loadedmetadataListener;
const resolveDimensions = () => { const resolveDimensions = () => {

View File

@ -44,7 +44,13 @@ import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/Open
import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode'; import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
import { StreamPropertyChangedEventReason, ChangedPropertyType, RecordingEventReason, ConnectionEventReason, StreamEventReason } from '../OpenViduInternal/Events/Types/Types'; import {
StreamPropertyChangedEventReason,
ChangedPropertyType,
RecordingEventReason,
ConnectionEventReason,
StreamEventReason
} from '../OpenViduInternal/Events/Types/Types';
/** /**
* @hidden * @hidden
*/ */
@ -183,12 +189,12 @@ export class Session extends EventDispatcher {
new OpenViduError( new OpenViduError(
OpenViduErrorName.BROWSER_NOT_SUPPORTED, OpenViduErrorName.BROWSER_NOT_SUPPORTED,
'Browser ' + 'Browser ' +
platform.getName() + platform.getName() +
' (version ' + ' (version ' +
platform.getVersion() + platform.getVersion() +
') for ' + ') for ' +
platform.getFamily() + platform.getFamily() +
' is not supported in OpenVidu' ' is not supported in OpenVidu'
) )
); );
} }
@ -471,7 +477,7 @@ export class Session extends EventDispatcher {
return reject( return reject(
new Error( new Error(
'The associated Connection object of this Publisher is not your local Connection. ' + 'The associated Connection object of this Publisher is not your local Connection. ' +
"Only moderators can force unpublish on remote Streams via 'forceUnpublish' method" "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method"
) )
); );
} else { } else {
@ -652,7 +658,7 @@ export class Session extends EventDispatcher {
* *
* @param stream - The Stream for which you want to start receiving {@link SpeechToTextEvent}. * @param stream - The Stream for which you want to start receiving {@link SpeechToTextEvent}.
* @param lang - The language of the Stream's audio track. It must be a valid [BCP-47](https://tools.ietf.org/html/bcp47) language tag like "en-US" or "es-ES". * @param lang - The language of the Stream's audio track. It must be a valid [BCP-47](https://tools.ietf.org/html/bcp47) language tag like "en-US" or "es-ES".
* *
* @returns A Promise (to which you can optionally subscribe to) that is resolved if the speech-to-text subscription * @returns A Promise (to which you can optionally subscribe to) that is resolved if the speech-to-text subscription
* was successful and rejected with an Error object if not. * was successful and rejected with an Error object if not.
*/ */
@ -949,11 +955,11 @@ export class Session extends EventDispatcher {
this.getConnection( this.getConnection(
event.from, event.from,
"Connection '" + "Connection '" +
event.from + event.from +
"' unknown when 'onNewMessage'. Existing remote connections: " + "' unknown when 'onNewMessage'. Existing remote connections: " +
JSON.stringify(this.remoteConnections.keys()) + JSON.stringify(this.remoteConnections.keys()) +
'. Existing local connection: ' + '. Existing local connection: ' +
this.connection.connectionId this.connection.connectionId
) )
.then((connection) => { .then((connection) => {
@ -977,7 +983,13 @@ export class Session extends EventDispatcher {
/** /**
* @hidden * @hidden
*/ */
onStreamPropertyChanged(event: { connectionId: string; streamId: string; property: ChangedPropertyType; newValue: any; reason: StreamPropertyChangedEventReason }): void { onStreamPropertyChanged(event: {
connectionId: string;
streamId: string;
property: ChangedPropertyType;
newValue: any;
reason: StreamPropertyChangedEventReason;
}): void {
const callback = (connection: Connection) => { const callback = (connection: Connection) => {
if (!!connection.stream && connection.stream.streamId === event.streamId) { if (!!connection.stream && connection.stream.streamId === event.streamId) {
const stream = connection.stream; const stream = connection.stream;
@ -993,7 +1005,7 @@ export class Session extends EventDispatcher {
event.newValue = event.newValue === 'true'; event.newValue = event.newValue === 'true';
stream.videoActive = event.newValue; stream.videoActive = event.newValue;
const videoTrack = stream?.getMediaStream()?.getVideoTracks()?.[0]; const videoTrack = stream?.getMediaStream()?.getVideoTracks()?.[0];
if(videoTrack && !videoTrack.enabled && stream.videoActive){ if (videoTrack && !videoTrack.enabled && stream.videoActive) {
videoTrack.enabled = true; videoTrack.enabled = true;
} }
break; break;
@ -1034,10 +1046,10 @@ export class Session extends EventDispatcher {
} else { } else {
logger.error( logger.error(
"No stream with streamId '" + "No stream with streamId '" +
event.streamId + event.streamId +
"' found for connection '" + "' found for connection '" +
event.connectionId + event.connectionId +
"' on 'streamPropertyChanged' event" "' on 'streamPropertyChanged' event"
); );
} }
}; };
@ -1123,11 +1135,11 @@ export class Session extends EventDispatcher {
this.getConnection( this.getConnection(
event.senderConnectionId, event.senderConnectionId,
'Connection not found for connectionId ' + 'Connection not found for connectionId ' +
event.senderConnectionId + event.senderConnectionId +
' owning endpoint ' + ' owning endpoint ' +
event.endpointName + event.endpointName +
'. Ice candidate will be ignored: ' + '. Ice candidate will be ignored: ' +
iceCandidate iceCandidate
) )
.then((connection) => { .then((connection) => {
const stream: Stream = connection.stream!; const stream: Stream = connection.stream!;
@ -1232,7 +1244,8 @@ export class Session extends EventDispatcher {
const stream: Stream = connection.stream!; const stream: Stream = connection.stream!;
if (!stream || !stream.filter) { if (!stream || !stream.filter) {
return logger.error( return logger.error(
`Filter event of type "${event.eventType}" dispatched for stream ${stream.streamId} but there is no ${!stream ? 'stream' : 'filter' `Filter event of type "${event.eventType}" dispatched for stream ${stream.streamId} but there is no ${
!stream ? 'stream' : 'filter'
} defined` } defined`
); );
} }
@ -1356,7 +1369,7 @@ export class Session extends EventDispatcher {
lang: string; lang: string;
}): Promise<void> { }): Promise<void> {
const connection = await this.getConnection(event.connectionId, 'No connection found for connectionId ' + event.connectionId); const connection = await this.getConnection(event.connectionId, 'No connection found for connectionId ' + event.connectionId);
const ev = new SpeechToTextEvent(this, connection, event.text, <any>(event.reason).toLowerCase(), event.raw, event.lang); const ev = new SpeechToTextEvent(this, connection, event.text, <any>event.reason.toLowerCase(), event.raw, event.lang);
this.ee.emitEvent('speechToTextMessage', [ev]); this.ee.emitEvent('speechToTextMessage', [ev]);
} }
@ -1503,12 +1516,12 @@ export class Session extends EventDispatcher {
} else { } else {
logger.error( logger.error(
'Browser ' + 'Browser ' +
platform.getName() + platform.getName() +
' (version ' + ' (version ' +
platform.getVersion() + platform.getVersion() +
') for ' + ') for ' +
platform.getFamily() + platform.getFamily() +
' is not supported in OpenVidu for Network Quality' ' is not supported in OpenVidu for Network Quality'
); );
} }
} }
@ -1783,15 +1796,15 @@ export class Session extends EventDispatcher {
if (semverMajor(opts.version) !== semverMajor(this.openvidu.libraryVersion) || !(minorDifference == 0 || minorDifference == 1)) { if (semverMajor(opts.version) !== semverMajor(this.openvidu.libraryVersion) || !(minorDifference == 0 || minorDifference == 1)) {
logger.error( logger.error(
`openvidu-browser (${this.openvidu.libraryVersion}) and openvidu-server (${opts.version}) versions are incompatible. ` + `openvidu-browser (${this.openvidu.libraryVersion}) and openvidu-server (${opts.version}) versions are incompatible. ` +
'Errors are likely to occur. openvidu-browser SDK is only compatible with the same version or the immediately following minor version of an OpenVidu deployment' 'Errors are likely to occur. openvidu-browser SDK is only compatible with the same version or the immediately following minor version of an OpenVidu deployment'
); );
} else if (minorDifference == 1) { } else if (minorDifference == 1) {
logger.warn( logger.warn(
`openvidu-browser version ${this.openvidu.libraryVersion} does not match openvidu-server version ${opts.version}. ` + `openvidu-browser version ${this.openvidu.libraryVersion} does not match openvidu-server version ${opts.version}. ` +
`These versions are still compatible with each other, but openvidu-browser version must be updated as soon as possible to ${semverMajor( `These versions are still compatible with each other, but openvidu-browser version must be updated as soon as possible to ${semverMajor(
opts.version opts.version
)}.${semverMinor(opts.version)}.x. ` + )}.${semverMinor(opts.version)}.x. ` +
`This client using openvidu-browser ${this.openvidu.libraryVersion} will become incompatible with the next release of openvidu-server` `This client using openvidu-browser ${this.openvidu.libraryVersion} will become incompatible with the next release of openvidu-server`
); );
} }

View File

@ -40,7 +40,7 @@ import { TypeOfVideo } from '../OpenViduInternal/Enums/TypeOfVideo';
import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger';
import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; import { PlatformUtils } from '../OpenViduInternal/Utils/Platform';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuid } from 'uuid';
/** /**
* @hidden * @hidden
@ -414,7 +414,7 @@ export class Stream {
const afterScriptLoaded = async () => { const afterScriptLoaded = async () => {
try { try {
const id = this.streamId + '_' + uuidv4(); const id = this.streamId + '_' + uuid();
const mediaStreamClone = this.mediaStream!.clone(); const mediaStreamClone = this.mediaStream!.clone();
const videoClone = this.streamManager.videos[0].video.cloneNode(false) as HTMLVideoElement; const videoClone = this.streamManager.videos[0].video.cloneNode(false) as HTMLVideoElement;
// @ts-ignore // @ts-ignore
@ -707,11 +707,11 @@ export class Stream {
this.stopWebRtcStats(); this.stopWebRtcStats();
logger.info( logger.info(
(!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') + (!!this.outboundStreamOpts ? 'Outbound ' : 'Inbound ') +
'RTCPeerConnection with id [' + 'RTCPeerConnection with id [' +
webrtcId + webrtcId +
"] from 'Stream' with id [" + "] from 'Stream' with id [" +
this.streamId + this.streamId +
'] is now closed' '] is now closed'
); );
} }
@ -790,12 +790,14 @@ export class Stream {
* @hidden * @hidden
*/ */
isSendScreen(): boolean { isSendScreen(): boolean {
let screen = false let screen = false;
if (typeof MediaStreamTrack !== 'undefined' && if (
this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack) { typeof MediaStreamTrack !== 'undefined' &&
this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack
) {
let trackSettings: any = this.outboundStreamOpts.publisherProperties.videoSource.getSettings(); let trackSettings: any = this.outboundStreamOpts.publisherProperties.videoSource.getSettings();
if (trackSettings.displaySurface) { if (trackSettings.displaySurface) {
screen = ["monitor", "window", "browser"].includes(trackSettings.displaySurface); screen = ['monitor', 'window', 'browser'].includes(trackSettings.displaySurface);
} }
} }
if (!screen && platform.isElectron()) { if (!screen && platform.isElectron()) {
@ -1074,7 +1076,8 @@ export class Stream {
} }
if (!!this.session.openvidu.advancedConfiguration.forceMediaReconnectionAfterNetworkDrop) { if (!!this.session.openvidu.advancedConfiguration.forceMediaReconnectionAfterNetworkDrop) {
logger.warn( logger.warn(
`OpenVidu Browser advanced configuration option "forceMediaReconnectionAfterNetworkDrop" is enabled. Stream ${this.streamId `OpenVidu Browser advanced configuration option "forceMediaReconnectionAfterNetworkDrop" is enabled. Stream ${
this.streamId
} (${this.isLocal() ? 'Publisher' : 'Subscriber'}) will force a reconnection` } (${this.isLocal() ? 'Publisher' : 'Subscriber'}) will force a reconnection`
); );
return true; return true;
@ -1112,7 +1115,8 @@ export class Stream {
} else { } else {
// Ongoing reconnection // Ongoing reconnection
console.warn( console.warn(
`Trying to reconnect stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `Trying to reconnect stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
}) but an ongoing reconnection process is active. Waiting for response...` }) but an ongoing reconnection process is active. Waiting for response...`
); );
this.reconnectionEventEmitter.once('success', () => resolve()); this.reconnectionEventEmitter.once('success', () => resolve());
@ -1167,11 +1171,11 @@ export class Stream {
if (this.isSendVideo()) { if (this.isSendVideo()) {
typeOfVideo = typeOfVideo =
typeof MediaStreamTrack !== 'undefined' && typeof MediaStreamTrack !== 'undefined' &&
this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack this.outboundStreamOpts.publisherProperties.videoSource instanceof MediaStreamTrack
? TypeOfVideo.CUSTOM ? TypeOfVideo.CUSTOM
: this.isSendScreen() : this.isSendScreen()
? TypeOfVideo.SCREEN ? TypeOfVideo.SCREEN
: TypeOfVideo.CAMERA; : TypeOfVideo.CAMERA;
} }
params = { params = {
doLoopback: this.displayMyRemote() || false, doLoopback: this.displayMyRemote() || false,
@ -1216,10 +1220,10 @@ export class Stream {
this.initWebRtcStats(); this.initWebRtcStats();
logger.info( logger.info(
"'Publisher' (" + "'Publisher' (" +
this.streamId + this.streamId +
') successfully ' + ') successfully ' +
(reconnect ? 'reconnected' : 'published') + (reconnect ? 'reconnected' : 'published') +
' to session' ' to session'
); );
finalResolve(); finalResolve();
@ -1298,11 +1302,11 @@ export class Stream {
finalRejectForSubscription(reconnect: boolean, error: any, reject: (reason?: any) => void) { finalRejectForSubscription(reconnect: boolean, error: any, reject: (reason?: any) => void) {
logger.error( logger.error(
"Error for 'Subscriber' (" + "Error for 'Subscriber' (" +
this.streamId + this.streamId +
') while trying to ' + ') while trying to ' +
(reconnect ? 'reconnect' : 'subscribe') + (reconnect ? 'reconnect' : 'subscribe') +
': ' + ': ' +
error.toString() error.toString()
); );
if (reconnect) { if (reconnect) {
this.reconnectionEventEmitter?.emitEvent('error', [error]); this.reconnectionEventEmitter?.emitEvent('error', [error]);
@ -1494,7 +1498,9 @@ export class Stream {
this.mediaStream.getAudioTracks()[0].enabled = enabled; this.mediaStream.getAudioTracks()[0].enabled = enabled;
} }
if (!!this.mediaStream.getVideoTracks()[0]) { if (!!this.mediaStream.getVideoTracks()[0]) {
const enabled = reconnect ? this.videoActive : !!this.videoActive && !!(this.streamManager as Subscriber).properties.subscribeToVideo; const enabled = reconnect
? this.videoActive
: !!this.videoActive && !!(this.streamManager as Subscriber).properties.subscribeToVideo;
this.mediaStream.getVideoTracks()[0].enabled = enabled; this.mediaStream.getVideoTracks()[0].enabled = enabled;
} }
} }
@ -1546,7 +1552,8 @@ export class Stream {
private onIceConnectionFailed() { private onIceConnectionFailed() {
// Immediately reconnect, as this is a terminal error // Immediately reconnect, as this is a terminal error
logger.log( logger.log(
`[ICE_CONNECTION_FAILED] Handling ICE_CONNECTION_FAILED event. Reconnecting stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `[ICE_CONNECTION_FAILED] Handling ICE_CONNECTION_FAILED event. Reconnecting stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
})` })`
); );
this.reconnectStreamAndLogResultingIceConnectionState(ExceptionEventName.ICE_CONNECTION_FAILED); this.reconnectStreamAndLogResultingIceConnectionState(ExceptionEventName.ICE_CONNECTION_FAILED);
@ -1555,7 +1562,8 @@ export class Stream {
private onIceConnectionDisconnected() { private onIceConnectionDisconnected() {
// Wait to see if the ICE connection is able to reconnect // Wait to see if the ICE connection is able to reconnect
logger.log( logger.log(
`[ICE_CONNECTION_DISCONNECTED] Handling ICE_CONNECTION_DISCONNECTED event. Waiting for ICE to be restored and reconnect stream ${this.streamId `[ICE_CONNECTION_DISCONNECTED] Handling ICE_CONNECTION_DISCONNECTED event. Waiting for ICE to be restored and reconnect stream ${
this.streamId
} (${this.isLocal() ? 'Publisher' : 'Subscriber'}) if not possible` } (${this.isLocal() ? 'Publisher' : 'Subscriber'}) if not possible`
); );
const timeout = this.session.openvidu.advancedConfiguration.iceConnectionDisconnectedExceptionTimeout || 4000; const timeout = this.session.openvidu.advancedConfiguration.iceConnectionDisconnectedExceptionTimeout || 4000;
@ -1564,14 +1572,16 @@ export class Stream {
case 'failed': case 'failed':
// Do nothing, as an ICE_CONNECTION_FAILED event will have already raised // Do nothing, as an ICE_CONNECTION_FAILED event will have already raised
logger.warn( logger.warn(
`[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
}) is now failed after ICE_CONNECTION_DISCONNECTED` }) is now failed after ICE_CONNECTION_DISCONNECTED`
); );
break; break;
case 'connected': case 'connected':
case 'completed': case 'completed':
logger.log( logger.log(
`[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
}) automatically restored after ICE_CONNECTION_DISCONNECTED. Current ICE connection state: ${state}` }) automatically restored after ICE_CONNECTION_DISCONNECTED. Current ICE connection state: ${state}`
); );
break; break;
@ -1581,7 +1591,8 @@ export class Stream {
case 'disconnected': case 'disconnected':
// Rest of states // Rest of states
logger.warn( logger.warn(
`[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `[ICE_CONNECTION_DISCONNECTED] ICE connection of stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
}) couldn't be restored after ICE_CONNECTION_DISCONNECTED event. Current ICE connection state after ${timeout} ms: ${state}` }) couldn't be restored after ICE_CONNECTION_DISCONNECTED event. Current ICE connection state after ${timeout} ms: ${state}`
); );
this.reconnectStreamAndLogResultingIceConnectionState(ExceptionEventName.ICE_CONNECTION_DISCONNECTED); this.reconnectStreamAndLogResultingIceConnectionState(ExceptionEventName.ICE_CONNECTION_DISCONNECTED);
@ -1597,20 +1608,23 @@ export class Stream {
case 'connected': case 'connected':
case 'completed': case 'completed':
logger.log( logger.log(
`[${event}] Stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `[${event}] Stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
}) successfully reconnected after ${event}. Current ICE connection state: ${finalIceStateAfterReconnection}` }) successfully reconnected after ${event}. Current ICE connection state: ${finalIceStateAfterReconnection}`
); );
break; break;
default: default:
logger.error( logger.error(
`[${event}] Stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `[${event}] Stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
}) failed to reconnect after ${event}. Current ICE connection state: ${finalIceStateAfterReconnection}` }) failed to reconnect after ${event}. Current ICE connection state: ${finalIceStateAfterReconnection}`
); );
break; break;
} }
} catch (error) { } catch (error) {
logger.error( logger.error(
`[${event}] Error reconnecting stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `[${event}] Error reconnecting stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
}) after ${event}: ${error}` }) after ${event}: ${error}`
); );
} }
@ -1650,7 +1664,8 @@ export class Stream {
if (isWsConnected) { if (isWsConnected) {
// There is connection to openvidu-server. The RTCPeerConnection is the only one broken // There is connection to openvidu-server. The RTCPeerConnection is the only one broken
logger.log( logger.log(
`[${event}] Trying to reconnect stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' `[${event}] Trying to reconnect stream ${this.streamId} (${
this.isLocal() ? 'Publisher' : 'Subscriber'
}) and the websocket is opened` }) and the websocket is opened`
); );
if (this.isLocal()) { if (this.isLocal()) {
@ -1661,8 +1676,9 @@ export class Stream {
} else { } else {
// There is no connection to openvidu-server. Nothing can be done. The automatic reconnection // There is no connection to openvidu-server. Nothing can be done. The automatic reconnection
// feature should handle a possible reconnection of RTCPeerConnection in case network comes back // feature should handle a possible reconnection of RTCPeerConnection in case network comes back
const errorMsg = `[${event}] Trying to reconnect stream ${this.streamId} (${this.isLocal() ? 'Publisher' : 'Subscriber' const errorMsg = `[${event}] Trying to reconnect stream ${this.streamId} (${
}) but the websocket wasn't opened`; this.isLocal() ? 'Publisher' : 'Subscriber'
}) but the websocket wasn't opened`;
logger.error(errorMsg); logger.error(errorMsg);
throw Error(errorMsg); throw Error(errorMsg);
} }

View File

@ -388,14 +388,14 @@ export abstract class StreamManager extends EventDispatcher {
typeof publisherSpeakingEventsOptions.interval === 'number' typeof publisherSpeakingEventsOptions.interval === 'number'
? publisherSpeakingEventsOptions.interval ? publisherSpeakingEventsOptions.interval
: typeof currentHarkOptions.interval === 'number' : typeof currentHarkOptions.interval === 'number'
? currentHarkOptions.interval ? currentHarkOptions.interval
: 100; : 100;
const newThreshold = const newThreshold =
typeof publisherSpeakingEventsOptions.threshold === 'number' typeof publisherSpeakingEventsOptions.threshold === 'number'
? publisherSpeakingEventsOptions.threshold ? publisherSpeakingEventsOptions.threshold
: typeof currentHarkOptions.threshold === 'number' : typeof currentHarkOptions.threshold === 'number'
? currentHarkOptions.threshold ? currentHarkOptions.threshold
: -50; : -50;
this.stream.harkOptions = { this.stream.harkOptions = {
interval: newInterval, interval: newInterval,
threshold: newThreshold threshold: newThreshold

View File

@ -7,13 +7,9 @@
"allowJs": true, "allowJs": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"emitBOM": false, "emitBOM": false,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"lib": [ "lib": ["dom", "es2015", "scripthost"],
"dom",
"es2015.promise",
"es5",
"scripthost"
],
"module": "commonjs", "module": "commonjs",
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
//"noImplicitAny": true, //"noImplicitAny": true,
@ -28,8 +24,6 @@
"skipLibCheck": true, "skipLibCheck": true,
"sourceMap": true, "sourceMap": true,
"strictNullChecks": true, "strictNullChecks": true,
"suppressExcessPropertyErrors": true, "target": "es2015"
"suppressImplicitAnyIndexErrors": true,
"target": "es5"
} }
} }

View File

@ -56,6 +56,6 @@ export class ConnectionEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() { } callDefaultBehavior() {}
} }

View File

@ -63,6 +63,6 @@ export class ConnectionPropertyChangedEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() {} callDefaultBehavior() {}
} }

View File

@ -71,7 +71,6 @@ export abstract class Event {
* by calling {@link Subscriber.createVideoElement}). For every video removed, the Subscriber object will also dispatch a `videoElementDestroyed` event. * by calling {@link Subscriber.createVideoElement}). For every video removed, the Subscriber object will also dispatch a `videoElementDestroyed` event.
*/ */
preventDefault() { preventDefault() {
// tslint:disable-next-line:no-empty
this.callDefaultBehavior = () => {}; this.callDefaultBehavior = () => {};
this.hasBeenPrevented = true; this.hasBeenPrevented = true;
} }

View File

@ -63,7 +63,7 @@ export interface SessionEventMap extends EventMap {
* and * and
* <a href="https://docs.openvidu.io/en/stable/openvidu-enterprise/" style="display: inline-block; background-color: rgb(156, 39, 176); color: white; font-weight: bold; padding: 0px 5px; margin: 0 2px 0 2px; border-radius: 3px; font-size: 13px; line-height:21px; text-decoration: none; font-family: Montserrat, sans-serif">ENTERPRISE</a> * <a href="https://docs.openvidu.io/en/stable/openvidu-enterprise/" style="display: inline-block; background-color: rgb(156, 39, 176); color: white; font-weight: bold; padding: 0px 5px; margin: 0 2px 0 2px; border-radius: 3px; font-size: 13px; line-height:21px; text-decoration: none; font-family: Montserrat, sans-serif">ENTERPRISE</a>
* editions** * editions**
* *
* Event dispatched when a property of the local {@link Connection} object changes. * Event dispatched when a property of the local {@link Connection} object changes.
* *
* It is fired only for the local user. * It is fired only for the local user.
@ -162,7 +162,7 @@ export interface SessionEventMap extends EventMap {
* and * and
* <a href="https://docs.openvidu.io/en/stable/openvidu-enterprise/" style="display: inline-block; background-color: rgb(156, 39, 176); color: white; font-weight: bold; padding: 0px 5px; margin: 0 2px 0 2px; border-radius: 3px; font-size: 13px; line-height:21px; text-decoration: none; font-family: Montserrat, sans-serif">ENTERPRISE</a> * <a href="https://docs.openvidu.io/en/stable/openvidu-enterprise/" style="display: inline-block; background-color: rgb(156, 39, 176); color: white; font-weight: bold; padding: 0px 5px; margin: 0 2px 0 2px; border-radius: 3px; font-size: 13px; line-height:21px; text-decoration: none; font-family: Montserrat, sans-serif">ENTERPRISE</a>
* editions** * editions**
* *
* Event dispatched when the session has started being broadcasted. See [Broadcast to YouTube/Twitch](/en/stable/advanced-features/broadcast/) * Event dispatched when the session has started being broadcasted. See [Broadcast to YouTube/Twitch](/en/stable/advanced-features/broadcast/)
*/ */
broadcastStarted: never; broadcastStarted: never;
@ -173,7 +173,7 @@ export interface SessionEventMap extends EventMap {
* and * and
* <a href="https://docs.openvidu.io/en/stable/openvidu-enterprise/" style="display: inline-block; background-color: rgb(156, 39, 176); color: white; font-weight: bold; padding: 0px 5px; margin: 0 2px 0 2px; border-radius: 3px; font-size: 13px; line-height:21px; text-decoration: none; font-family: Montserrat, sans-serif">ENTERPRISE</a> * <a href="https://docs.openvidu.io/en/stable/openvidu-enterprise/" style="display: inline-block; background-color: rgb(156, 39, 176); color: white; font-weight: bold; padding: 0px 5px; margin: 0 2px 0 2px; border-radius: 3px; font-size: 13px; line-height:21px; text-decoration: none; font-family: Montserrat, sans-serif">ENTERPRISE</a>
* editions** * editions**
* *
* Event dispatched when the session has stopped being broadcasted. See [Broadcast to YouTube/Twitch](/en/stable/advanced-features/broadcast/) * Event dispatched when the session has stopped being broadcasted. See [Broadcast to YouTube/Twitch](/en/stable/advanced-features/broadcast/)
*/ */
broadcastStopped: never; broadcastStopped: never;
@ -195,7 +195,7 @@ export interface SessionEventMap extends EventMap {
* and * and
* <a href="https://docs.openvidu.io/en/stable/openvidu-enterprise/" style="display: inline-block; background-color: rgb(156, 39, 176); color: white; font-weight: bold; padding: 0px 5px; margin: 0 2px 0 2px; border-radius: 3px; font-size: 13px; line-height:21px; text-decoration: none; font-family: Montserrat, sans-serif">ENTERPRISE</a> * <a href="https://docs.openvidu.io/en/stable/openvidu-enterprise/" style="display: inline-block; background-color: rgb(156, 39, 176); color: white; font-weight: bold; padding: 0px 5px; margin: 0 2px 0 2px; border-radius: 3px; font-size: 13px; line-height:21px; text-decoration: none; font-family: Montserrat, sans-serif">ENTERPRISE</a>
* editions** * editions**
* *
* Event dispatched when a speech-to-text message has been received for certain Stream. See [Speech To Text](/en/stable/advanced-features/speech-to-text/). * Event dispatched when a speech-to-text message has been received for certain Stream. See [Speech To Text](/en/stable/advanced-features/speech-to-text/).
*/ */
speechToTextMessage: SpeechToTextEvent; speechToTextMessage: SpeechToTextEvent;

View File

@ -87,7 +87,7 @@ export enum ExceptionEventName {
* *
* {@link ExceptionEvent} objects with this {@link ExceptionEvent.name} will have as {@link ExceptionEvent.origin} property a {@link Session} object. * {@link ExceptionEvent} objects with this {@link ExceptionEvent.name} will have as {@link ExceptionEvent.origin} property a {@link Session} object.
*/ */
SPEECH_TO_TEXT_DISCONNECTED = 'SPEECH_TO_TEXT_DISCONNECTED', SPEECH_TO_TEXT_DISCONNECTED = 'SPEECH_TO_TEXT_DISCONNECTED'
} }
/** /**
@ -131,6 +131,6 @@ export class ExceptionEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() { } callDefaultBehavior() {}
} }

View File

@ -38,6 +38,6 @@ export class FilterEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() {} callDefaultBehavior() {}
} }

View File

@ -51,6 +51,6 @@ export class NetworkQualityLevelChangedEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() {} callDefaultBehavior() {}
} }

View File

@ -49,6 +49,6 @@ export class PublisherSpeakingEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() {} callDefaultBehavior() {}
} }

View File

@ -66,6 +66,6 @@ export class RecordingEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() { } callDefaultBehavior() {}
} }

View File

@ -59,6 +59,6 @@ export class SignalEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() {} callDefaultBehavior() {}
} }

View File

@ -24,7 +24,6 @@ import { SpeechToTextEventReason } from './Types/Types';
* Triggered by {@link SessionEventMap.speechToTextMessage} * Triggered by {@link SessionEventMap.speechToTextMessage}
*/ */
export class SpeechToTextEvent extends Event { export class SpeechToTextEvent extends Event {
/** /**
* The {@link Connection} owning the Stream that produced the speech-to-text event. * The {@link Connection} owning the Stream that produced the speech-to-text event.
* In other words, this is the participant that spoke and produced this transcription event. * In other words, this is the participant that spoke and produced this transcription event.
@ -37,7 +36,7 @@ export class SpeechToTextEvent extends Event {
text: string; text: string;
/** /**
* All speech-to-text events are generated * All speech-to-text events are generated
*/ */
reason: SpeechToTextEventReason; reason: SpeechToTextEventReason;
@ -67,6 +66,6 @@ export class SpeechToTextEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() { } callDefaultBehavior() {}
} }

View File

@ -44,6 +44,6 @@ export class StreamManagerEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() {} callDefaultBehavior() {}
} }

View File

@ -78,6 +78,6 @@ export class StreamPropertyChangedEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() { } callDefaultBehavior() {}
} }

View File

@ -1,42 +1,26 @@
export type ChangedPropertyType = export type ChangedPropertyType = 'videoActive' | 'audioActive' | 'videoTrack' | 'audioTrack' | 'videoDimensions' | 'filter';
'videoActive' |
'audioActive' |
'videoTrack' |
'audioTrack' |
'videoDimensions' |
'filter';
export type StreamPropertyChangedEventReason = export type StreamPropertyChangedEventReason =
'publishVideo' | | 'publishVideo'
'publishAudio' | | 'publishAudio'
'trackReplaced' | | 'trackReplaced'
'deviceRotated' | | 'deviceRotated'
'screenResized' | | 'screenResized'
'applyFilter' | | 'applyFilter'
'execFilterMethod' | | 'execFilterMethod'
'removeFilter'; | 'removeFilter';
export type ConnectionEventReason = export type ConnectionEventReason =
'disconnect' | | 'disconnect'
'forceDisconnectByUser' | | 'forceDisconnectByUser'
'forceDisconnectByServer' | | 'forceDisconnectByServer'
'sessionClosedByServer' | | 'sessionClosedByServer'
'networkDisconnect' | | 'networkDisconnect'
'nodeCrashed' | | 'nodeCrashed'
''; | '';
export type StreamEventReason = export type StreamEventReason = ConnectionEventReason | 'unpublish' | 'forceUnpublishByUser' | 'forceUnpublishByServer';
ConnectionEventReason |
'unpublish' |
'forceUnpublishByUser' |
'forceUnpublishByServer';
export type RecordingEventReason = export type RecordingEventReason = 'recordingStoppedByServer' | 'sessionClosedByServer' | 'automaticStop' | 'nodeCrashed';
'recordingStoppedByServer' |
'sessionClosedByServer' |
'automaticStop' |
'nodeCrashed';
export type SpeechToTextEventReason = export type SpeechToTextEventReason = 'recognizing' | 'recognized';
'recognizing' |
'recognized';

View File

@ -40,6 +40,6 @@ export class VideoElementEvent extends Event {
/** /**
* @hidden * @hidden
*/ */
// tslint:disable-next-line:no-empty
callDefaultBehavior() {} callDefaultBehavior() {}
} }

View File

@ -32,10 +32,10 @@ export class ConsoleLogger {
constructor(console: Console) { constructor(console: Console) {
this.logger = console; this.logger = console;
(this.log = console.log), ((this.log = console.log),
(this.info = console.info), (this.info = console.info),
(this.debug = console.debug), (this.debug = console.debug),
(this.warn = console.warn), (this.warn = console.warn),
(this.error = console.error); (this.error = console.error));
} }
} }

View File

@ -182,8 +182,6 @@ export class PlatformUtils {
); );
} }
/** /**
* @hidden * @hidden
*/ */

View File

@ -16,7 +16,7 @@
*/ */
import freeice = require('freeice'); import freeice = require('freeice');
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuid } from 'uuid';
import { TypeOfVideo } from '../Enums/TypeOfVideo'; import { TypeOfVideo } from '../Enums/TypeOfVideo';
import { ExceptionEventName } from '../Events/ExceptionEvent'; import { ExceptionEventName } from '../Events/ExceptionEvent';
import { OpenViduLogger } from '../Logger/OpenViduLogger'; import { OpenViduLogger } from '../Logger/OpenViduLogger';
@ -391,7 +391,8 @@ export class WebRtcPeer {
offerToReceiveAudio: offerAudio, offerToReceiveAudio: offerAudio,
offerToReceiveVideo: offerVideo offerToReceiveVideo: offerVideo
}; };
(this.pc as RTCPeerConnection).createAnswer(constraints) (this.pc as RTCPeerConnection)
.createAnswer(constraints)
.then((sdpAnswer) => resolve(sdpAnswer)) .then((sdpAnswer) => resolve(sdpAnswer))
.catch((error) => reject(error)); .catch((error) => reject(error));
} }
@ -574,7 +575,7 @@ export class WebRtcPeer {
* @hidden * @hidden
*/ */
generateUniqueId(): string { generateUniqueId(): string {
return uuidv4(); return uuid();
} }
} }

View File

@ -15,8 +15,6 @@
* *
*/ */
// tslint:disable:no-string-literal
import { Stream } from '../../OpenVidu/Stream'; import { Stream } from '../../OpenVidu/Stream';
import { OpenViduLogger } from '../Logger/OpenViduLogger'; import { OpenViduLogger } from '../Logger/OpenViduLogger';
import { PlatformUtils } from '../Utils/Platform'; import { PlatformUtils } from '../Utils/Platform';
@ -108,7 +106,7 @@ export class WebRtcStats {
private readonly STATS_ITEM_NAME = 'webrtc-stats-config'; private readonly STATS_ITEM_NAME = 'webrtc-stats-config';
private webRtcStatsEnabled = false; private webRtcStatsEnabled = false;
private webRtcStatsIntervalId: NodeJS.Timer; private webRtcStatsIntervalId: ReturnType<typeof setInterval>;
private statsInterval = 1; private statsInterval = 1;
private POST_URL: string; private POST_URL: string;
@ -126,8 +124,7 @@ export class WebRtcStats {
// accessing localStorage in a third-party iframe throws a DOMException. // accessing localStorage in a third-party iframe throws a DOMException.
try { try {
webrtcObj = localStorage.getItem(this.STATS_ITEM_NAME); webrtcObj = localStorage.getItem(this.STATS_ITEM_NAME);
} } catch (e) {}
catch(e){}
if (!!webrtcObj) { if (!!webrtcObj) {
this.webRtcStatsEnabled = true; this.webRtcStatsEnabled = true;

View File

@ -7,13 +7,9 @@
"allowJs": true, "allowJs": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"emitBOM": false, "emitBOM": false,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"lib": [ "lib": ["dom", "es2015", "scripthost"],
"dom",
"es2015.promise",
"es5",
"scripthost"
],
"module": "commonjs", "module": "commonjs",
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
//"noImplicitAny": true, //"noImplicitAny": true,
@ -29,8 +25,6 @@
"skipLibCheck": true, "skipLibCheck": true,
"sourceMap": true, "sourceMap": true,
"strictNullChecks": true, "strictNullChecks": true,
"suppressExcessPropertyErrors": true, "target": "es2015"
"suppressImplicitAnyIndexErrors": true,
"target": "es5"
} }
} }