Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/system-requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ Apache and Nginx must use:

Other combinations will not work due to the long polling used for chat and signaling messages, see [this issue](https://github.com/nextcloud/spreed/issues/2211#issuecomment-610198026) for details.

### WebAssembly and TensorFlow Lite files

Since Talk 13 the web server needs to handle WebAssembly (.wasm) and TensorFlow Lite (.tflite) files in a similar way to JavaScript and CSS files, as they will be requested by Talk clients to provide certain features (for example, the background blur when Talk is running in a browser). If Apache is used the default configuration provided by the Nextcloud server should be enough; if NGINX is used please refer to the [_NGINX configuration_ section in Nextcloud Administration manual](https://docs.nextcloud.com/server/stable/admin_manual/installation/nginx.html).

Besides that the web server should associate _.wasm_ files with the right MIME type. This is not strictly needed, though, but if they are not the browser console may show a warning similar to:
```
wasm streaming compile failed: TypeError: WebAssembly: Response has unsupported MIME type '' expected 'application/wasm'
falling back to ArrayBuffer instantiation
```

In Apache, if _mod_mime_ and _.htaccess_ files are enabled, the default _.htaccess_ file in Nextcloud server associates the _application/wasm_ MIME type with _.wasm_ files. Alternatively the association can be done by adding `AddType application/wasm .wasm` in _/etc/apache2/mods-enabled/mime.conf_, or `application/wasm wasm` to _/etc/mime.types_. Similarly, the default configuration for NGINX does the association too, but alternatively it can be done by adding `application/wasm wasm;` to _/etc/nginx/mime.types_.

## TURN server

A TURN server running on **port 443** (or 80) is required in almost all scenarios, see [Configuring coTURN](TURN.md) for more details.
Expand Down
178 changes: 178 additions & 0 deletions src/components/AdminSettings/WebServerSetupChecks.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<!--
- @copyright Copyright (c) 2021 Daniel Calviño Sánchez <[email protected]>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->

<template>
<div id="web_server_setup_checks" class="section">
<h2>
{{ t('spreed', 'Web server setup checks') }}
</h2>

<ul class="web-server-setup-checks">
<li class="background-blur">
{{ t('spreed', 'Files required for background blur can be loaded') }}
<button
v-if="backgroundBlurAvailable === false"
v-tooltip="backgroundBlurAvailableToolTip"
:aria-label="backgroundBlurAvailableAriaLabel"
class="icon"
:class="backgroundBlurAvailableClasses"
@click="checkBackgroundBlur" />
<button
v-else-if="backgroundBlurAvailable === true"
v-tooltip="backgroundBlurAvailableToolTip"
:aria-label="backgroundBlurAvailableAriaLabel"
class="icon"
:class="backgroundBlurAvailableClasses"
@click="checkBackgroundBlur" />
<span
v-else
v-tooltip="backgroundBlurAvailableToolTip"
:aria-label="backgroundBlurAvailableAriaLabel"
class="icon"
:class="backgroundBlurAvailableClasses" />
</li>
</ul>
</div>
</template>

<script>
import { generateFilePath } from '@nextcloud/router'
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
import { VIRTUAL_BACKGROUND_TYPE } from '../../utils/media/effects/virtual-background/constants'
import JitsiStreamBackgroundEffect from '../../utils/media/effects/virtual-background/JitsiStreamBackgroundEffect'
import VirtualBackground from '../../utils/media/pipeline/VirtualBackground'

export default {
name: 'WebServerSetupChecks',

directives: {
tooltip: Tooltip,
},

data() {
return {
backgroundBlurLoaded: undefined,
}
},

computed: {
backgroundBlurAvailable() {
return this.backgroundBlurLoaded
},

backgroundBlurAvailableClasses() {
return {
'icon-checkmark': this.backgroundBlurAvailable === true,
'icon-error': this.backgroundBlurAvailable === false,
'icon-loading-small': this.backgroundBlurAvailable === undefined,
}
},

backgroundBlurAvailableAriaLabel() {
if (this.backgroundBlurAvailable === false) {
return t('spreed', 'Failed')
}

if (this.backgroundBlurAvailable === true) {
return t('spreed', 'OK')
}

return t('spreed', 'Checking …')
},

backgroundBlurAvailableToolTip() {
if (this.backgroundBlurAvailable === false && !VirtualBackground.isWasmSupported()) {
return t('spreed', 'Failed: WebAssembly is disabled or not supported in this browser. Please enable WebAssembly or use a browser with support for it to do the check.')
}

if (this.backgroundBlurAvailable === false) {
return t('spreed', 'Failed: ".wasm" and ".tflite" files were not properly returned by the web server. Please check "System requirements" section in Talk documentation.')
}

if (this.backgroundBlurAvailable === true) {
return t('spreed', 'OK: ".wasm" and ".tflite" files were properly returned by the web server')
}

return t('spreed', 'Checking …')
},
},

beforeMount() {
this.checkBackgroundBlur()
},

methods: {
checkBackgroundBlur() {
if (!VirtualBackground.isWasmSupported()) {
this.backgroundBlurLoaded = false

return
}

this.backgroundBlurLoaded = undefined

// Pass only the essential options to check if the files can be
// loaded.
const options = {
virtualBackground: {
type: VIRTUAL_BACKGROUND_TYPE.NONE,
},
simd: VirtualBackground.isWasmSimd(),
}

/* eslint-disable no-undef, camelcase */

// When the worker is loaded from Talk its URL starts with
// "apps/spreed/js". However, when it is loaded from the
// administration settings its URL starts with "apps/talk/js"
// instead, so it fails to load.
//
// "publicPath" option in "worker-loader" configuration does not
// work with Webpack 5. As a workaround the public path needs to be
// overriden at runtime before loading the worker and restored
// afterwards.
// https://github.com/webpack-contrib/worker-loader/issues/281
const __webpack_public_path__saved = __webpack_public_path__

__webpack_public_path__ = generateFilePath('spreed', 'js', '')

const jitsiStreamBackgroundEffect = new JitsiStreamBackgroundEffect(options)

__webpack_public_path__ = __webpack_public_path__saved

/* eslint-enable no-undef, camelcase */

jitsiStreamBackgroundEffect.load().then(() => {
this.backgroundBlurLoaded = true
}).catch(() => {
this.backgroundBlurLoaded = false
})
},
},
}
</script>

<style lang="scss" scoped>
button.icon {
background-color: transparent;
border: none;
width: 44px;
}
</style>
56 changes: 37 additions & 19 deletions src/utils/media/pipeline/VirtualBackground.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,49 @@ export default class VirtualBackground extends TrackSinkSource {
static _canvasFilterSupported

static isSupported() {
return this._isWasmSupported() && this._isCanvasFilterSupported()
return this.isWasmSupported() && this.isCanvasFilterSupported()
}

static _isWasmSupported() {
if (this._wasmSupported === undefined) {
try {
const wasmCheck = require('wasm-check')
this._wasmSupported = true

if (wasmCheck?.feature?.simd) {
this._wasmSimd = true
} else {
this._wasmSimd = false
}
} catch (error) {
this._wasmSupported = false

console.error('Looks like WebAssembly is disabled or not supported on this browser, virtual background will not be available')
static _checkWasmSupport() {
try {
const wasmCheck = require('wasm-check')
this._wasmSupported = true

if (wasmCheck?.feature?.simd) {
this._wasmSimd = true
} else {
this._wasmSimd = false
}
} catch (error) {
this._wasmSupported = false

console.error('Looks like WebAssembly is disabled or not supported on this browser, virtual background will not be available')
}
}

static isWasmSupported() {
if (this._wasmSupported === undefined) {
this._checkWasmSupport()
}

return this._wasmSupported
}

static _isCanvasFilterSupported() {
/**
* Returns whether SIMD instructions are available in WebAssembly or not.
*
* @return {boolean} undefined if WebAssembly is not supported, true if SIMD
* instructions are available in WebAssembly, or false otherwise.
*/
static isWasmSimd() {
if (this._wasmSupported === undefined) {
this._checkWasmSupport()
}

return this._wasmSimd
}

static isCanvasFilterSupported() {
if (this._canvasFilterSupported === undefined) {
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
Expand Down Expand Up @@ -129,11 +147,11 @@ export default class VirtualBackground extends TrackSinkSource {
},
}

if (!VirtualBackground._isWasmSupported()) {
if (!VirtualBackground.isWasmSupported()) {
return
}

const isSimd = VirtualBackground._wasmSimd
const isSimd = VirtualBackground.isWasmSimd()

const virtualBackground = {
type: VIRTUAL_BACKGROUND_TYPE.NONE,
Expand Down
3 changes: 3 additions & 0 deletions src/views/AdminSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<MatterbridgeIntegration />
<AllowedGroups />
<Commands />
<WebServerSetupChecks />
<StunServers />
<TurnServers />
<SignalingServers />
Expand All @@ -44,6 +45,7 @@ import SignalingServers from '../components/AdminSettings/SignalingServers'
import SIPBridge from '../components/AdminSettings/SIPBridge'
import StunServers from '../components/AdminSettings/StunServers'
import TurnServers from '../components/AdminSettings/TurnServers'
import WebServerSetupChecks from '../components/AdminSettings/WebServerSetupChecks'

export default {
name: 'AdminSettings',
Expand All @@ -58,6 +60,7 @@ export default {
SIPBridge,
StunServers,
TurnServers,
WebServerSetupChecks,
},
}
</script>