mirror of https://github.com/OpenVidu/openvidu.git
Compare commits
46 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
773555ff65 | |
|
|
2130d203a0 | |
|
|
9e32bf7eb6 | |
|
|
d15b626828 | |
|
|
603158b814 | |
|
|
d17f89cae3 | |
|
|
09d50f73ce | |
|
|
b8402bbb9e | |
|
|
9b93884c90 | |
|
|
27e6c9d25d | |
|
|
3e37a4b622 | |
|
|
feefb0082b | |
|
|
580b00c121 | |
|
|
8bcf08cf80 | |
|
|
b5dc6d8517 | |
|
|
66001d8f11 | |
|
|
8b3bfc3b69 | |
|
|
43267700fb | |
|
|
7907fc40e5 | |
|
|
05209f1d97 | |
|
|
d6c60792b5 | |
|
|
2db928e06d | |
|
|
a3e0443dd1 | |
|
|
9b850756dd | |
|
|
a290f11984 | |
|
|
87c0f0ddaa | |
|
|
7922acffa0 | |
|
|
8ac77ae0ac | |
|
|
7074303b60 | |
|
|
c33813184b | |
|
|
bf3c9ac302 | |
|
|
ece8481a4f | |
|
|
18691db3b6 | |
|
|
4ad87927bd | |
|
|
c32c49aba9 | |
|
|
f76c590144 | |
|
|
9e42cdbbf0 | |
|
|
2e993cadc8 | |
|
|
61413cb0ee | |
|
|
16bc1ad5bd | |
|
|
266e30cd1f | |
|
|
5c31691885 | |
|
|
5b6890b6fc | |
|
|
7608c7aa52 | |
|
|
aec97450d5 | |
|
|
2a16c3642e |
|
|
@ -34,6 +34,8 @@ jobs:
|
|||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Install safe-chain
|
||||
uses: OpenVidu/actions/install-safe-chain@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
- name: Commit URL
|
||||
run: echo https://github.com/OpenVidu/openvidu/commit/${{ inputs.commit_sha || github.sha }}
|
||||
- name: Send Dispatch Event
|
||||
|
|
@ -93,6 +95,8 @@ jobs:
|
|||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Install safe-chain
|
||||
uses: OpenVidu/actions/install-safe-chain@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
- name: Install wait-on package
|
||||
run: npm install -g wait-on
|
||||
- name: Run Chrome
|
||||
|
|
@ -103,15 +107,15 @@ jobs:
|
|||
docker run --network=host -d -p 4444:4444 ${{ env.CHROME_IMAGE }}
|
||||
fi
|
||||
- name: Run openvidu-local-deployment
|
||||
uses: OpenVidu/actions/start-openvidu-local-deployment@0f5592e91f0dca4c62e7a3cf412a6c17cf432b6d # v1.0.4
|
||||
uses: OpenVidu/actions/start-openvidu-local-deployment@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
- name: Start OpenVidu Call backend
|
||||
uses: OpenVidu/actions/start-openvidu-call@0f5592e91f0dca4c62e7a3cf412a6c17cf432b6d # v1.0.4
|
||||
uses: OpenVidu/actions/start-openvidu-call@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
- name: Build and Serve openvidu-components-angular Testapp
|
||||
uses: OpenVidu/actions/start-openvidu-components-testapp@0f5592e91f0dca4c62e7a3cf412a6c17cf432b6d # v1.0.4
|
||||
uses: OpenVidu/actions/start-openvidu-components-testapp@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
- name: Run Tests
|
||||
env:
|
||||
LAUNCH_MODE: CI
|
||||
run: npm run ${{ matrix.script }} --prefix openvidu-components-angular
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
uses: OpenVidu/actions/cleanup@0f5592e91f0dca4c62e7a3cf412a6c17cf432b6d # v1.0.4
|
||||
uses: OpenVidu/actions/cleanup@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Configure OpenVidu Local Deployment
|
||||
uses: OpenVidu/actions/start-openvidu-local-deployment@0f5592e91f0dca4c62e7a3cf412a6c17cf432b6d # v1.0.4
|
||||
uses: OpenVidu/actions/start-openvidu-local-deployment@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
with:
|
||||
ref-openvidu-local-deployment: development
|
||||
pre_startup_commands: |
|
||||
|
|
@ -34,6 +34,8 @@ jobs:
|
|||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: 24
|
||||
- name: Install safe-chain
|
||||
uses: OpenVidu/actions/install-safe-chain@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ./openvidu/openvidu-test-integration
|
||||
|
|
@ -52,5 +54,5 @@ jobs:
|
|||
retention-days: 7
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
uses: OpenVidu/actions/cleanup@0f5592e91f0dca4c62e7a3cf412a6c17cf432b6d # v1.0.4
|
||||
uses: OpenVidu/actions/cleanup@58e9bb7b49e14849ee3cde9b532c4af48fe1d827 # v1.0.19
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "openvidu-components-testapp",
|
||||
"version": "3.6.1",
|
||||
"version": "3.7.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "openvidu-components-testapp",
|
||||
"version": "3.6.1",
|
||||
"version": "3.7.0",
|
||||
"dependencies": {
|
||||
"@angular/animations": "20.3.15",
|
||||
"@angular/cdk": "20.2.14",
|
||||
|
|
|
|||
|
|
@ -106,5 +106,5 @@
|
|||
"simulate:multiparty": "livekit-cli load-test --url ws://localhost:7880 --api-key devkey --api-secret secret --room daily-call --publishers 8 --audio-publishers 8 --identity-prefix Participant --identity publisher",
|
||||
"husky": "cd .. && husky install"
|
||||
},
|
||||
"version": "3.6.1"
|
||||
"version": "3.7.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@
|
|||
"livekit-client": "^2.16.0",
|
||||
"@livekit/track-processors": "^0.7.2"
|
||||
},
|
||||
"version": "3.6.1"
|
||||
"version": "3.7.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
services:
|
||||
|
||||
generate-scripts:
|
||||
image: alpine:3.23.3
|
||||
image: alpine:3.23.4
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
restart: "no"
|
||||
user: root
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
services:
|
||||
|
||||
caddy-proxy:
|
||||
image: docker.io/openvidu/openvidu-caddy-local:3.6.1
|
||||
image: docker.io/openvidu/openvidu-caddy-local:main
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -33,7 +33,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
redis:
|
||||
image: docker.io/redis:8.6.1-alpine
|
||||
image: docker.io/redis:8.6.2-alpine
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
|
@ -49,7 +49,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
minio:
|
||||
image: docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0
|
||||
image: docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 9000:9000
|
||||
|
|
@ -69,7 +69,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
mongo:
|
||||
image: docker.io/openvidu/mongodb:8.0.19-r2
|
||||
image: docker.io/openvidu/mongodb:8.0.21-r0
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 27017:27017
|
||||
|
|
@ -88,7 +88,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
dashboard:
|
||||
image: docker.io/openvidu/openvidu-dashboard:3.6.1
|
||||
image: docker.io/openvidu/openvidu-dashboard:main
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SERVER_PORT=5000
|
||||
|
|
@ -102,7 +102,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
openvidu:
|
||||
image: docker.io/openvidu/openvidu-server:3.6.1
|
||||
image: docker.io/openvidu/openvidu-server:main
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -123,7 +123,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
ingress:
|
||||
image: docker.io/openvidu/ingress:3.6.1
|
||||
image: docker.io/openvidu/ingress:main
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -141,7 +141,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
egress:
|
||||
image: docker.io/openvidu/egress:3.6.1
|
||||
image: docker.io/openvidu/egress:main
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -156,7 +156,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
operator:
|
||||
image: docker.io/openvidu/openvidu-operator:3.6.1
|
||||
image: docker.io/openvidu/openvidu-operator:main
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
|
@ -179,7 +179,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
openvidu-meet:
|
||||
image: docker.io/openvidu/openvidu-meet:3.6.1
|
||||
image: docker.io/openvidu/openvidu-meet:main
|
||||
restart: on-failure
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -219,7 +219,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
openvidu-meet-init:
|
||||
image: docker.io/openvidu/openvidu-operator:3.6.1
|
||||
image: docker.io/openvidu/openvidu-operator:main
|
||||
restart: on-failure
|
||||
environment:
|
||||
- MODE=local-ready-check
|
||||
|
|
|
|||
|
|
@ -680,9 +680,9 @@ Resources:
|
|||
'/usr/local/bin/install.sh':
|
||||
content: !Sub |
|
||||
#!/bin/bash -x
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
|
||||
apt-get update && apt-get install -y \
|
||||
curl \
|
||||
|
|
@ -692,7 +692,7 @@ Resources:
|
|||
wget https://github.com/mikefarah/yq/releases/download/${!YQ_VERSION}/yq_linux_$(dpkg --print-architecture).tar.gz -O - |\
|
||||
tar xz && mv yq_linux_$(dpkg --print-architecture) /usr/bin/yq
|
||||
|
||||
AWS_CLI_VERSION=2.34.0
|
||||
AWS_CLI_VERSION=2.34.41
|
||||
# Install aws-cli if not already installed
|
||||
if ! command -v aws &> /dev/null; then
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m)-${!AWS_CLI_VERSION}.zip" -o "awscliv2.zip"
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ var stringInterpolationParams = {
|
|||
|
||||
var installScriptTemplate = '''
|
||||
#!/bin/bash -x
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
|
||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||
|
|
@ -692,7 +692,7 @@ echo ${base64config_blobStorage} | base64 -d > /usr/local/bin/config_blobStorage
|
|||
chmod +x /usr/local/bin/config_blobStorage.sh
|
||||
|
||||
# Install azure cli
|
||||
AZURE_CLI_VERSION=2.83.0
|
||||
AZURE_CLI_VERSION=2.85.0
|
||||
apt-get install -y apt-transport-https ca-certificates gnupg lsb-release
|
||||
curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/microsoft.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -148,9 +148,9 @@ locals {
|
|||
#!/bin/bash -x
|
||||
set -e
|
||||
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||
|
||||
apt-get update && apt-get install -y \
|
||||
|
|
@ -636,7 +636,7 @@ CONFIG_S3_EOF
|
|||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||
apt-get update && apt-get install -y
|
||||
|
||||
GCLOUD_VERSION=558.0.0
|
||||
GCLOUD_VERSION=566.0.0
|
||||
# Install google cli
|
||||
if ! command -v gcloud >/dev/null 2>&1; then
|
||||
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Docker & Docker Compose will need to be installed on the machine
|
||||
set -eu
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.2.1}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.0.2}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.6.1}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.4.2}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.1.3}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-03-12T12-23-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.19}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.1-alpine}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-05-04T15-44-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.21}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.2-alpine}"
|
||||
export BUSYBOX_IMAGE="${BUSYBOX_IMAGE:-docker.io/busybox:1.37.0}"
|
||||
export CADDY_SERVER_IMAGE="${CADDY_SERVER_IMAGE:-docker.io/openvidu/openvidu-caddy:${OPENVIDU_VERSION}}"
|
||||
export CADDY_SERVER_PRO_IMAGE="${CADDY_SERVER_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-caddy:${OPENVIDU_VERSION}}"
|
||||
|
|
@ -23,11 +23,11 @@ export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSIN
|
|||
export OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-sherpa:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.9.1}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.11}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.11}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.4-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.4}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.11.3}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.12}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.12}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.6-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.6}"
|
||||
|
||||
# Function to compare two version strings
|
||||
compare_versions() {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Docker & Docker Compose will need to be installed on the machine
|
||||
set -eu
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.2.1}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.0.2}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.6.1}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.4.2}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.1.3}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-03-12T12-23-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.19}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.1-alpine}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-05-04T15-44-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.21}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.2-alpine}"
|
||||
export BUSYBOX_IMAGE="${BUSYBOX_IMAGE:-docker.io/busybox:1.37.0}"
|
||||
export CADDY_SERVER_IMAGE="${CADDY_SERVER_IMAGE:-docker.io/openvidu/openvidu-caddy:${OPENVIDU_VERSION}}"
|
||||
export CADDY_SERVER_PRO_IMAGE="${CADDY_SERVER_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-caddy:${OPENVIDU_VERSION}}"
|
||||
|
|
@ -23,11 +23,11 @@ export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSIN
|
|||
export OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-sherpa:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.9.1}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.11}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.11}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.4-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.4}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.11.3}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.12}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.12}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.6-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.6}"
|
||||
|
||||
# Function to compare two version strings
|
||||
compare_versions() {
|
||||
|
|
|
|||
|
|
@ -1441,9 +1441,9 @@ Resources:
|
|||
content: !Sub |
|
||||
#!/bin/bash
|
||||
set -e
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
|
||||
# Install dependencies
|
||||
apt-get update && apt-get install -y \
|
||||
|
|
@ -1454,7 +1454,7 @@ Resources:
|
|||
wget https://github.com/mikefarah/yq/releases/download/${!YQ_VERSION}/yq_linux_$(dpkg --print-architecture).tar.gz -O - |\
|
||||
tar xz && mv yq_linux_$(dpkg --print-architecture) /usr/bin/yq
|
||||
|
||||
AWS_CLI_VERSION=2.34.0
|
||||
AWS_CLI_VERSION=2.34.41
|
||||
# Install aws-cli if not already installed
|
||||
if ! command -v aws &> /dev/null; then
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m)-${!AWS_CLI_VERSION}.zip" -o "awscliv2.zip"
|
||||
|
|
@ -1977,7 +1977,7 @@ Resources:
|
|||
#!/bin/bash
|
||||
set -e
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
|
||||
# Install dependencies
|
||||
apt-get update && apt-get install -y \
|
||||
|
|
@ -1988,7 +1988,7 @@ Resources:
|
|||
wget https://github.com/mikefarah/yq/releases/download/${!YQ_VERSION}/yq_linux_$(dpkg --print-architecture).tar.gz -O - |\
|
||||
tar xz && mv yq_linux_$(dpkg --print-architecture) /usr/bin/yq
|
||||
|
||||
AWS_CLI_VERSION=2.34.0
|
||||
AWS_CLI_VERSION=2.34.41
|
||||
# Install aws-cli if not already installed
|
||||
if ! command -v aws &> /dev/null; then
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m)-${!AWS_CLI_VERSION}.zip" -o "awscliv2.zip"
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ var stringInterpolationParamsMaster = {
|
|||
|
||||
var installScriptTemplateMaster = '''
|
||||
#!/bin/bash -x
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
|
||||
# Assume azure cli is installed
|
||||
|
|
@ -790,7 +790,7 @@ echo ${base64config_blobStorage} | base64 -d > /usr/local/bin/config_blobStorage
|
|||
chmod +x /usr/local/bin/config_blobStorage.sh
|
||||
|
||||
# Install azure cli
|
||||
AZURE_CLI_VERSION=2.83.0
|
||||
AZURE_CLI_VERSION=2.85.0
|
||||
apt-get install -y apt-transport-https ca-certificates gnupg lsb-release
|
||||
curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/microsoft.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list
|
||||
|
|
@ -1039,7 +1039,7 @@ apt-get update && apt-get install -y
|
|||
apt-get install -y jq
|
||||
|
||||
# Install azure cli
|
||||
AZURE_CLI_VERSION=2.83.0
|
||||
AZURE_CLI_VERSION=2.85.0
|
||||
apt-get install -y apt-transport-https ca-certificates gnupg lsb-release
|
||||
curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/microsoft.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -617,9 +617,9 @@ locals {
|
|||
#!/bin/bash -x
|
||||
set -e
|
||||
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||
|
||||
apt-get update && apt-get install -y \
|
||||
|
|
@ -1131,7 +1131,7 @@ CONFIG_S3_EOF
|
|||
|
||||
apt-get update && apt-get install -y
|
||||
|
||||
GCLOUD_VERSION=558.0.0
|
||||
GCLOUD_VERSION=566.0.0
|
||||
# Install google cli
|
||||
if ! command -v gcloud >/dev/null 2>&1; then
|
||||
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
|
||||
|
|
@ -1327,7 +1327,7 @@ echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
|||
|
||||
apt-get update && apt-get install -y
|
||||
|
||||
GCLOUD_VERSION=558.0.0
|
||||
GCLOUD_VERSION=566.0.0
|
||||
# Install google cli
|
||||
if ! command -v gcloud >/dev/null 2>&1; then
|
||||
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Docker & Docker Compose will need to be installed on the machine
|
||||
set -eu
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.2.1}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.0.2}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.6.1}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.4.2}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.1.3}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-03-12T12-23-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.19}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.1-alpine}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-05-04T15-44-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.21}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.2-alpine}"
|
||||
export BUSYBOX_IMAGE="${BUSYBOX_IMAGE:-docker.io/busybox:1.37.0}"
|
||||
export CADDY_SERVER_IMAGE="${CADDY_SERVER_IMAGE:-docker.io/openvidu/openvidu-caddy:${OPENVIDU_VERSION}}"
|
||||
export CADDY_SERVER_PRO_IMAGE="${CADDY_SERVER_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-caddy:${OPENVIDU_VERSION}}"
|
||||
|
|
@ -23,11 +23,11 @@ export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSIN
|
|||
export OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-sherpa:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.9.1}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.11}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.11}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.4-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.4}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.11.3}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.12}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.12}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.6-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.6}"
|
||||
|
||||
# Function to compare two version strings
|
||||
compare_versions() {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Docker & Docker Compose will need to be installed on the machine
|
||||
set -eu
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.2.1}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.0.2}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.6.1}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.4.2}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.1.3}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-03-12T12-23-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.19}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.1-alpine}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-05-04T15-44-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.21}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.2-alpine}"
|
||||
export BUSYBOX_IMAGE="${BUSYBOX_IMAGE:-docker.io/busybox:1.37.0}"
|
||||
export CADDY_SERVER_IMAGE="${CADDY_SERVER_IMAGE:-docker.io/openvidu/openvidu-caddy:${OPENVIDU_VERSION}}"
|
||||
export CADDY_SERVER_PRO_IMAGE="${CADDY_SERVER_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-caddy:${OPENVIDU_VERSION}}"
|
||||
|
|
@ -23,11 +23,11 @@ export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSIN
|
|||
export OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-sherpa:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.9.1}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.11}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.11}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.4-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.4}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.11.3}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.12}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.12}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.6-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.6}"
|
||||
|
||||
# Function to compare two version strings
|
||||
compare_versions() {
|
||||
|
|
|
|||
|
|
@ -1544,9 +1544,9 @@ Resources:
|
|||
content: !Sub |
|
||||
#!/bin/bash -x
|
||||
set -e
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
|
||||
# Install dependencies
|
||||
apt-get update && apt-get install -y \
|
||||
|
|
@ -1557,7 +1557,7 @@ Resources:
|
|||
wget https://github.com/mikefarah/yq/releases/download/${!YQ_VERSION}/yq_linux_$(dpkg --print-architecture).tar.gz -O - |\
|
||||
tar xz && mv yq_linux_$(dpkg --print-architecture) /usr/bin/yq
|
||||
|
||||
AWS_CLI_VERSION=2.34.0
|
||||
AWS_CLI_VERSION=2.34.41
|
||||
# Install aws-cli if not already installed
|
||||
if ! command -v aws &> /dev/null; then
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m)-${!AWS_CLI_VERSION}.zip" -o "awscliv2.zip"
|
||||
|
|
@ -2316,7 +2316,7 @@ Resources:
|
|||
content: !Sub |
|
||||
#!/bin/bash
|
||||
set -e
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
|
||||
# Install dependencies
|
||||
apt-get update && apt-get install -y \
|
||||
|
|
@ -2327,7 +2327,7 @@ Resources:
|
|||
wget https://github.com/mikefarah/yq/releases/download/${!YQ_VERSION}/yq_linux_$(dpkg --print-architecture).tar.gz -O - |\
|
||||
tar xz && mv yq_linux_$(dpkg --print-architecture) /usr/bin/yq
|
||||
|
||||
AWS_CLI_VERSION=2.34.0
|
||||
AWS_CLI_VERSION=2.34.41
|
||||
# Install aws-cli if not already installed
|
||||
if ! command -v aws &> /dev/null; then
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m)-${!AWS_CLI_VERSION}.zip" -o "awscliv2.zip"
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ var stringInterpolationParamsMaster4 = {
|
|||
var installScriptTemplateMaster = '''
|
||||
#!/bin/bash -x
|
||||
set -e
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
|
||||
# Assume azure cli is installed
|
||||
|
|
@ -990,7 +990,7 @@ echo ${base64config_blobStorage} | base64 -d > /usr/local/bin/config_blobStorage
|
|||
chmod +x /usr/local/bin/config_blobStorage.sh
|
||||
|
||||
# Install azure cli
|
||||
AZURE_CLI_VERSION=2.83.0
|
||||
AZURE_CLI_VERSION=2.85.0
|
||||
apt-get install -y apt-transport-https ca-certificates gnupg lsb-release
|
||||
curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/microsoft.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list
|
||||
|
|
@ -1371,7 +1371,7 @@ apt-get update && apt-get install -y
|
|||
apt-get install -y jq
|
||||
|
||||
# Install azure cli
|
||||
AZURE_CLI_VERSION=2.83.0
|
||||
AZURE_CLI_VERSION=2.85.0
|
||||
apt-get install -y apt-transport-https ca-certificates gnupg lsb-release
|
||||
curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/microsoft.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -942,9 +942,9 @@ locals {
|
|||
#!/bin/bash -x
|
||||
set -e
|
||||
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
|
||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||
|
||||
|
|
@ -1501,7 +1501,7 @@ CONFIG_S3_EOF
|
|||
|
||||
apt-get update && apt-get install -y
|
||||
|
||||
GCLOUD_VERSION=558.0.0
|
||||
GCLOUD_VERSION=566.0.0
|
||||
# Install google cli
|
||||
if ! command -v gcloud >/dev/null 2>&1; then
|
||||
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
|
||||
|
|
@ -1689,7 +1689,7 @@ echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
|||
|
||||
apt-get update && apt-get install -y
|
||||
|
||||
GCLOUD_VERSION=558.0.0
|
||||
GCLOUD_VERSION=566.0.0
|
||||
# Install google cli
|
||||
if ! command -v gcloud >/dev/null 2>&1; then
|
||||
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Docker & Docker Compose will need to be installed on the machine
|
||||
set -eu
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.2.1}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.0.2}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.6.1}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.4.2}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.1.3}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-03-12T12-23-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.19}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.1-alpine}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-05-04T15-44-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.21}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.2-alpine}"
|
||||
export BUSYBOX_IMAGE="${BUSYBOX_IMAGE:-docker.io/busybox:1.37.0}"
|
||||
export CADDY_SERVER_IMAGE="${CADDY_SERVER_IMAGE:-docker.io/openvidu/openvidu-caddy:${OPENVIDU_VERSION}}"
|
||||
export CADDY_SERVER_PRO_IMAGE="${CADDY_SERVER_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-caddy:${OPENVIDU_VERSION}}"
|
||||
|
|
@ -23,11 +23,11 @@ export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSIN
|
|||
export OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-sherpa:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.9.1}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.11}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.11}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.4-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.4}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.11.3}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.12}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.12}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.6-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.6}"
|
||||
|
||||
# Function to compare two version strings
|
||||
compare_versions() {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Docker & Docker Compose will need to be installed on the machine
|
||||
set -eu
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.2.1}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.0.2}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.6.1}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.4.2}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.1.3}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-03-12T12-23-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.19}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.1-alpine}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-05-04T15-44-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.21}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.2-alpine}"
|
||||
export BUSYBOX_IMAGE="${BUSYBOX_IMAGE:-docker.io/busybox:1.37.0}"
|
||||
export CADDY_SERVER_IMAGE="${CADDY_SERVER_IMAGE:-docker.io/openvidu/openvidu-caddy:${OPENVIDU_VERSION}}"
|
||||
export CADDY_SERVER_PRO_IMAGE="${CADDY_SERVER_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-caddy:${OPENVIDU_VERSION}}"
|
||||
|
|
@ -23,11 +23,11 @@ export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSIN
|
|||
export OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-sherpa:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.9.1}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.11}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.11}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.4-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.4}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.11.3}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.12}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.12}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.6-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.6}"
|
||||
|
||||
# Function to compare two version strings
|
||||
compare_versions() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
services:
|
||||
|
||||
generate-scripts:
|
||||
image: alpine:3.23.3
|
||||
image: alpine:3.23.4
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
restart: "no"
|
||||
user: root
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
services:
|
||||
caddy-proxy:
|
||||
image: docker.io/openvidu/openvidu-caddy-local:3.6.1
|
||||
image: docker.io/openvidu/openvidu-caddy-local:main
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -33,7 +33,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
redis:
|
||||
image: docker.io/redis:8.6.1-alpine
|
||||
image: docker.io/redis:8.6.2-alpine
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
|
@ -49,7 +49,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
minio:
|
||||
image: docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0
|
||||
image: docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 9000:9000
|
||||
|
|
@ -69,7 +69,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
mongo:
|
||||
image: docker.io/openvidu/mongodb:8.0.19-r2
|
||||
image: docker.io/openvidu/mongodb:8.0.21-r0
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 27017:27017
|
||||
|
|
@ -88,7 +88,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
dashboard:
|
||||
image: docker.io/openvidu/openvidu-dashboard:3.6.1
|
||||
image: docker.io/openvidu/openvidu-dashboard:main
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
|
|
@ -102,7 +102,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
openvidu:
|
||||
image: docker.io/openvidu/openvidu-server-pro:3.6.1
|
||||
image: docker.io/openvidu/openvidu-server-pro:main
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -125,7 +125,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
ingress:
|
||||
image: docker.io/openvidu/ingress:3.6.1
|
||||
image: docker.io/openvidu/ingress:main
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -143,7 +143,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
egress:
|
||||
image: docker.io/openvidu/egress:3.6.1
|
||||
image: docker.io/openvidu/egress:main
|
||||
restart: unless-stopped
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -157,7 +157,7 @@ services:
|
|||
setup:
|
||||
condition: service_completed_successfully
|
||||
operator:
|
||||
image: docker.io/openvidu/openvidu-operator:3.6.1
|
||||
image: docker.io/openvidu/openvidu-operator:main
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
|
@ -181,7 +181,7 @@ services:
|
|||
|
||||
|
||||
openvidu-meet:
|
||||
image: docker.io/openvidu/openvidu-meet:3.6.1
|
||||
image: docker.io/openvidu/openvidu-meet:main
|
||||
restart: on-failure
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
|
|
@ -221,7 +221,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
openvidu-v2compatibility:
|
||||
image: docker.io/openvidu/openvidu-v2compatibility:3.6.1
|
||||
image: docker.io/openvidu/openvidu-v2compatibility:main
|
||||
restart: unless-stopped
|
||||
entrypoint: /bin/sh /scripts/entrypoint_openvidu_v2_compat.sh
|
||||
extra_hosts:
|
||||
|
|
@ -258,7 +258,7 @@ services:
|
|||
condition: service_completed_successfully
|
||||
|
||||
openvidu-meet-init:
|
||||
image: docker.io/openvidu/openvidu-operator:3.6.1
|
||||
image: docker.io/openvidu/openvidu-operator:main
|
||||
restart: on-failure
|
||||
environment:
|
||||
- MODE=local-ready-check
|
||||
|
|
|
|||
|
|
@ -782,9 +782,9 @@ Resources:
|
|||
'/usr/local/bin/install.sh':
|
||||
content: !Sub |
|
||||
#!/bin/bash -x
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
|
||||
apt-get update && apt-get install -y \
|
||||
curl \
|
||||
|
|
@ -794,7 +794,7 @@ Resources:
|
|||
wget https://github.com/mikefarah/yq/releases/download/${!YQ_VERSION}/yq_linux_$(dpkg --print-architecture).tar.gz -O - |\
|
||||
tar xz && mv yq_linux_$(dpkg --print-architecture) /usr/bin/yq
|
||||
|
||||
AWS_CLI_VERSION=2.34.0
|
||||
AWS_CLI_VERSION=2.34.41
|
||||
# Install aws-cli if not already installed
|
||||
if ! command -v aws &> /dev/null; then
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m)-${!AWS_CLI_VERSION}.zip" -o "awscliv2.zip"
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ var stringInterpolationParams = {
|
|||
|
||||
var installScriptTemplate = '''
|
||||
#!/bin/bash -x
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
|
||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||
|
|
@ -713,7 +713,7 @@ echo ${base64config_blobStorage} | base64 -d > /usr/local/bin/config_blobStorage
|
|||
chmod +x /usr/local/bin/config_blobStorage.sh
|
||||
|
||||
# Install azure cli
|
||||
AZURE_CLI_VERSION=2.83.0
|
||||
AZURE_CLI_VERSION=2.85.0
|
||||
apt-get install -y apt-transport-https ca-certificates gnupg lsb-release
|
||||
curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/microsoft.gpg
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -148,9 +148,9 @@ locals {
|
|||
#!/bin/bash -x
|
||||
set -e
|
||||
|
||||
OPENVIDU_VERSION=3.6.1
|
||||
OPENVIDU_VERSION=main
|
||||
DOMAIN=
|
||||
YQ_VERSION=v4.52.4
|
||||
YQ_VERSION=v4.53.2
|
||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||
|
||||
apt-get update && apt-get install -y \
|
||||
|
|
@ -648,7 +648,7 @@ CONFIG_S3_EOF
|
|||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||
apt-get update && apt-get install -y
|
||||
|
||||
GCLOUD_VERSION=558.0.0
|
||||
GCLOUD_VERSION=566.0.0
|
||||
# Install google cli
|
||||
if ! command -v gcloud >/dev/null 2>&1; then
|
||||
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#!/bin/sh
|
||||
# Docker & Docker Compose will need to be installed on the machine
|
||||
set -eu
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.2.1}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.0.2}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.6.1}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.4.2}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.1.3}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-03-12T12-23-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.19}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.1-alpine}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-05-04T15-44-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.21}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.2-alpine}"
|
||||
export BUSYBOX_IMAGE="${BUSYBOX_IMAGE:-docker.io/busybox:1.37.0}"
|
||||
export CADDY_SERVER_IMAGE="${CADDY_SERVER_IMAGE:-docker.io/openvidu/openvidu-caddy:${OPENVIDU_VERSION}}"
|
||||
export CADDY_SERVER_PRO_IMAGE="${CADDY_SERVER_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-caddy:${OPENVIDU_VERSION}}"
|
||||
|
|
@ -23,11 +23,11 @@ export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSIN
|
|||
export OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-sherpa:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.9.1}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.11}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.11}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.4-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.4}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.11.3}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.12}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.12}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.6-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.6}"
|
||||
|
||||
# Function to compare two version strings
|
||||
compare_versions() {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
|
||||
export INSTALL_PREFIX="${INSTALL_PREFIX:-/opt/openvidu}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.2.1}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.0.2}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.6.1}"
|
||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.4.2}"
|
||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v5.1.3}"
|
||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||
export UPDATE_BASE_URL="${UPDATE_BASE_URL:-http://get.openvidu.io/update}"
|
||||
export UPDATER_IMAGE="${UPDATER_IMAGE:-docker.io/openvidu/openvidu-updater:${OPENVIDU_VERSION}}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-03-04T16-04-53Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-03-12T12-23-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.19}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.1-alpine}"
|
||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:RELEASE.2026-05-04T00-27-21Z-r0}"
|
||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/openvidu/minio-client:RELEASE.2026-05-04T15-44-10Z}"
|
||||
export MONGO_SERVER_IMAGE="${MONGO_SERVER_IMAGE:-docker.io/mongo:8.0.21}"
|
||||
export REDIS_SERVER_IMAGE="${REDIS_SERVER_IMAGE:-docker.io/redis:8.6.2-alpine}"
|
||||
export BUSYBOX_IMAGE="${BUSYBOX_IMAGE:-docker.io/busybox:1.37.0}"
|
||||
export CADDY_SERVER_IMAGE="${CADDY_SERVER_IMAGE:-docker.io/openvidu/openvidu-caddy:${OPENVIDU_VERSION}}"
|
||||
export CADDY_SERVER_PRO_IMAGE="${CADDY_SERVER_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-caddy:${OPENVIDU_VERSION}}"
|
||||
|
|
@ -23,11 +26,11 @@ export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSIN
|
|||
export OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-sherpa:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${OPENVIDU_VERSION}}"
|
||||
export LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.9.1}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.11}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.11}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.4-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.4}"
|
||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.11.3}"
|
||||
export PROMTAIL_IMAGE="${PROMTAIL_IMAGE:-docker.io/grafana/promtail:3.5.12}"
|
||||
export LOKI_IMAGE="${LOKI_IMAGE:-docker.io/grafana/loki:3.5.12}"
|
||||
export MIMIR_IMAGE="${MIMIR_IMAGE:-docker.io/openvidu/grafana-mimir:3.0.6-r0}"
|
||||
export GRAFANA_IMAGE="${GRAFANA_IMAGE:-docker.io/grafana/grafana:12.3.6}"
|
||||
|
||||
get_next_version() {
|
||||
case "$1" in
|
||||
|
|
@ -39,10 +42,22 @@ get_next_version() {
|
|||
"3.4.1") echo "3.5.0" ;;
|
||||
"3.5.0") echo "3.6.0" ;;
|
||||
"3.6.0") echo "3.6.1" ;;
|
||||
"3.6.1") echo "3.7.0" ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Existing versions use update-new.sh to keep the original update.sh intact.
|
||||
# Future versions (3.7.x+) will use update.sh normally.
|
||||
get_update_script() {
|
||||
case "$1" in
|
||||
"3.1.0"|"3.2.0"|"3.3.0"|"3.4.0"|"3.4.1"|"3.5.0"|"3.6.0"|"3.6.1")
|
||||
echo "update-new.sh" ;;
|
||||
*)
|
||||
echo "update.sh" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to compare two version strings
|
||||
compare_versions() {
|
||||
# Remove 'v' prefix if present
|
||||
|
|
@ -91,6 +106,37 @@ validate_upgrade() {
|
|||
current="$1"
|
||||
target="$2"
|
||||
|
||||
if [ "$current" = "$target" ]; then
|
||||
echo "Your installed version is $current"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Only upgrades from 3.4.0 or 3.4.1 targeting a version > 3.5.0 must stop
|
||||
# at 3.5.0 first.
|
||||
checkpoint="3.5.0"
|
||||
if [ "$current" = "3.4.0" ] || [ "$current" = "3.4.1" ]; then
|
||||
if [ "$target" = "main" ] || ( printf '%s\n%s\n' "$checkpoint" "$target" | sort -V -C && [ "$target" != "$checkpoint" ] ); then
|
||||
echo "WARNING: Upgrading through OpenVidu ${checkpoint} requires special steps."
|
||||
echo "The upgrade process must stop at version ${checkpoint} before continuing."
|
||||
echo ""
|
||||
echo "Please follow these steps:"
|
||||
echo ""
|
||||
echo " 1. Upgrade ALL cluster nodes to version ${checkpoint}:"
|
||||
echo " sh <(curl -fsSL ${UPDATE_BASE_URL}/${checkpoint}/update.sh)"
|
||||
echo ""
|
||||
echo " 2. Start OpenVidu on every node:"
|
||||
echo " systemctl start openvidu"
|
||||
echo ""
|
||||
echo " 3. Wait for initialization."
|
||||
echo ""
|
||||
echo " 4. Stop OpenVidu on every node:"
|
||||
echo " systemctl stop openvidu"
|
||||
echo ""
|
||||
echo "After completing these steps, re-run this upgrade script to continue."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$target" = "main" ]; then
|
||||
echo "WARNING: You are trying to upgrade to 'main' version."
|
||||
echo "This version is for OpenVidu developers and may be unstable."
|
||||
|
|
@ -111,17 +157,79 @@ validate_upgrade() {
|
|||
|
||||
if [ "$target" = "$next_version" ]; then
|
||||
return 0
|
||||
else
|
||||
echo "ERROR: Version $current can only be upgraded to version $next_version"
|
||||
echo "Please upgrade first to version $next_version"
|
||||
echo "You can do it by running the following command:"
|
||||
echo ""
|
||||
echo ""
|
||||
echo " sh <(curl -fsSL http://get.openvidu.io/update/$next_version/update.sh)"
|
||||
echo ""
|
||||
echo ""
|
||||
fi
|
||||
|
||||
while [ "$next_version" != "$target" ]; do
|
||||
if [ -z "$next_version" ]; then
|
||||
echo "ERROR: No upgrade path defined for version $current"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$NO_TTY_REQUESTED" != "yes" ]; then
|
||||
echo "Upgrading to $next_version before the target version."
|
||||
while true; do
|
||||
printf "Proceed with upgrading to $next_version? [y/N]: "
|
||||
read -r response
|
||||
if [ "$response" = "y" ] || [ "$response" = "Y" ]; then
|
||||
break
|
||||
elif [ "$response" = "n" ] || [ "$response" = "N" ]; then
|
||||
echo "Update cancelled"
|
||||
exit 1
|
||||
else
|
||||
echo "Please answer 'y' or 'n'."
|
||||
fi
|
||||
done
|
||||
fi
|
||||
echo "Upgrading from $current to $next_version first..."
|
||||
TMP_UPDATE="$(mktemp /tmp/ov_update.XXXXXX)"
|
||||
update_script="$(get_update_script "$next_version")"
|
||||
if ! curl -fsSL "${UPDATE_BASE_URL}/$next_version/${update_script}" -o "$TMP_UPDATE"; then
|
||||
rm -f "$TMP_UPDATE"
|
||||
echo "ERROR: Failed to download update script for $next_version"
|
||||
exit 1
|
||||
fi
|
||||
if ! env \
|
||||
-u OPENVIDU_VERSION \
|
||||
-u DOCKER_VERSION \
|
||||
-u DOCKER_COMPOSE_VERSION \
|
||||
-u UPDATER_IMAGE \
|
||||
-u MINIO_SERVER_IMAGE \
|
||||
-u MINIO_CLIENT_IMAGE \
|
||||
-u MONGO_SERVER_IMAGE \
|
||||
-u REDIS_SERVER_IMAGE \
|
||||
-u BUSYBOX_IMAGE \
|
||||
-u CADDY_SERVER_IMAGE \
|
||||
-u CADDY_SERVER_PRO_IMAGE \
|
||||
-u OPENVIDU_OPERATOR_IMAGE \
|
||||
-u OPENVIDU_SERVER_PRO_IMAGE \
|
||||
-u OPENVIDU_SERVER_IMAGE \
|
||||
-u OPENVIDU_MEET_SERVER_IMAGE \
|
||||
-u OPENVIDU_DASHBOARD_PRO_IMAGE \
|
||||
-u OPENVIDU_DASHBOARD_IMAGE \
|
||||
-u OPENVIDU_V2COMPATIBILITY_IMAGE \
|
||||
-u OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE \
|
||||
-u OPENVIDU_AGENT_PRO_SPEECH_PROCESSING_IMAGE \
|
||||
-u LIVEKIT_INGRESS_SERVER_IMAGE \
|
||||
-u LIVEKIT_EGRESS_SERVER_IMAGE \
|
||||
-u PROMETHEUS_IMAGE \
|
||||
-u PROMTAIL_IMAGE \
|
||||
-u LOKI_IMAGE \
|
||||
-u MIMIR_IMAGE \
|
||||
-u GRAFANA_IMAGE \
|
||||
sh "$TMP_UPDATE" $NO_TTY_FLAG; then
|
||||
rm -f "$TMP_UPDATE"
|
||||
echo "ERROR: Intermediate upgrade from $current to $next_version failed"
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$TMP_UPDATE"
|
||||
current="$(grep version "${INSTALL_PREFIX}/deployment-info.yaml" | cut -d':' -f2 | sed 's/^ *"//;s/"$//')"
|
||||
next_version="$(get_next_version "$current")"
|
||||
if [ -z "$next_version" ]; then
|
||||
echo "ERROR: No upgrade path found from version $current to $target"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Check if executing as root
|
||||
|
|
@ -130,6 +238,91 @@ if [ "$(id -u)" -ne 0 ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Check --no-tty
|
||||
if [ -z "${NO_TTY_REQUESTED:+x}" ]; then
|
||||
NO_TTY_REQUESTED="no"
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" = "--no-tty" ]; then
|
||||
NO_TTY_REQUESTED="yes"
|
||||
break
|
||||
fi
|
||||
done
|
||||
export NO_TTY_REQUESTED
|
||||
fi
|
||||
|
||||
NO_TTY_FLAG=""
|
||||
if [ "$NO_TTY_REQUESTED" = "yes" ]; then
|
||||
NO_TTY_FLAG="--no-tty"
|
||||
fi
|
||||
|
||||
# Ensure docker-compose shim exists
|
||||
if ! command -v docker-compose > /dev/null 2>&1; then
|
||||
if docker compose version > /dev/null 2>&1; then
|
||||
cat > /usr/local/bin/docker-compose <<'EOF'
|
||||
#!/bin/sh
|
||||
exec docker compose "$@"
|
||||
EOF
|
||||
chmod 755 /usr/local/bin/docker-compose
|
||||
mkdir -p /usr/local/lib/docker/cli-plugins
|
||||
ln -sf /usr/local/bin/docker-compose /usr/local/lib/docker/cli-plugins/docker-compose
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check Docker installation and version
|
||||
if [ "${OPENVIDU_SKIP_DOCKER_VERSION_CHECK:-}" != "true" ]; then
|
||||
if ! command -v docker > /dev/null 2>&1; then
|
||||
echo "ERROR: Docker is not installed. Docker is required to continue."
|
||||
exit 1
|
||||
else
|
||||
CURRENT_DOCKER_VERSION=$(docker --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
||||
VERSION_COMPARISON=$(compare_versions "$CURRENT_DOCKER_VERSION" "$DOCKER_VERSION")
|
||||
|
||||
if [ "$VERSION_COMPARISON" = "lower" ]; then
|
||||
echo "WARNING: Docker version $CURRENT_DOCKER_VERSION is older than the recommended version $DOCKER_VERSION."
|
||||
printf "Continue anyway? [Y/n]: "
|
||||
read -r response
|
||||
if [ "$response" != "n" ] && [ "$response" != "N" ]; then
|
||||
export OPENVIDU_SKIP_DOCKER_VERSION_CHECK=true
|
||||
else
|
||||
echo "Update cancelled"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check Docker Compose installation and version
|
||||
if [ "${OPENVIDU_SKIP_DOCKER_COMPOSE_VERSION_CHECK:-}" != "true" ]; then
|
||||
DOCKER_COMPOSE_CMD=""
|
||||
if command -v docker-compose > /dev/null 2>&1; then
|
||||
DOCKER_COMPOSE_CMD="docker-compose"
|
||||
elif docker compose version > /dev/null 2>&1; then
|
||||
DOCKER_COMPOSE_CMD="docker compose"
|
||||
fi
|
||||
|
||||
if [ -n "$DOCKER_COMPOSE_CMD" ]; then
|
||||
CURRENT_DC_VERSION=$($DOCKER_COMPOSE_CMD --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
||||
# Add 'v' prefix for proper comparison
|
||||
CURRENT_DC_VERSION="v${CURRENT_DC_VERSION}"
|
||||
VERSION_COMPARISON=$(compare_versions "$CURRENT_DC_VERSION" "$DOCKER_COMPOSE_VERSION")
|
||||
|
||||
if [ "$VERSION_COMPARISON" = "lower" ]; then
|
||||
echo "WARNING: Docker Compose version $CURRENT_DC_VERSION is older than the recommended version $DOCKER_COMPOSE_VERSION."
|
||||
printf "Continue anyway? [Y/n]: "
|
||||
read -r response
|
||||
if [ "$response" != "n" ] && [ "$response" != "N" ]; then
|
||||
export OPENVIDU_SKIP_DOCKER_COMPOSE_VERSION_CHECK=true
|
||||
else
|
||||
echo "Update cancelled"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "ERROR: Docker Compose is not installed. Docker Compose is required to continue."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate the upgrade path
|
||||
CURRENT_VERSION="$(grep version "${INSTALL_PREFIX}/deployment-info.yaml" | cut -d':' -f2 | sed 's/^ *"//;s/"$//')"
|
||||
validate_upgrade "$CURRENT_VERSION" "$OPENVIDU_VERSION"
|
||||
|
|
@ -138,87 +331,6 @@ validate_upgrade "$CURRENT_VERSION" "$OPENVIDU_VERSION"
|
|||
echo "Stopping OpenVidu service..."
|
||||
systemctl stop openvidu
|
||||
|
||||
# Check Docker installation and version
|
||||
DOCKER_NEEDED=false
|
||||
if ! command -v docker > /dev/null 2>&1; then
|
||||
echo "Docker not found. Will install Docker version ${DOCKER_VERSION}."
|
||||
DOCKER_NEEDED=true
|
||||
else
|
||||
CURRENT_DOCKER_VERSION=$(docker --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
||||
VERSION_COMPARISON=$(compare_versions "$CURRENT_DOCKER_VERSION" "$DOCKER_VERSION")
|
||||
|
||||
if [ "$VERSION_COMPARISON" = "lower" ]; then
|
||||
echo "Docker version $CURRENT_DOCKER_VERSION is older than required version $DOCKER_VERSION."
|
||||
echo "Please update Docker to version $DOCKER_VERSION or later."
|
||||
exit 1
|
||||
else
|
||||
echo "Docker version $CURRENT_DOCKER_VERSION is compatible with required version $DOCKER_VERSION."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install Docker if needed
|
||||
if [ "$DOCKER_NEEDED" = true ]; then
|
||||
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
|
||||
sh /tmp/get-docker.sh --version "${DOCKER_VERSION}" || { echo "Can't install Docker automatically. Install it manually and run this script again"; exit 1; }
|
||||
fi
|
||||
|
||||
# Check Docker Compose installation and version
|
||||
DOCKER_COMPOSE_NEEDED=false
|
||||
if ! command -v docker-compose > /dev/null 2>&1; then
|
||||
echo "Docker Compose not found. Will install Docker Compose version ${DOCKER_COMPOSE_VERSION}."
|
||||
DOCKER_COMPOSE_NEEDED=true
|
||||
else
|
||||
CURRENT_DC_VERSION=$(docker-compose --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
|
||||
# Add 'v' prefix for proper comparison
|
||||
CURRENT_DC_VERSION="v${CURRENT_DC_VERSION}"
|
||||
VERSION_COMPARISON=$(compare_versions "$CURRENT_DC_VERSION" "$DOCKER_COMPOSE_VERSION")
|
||||
|
||||
if [ "$VERSION_COMPARISON" = "lower" ]; then
|
||||
echo "Docker Compose version $CURRENT_DC_VERSION is older than required version $DOCKER_COMPOSE_VERSION."
|
||||
echo "Will update Docker Compose to version $DOCKER_COMPOSE_VERSION."
|
||||
DOCKER_COMPOSE_NEEDED=true
|
||||
else
|
||||
echo "Docker Compose version $CURRENT_DC_VERSION is compatible with required version $DOCKER_COMPOSE_VERSION."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install or update Docker Compose if needed
|
||||
if [ "$DOCKER_COMPOSE_NEEDED" = true ]; then
|
||||
TIME_LIMIT_SECONDS=20
|
||||
START_TIME=$(awk 'BEGIN{srand(); print srand()}')
|
||||
while true
|
||||
do
|
||||
CURRENT_TIME=$(awk 'BEGIN{srand(); print srand()}')
|
||||
if [ $((CURRENT_TIME-START_TIME)) -gt $TIME_LIMIT_SECONDS ]; then
|
||||
echo "Error downloading docker-compose. Could not download it in $TIME_LIMIT_SECONDS seconds"
|
||||
rm -f /usr/local/bin/docker-compose
|
||||
exit 1
|
||||
fi
|
||||
STATUS_RECEIVED=$(curl --retry 5 --retry-max-time 40 --write-out "%{http_code}\n" -L "https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_VERSION/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose)
|
||||
CURL_EXIT_CODE=$?
|
||||
if [ $CURL_EXIT_CODE -ne 0 ]; then
|
||||
echo "Error downloading docker-compose. curl failed with exit code $CURL_EXIT_CODE. There are still $((TIME_LIMIT_SECONDS - (CURRENT_TIME - START_TIME))) seconds left to retry..."
|
||||
rm -f /usr/local/bin/docker-compose
|
||||
sleep 2
|
||||
continue
|
||||
fi
|
||||
if [ "${STATUS_RECEIVED}" -ne "200" ]; then
|
||||
echo "Error downloading docker-compose. Received HTTP status code $STATUS_RECEIVED. There are still $((TIME_LIMIT_SECONDS - (CURRENT_TIME - START_TIME))) seconds left to retry..."
|
||||
rm -f /usr/local/bin/docker-compose
|
||||
sleep 2
|
||||
continue
|
||||
fi
|
||||
echo "Success downloading docker-compose version $DOCKER_COMPOSE_VERSION"
|
||||
chmod 755 /usr/local/bin/docker-compose
|
||||
break
|
||||
done
|
||||
|
||||
# Create a symbolic link to docker-compose in the Docker CLI plugins directory
|
||||
# so docker compose can be used also
|
||||
mkdir -p /usr/local/lib/docker/cli-plugins
|
||||
ln -sf /usr/local/bin/docker-compose /usr/local/lib/docker/cli-plugins/docker-compose
|
||||
fi
|
||||
|
||||
# Check if docker is running with docker info
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
echo "Docker is not running. Starting Docker..."
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5f592e68f16a2144c13116bd045e9ce8ce946043
|
||||
Subproject commit 18f44d6e166cfdc8a7ee9acc55835f6d685f6bd0
|
||||
|
|
@ -49,6 +49,8 @@ public class FirefoxUser extends BrowserUser {
|
|||
|
||||
// ATTENTION: WITHOUT THIS FLAG H264 DOES NOT WORK IN SELENIUM-MANAGED FIREFOX
|
||||
options.addPreference("media.webrtc.hw.h264.enabled", true);
|
||||
// This flag makes livekit-server think that this is not a Firefox in Linux
|
||||
options.addPreference("general.useragent.override", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0");
|
||||
|
||||
if (headless) {
|
||||
options.addArguments("--headless");
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package io.openvidu.test.e2e;
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
|
@ -51,7 +52,7 @@ public class OpenViduTestE2e {
|
|||
|
||||
private final static WaitStrategy waitBrowser = Wait.forLogMessage("^.*Started Selenium Standalone.*$", 1);
|
||||
|
||||
protected static String RTSP_SERVER_IMAGE = "bluenviron/mediamtx:latest-ffmpeg";
|
||||
protected static String RTSP_SERVER_IMAGE = "bluenviron/mediamtx:1.17.1-ffmpeg";
|
||||
protected static int RTSP_SRT_PORT = 8554;
|
||||
|
||||
// Key is the common name of the video codec. It must match the output log of
|
||||
|
|
@ -69,7 +70,7 @@ public class OpenViduTestE2e {
|
|||
put("VP8", Triple.of("libvpx", "", "VP8"));
|
||||
put("VP9", Triple.of("libvpx-vp9", "", "VP9"));
|
||||
put("MPEG-4", Triple.of("mpeg4", "", "MPEG-4"));
|
||||
put("M-JPEG", Triple.of("mjpeg", "-force_duplicated_matrix:v 1 -huffman:v 0", "MJPEG"));
|
||||
put("M-JPEG", Triple.of("mjpeg", "-force_duplicated_matrix:v 1 -huffman:v 0", "M-JPEG"));
|
||||
// put("AV1", Triple.of("libaom-av1", "", "AV1")); // NOT SUPPORTED BY THE RTSP SERVER
|
||||
// (maybe gstreamer?)
|
||||
// put("H265", Triple.of("libx265", "", "H265")); // NOT SUPPORTED BY INGRESS
|
||||
|
|
@ -87,7 +88,7 @@ public class OpenViduTestE2e {
|
|||
put("AAC", Triple.of("aac", "-ac 2 -b:a 128k", "MPEG-4 Audio"));
|
||||
put("AC3", Triple.of("ac3", "-b:a 128k", null));
|
||||
put("OPUS", Triple.of("libopus", "-ac 2", "Opus"));
|
||||
put("MP3", Triple.of("libmp3lame", "", "MPEG-1 Audio"));
|
||||
put("MP3", Triple.of("libmp3lame", "", "MPEG-1/2 Audio"));
|
||||
put("VORBIS", Triple.of("libvorbis", "", null));
|
||||
put("G711", Triple.of("pcm_mulaw", "", "G711"));
|
||||
}
|
||||
|
|
@ -191,13 +192,18 @@ public class OpenViduTestE2e {
|
|||
*/
|
||||
public String startRtspServer(String videoCodec, String audioCodec) throws Exception {
|
||||
|
||||
int rtspPort;
|
||||
try (ServerSocket socket = new ServerSocket(0)) {
|
||||
rtspPort = socket.getLocalPort();
|
||||
}
|
||||
|
||||
GenericContainer<?> rtspServerContainer = new GenericContainer<>(DockerImageName.parse(RTSP_SERVER_IMAGE))
|
||||
.withCreateContainerCmdModifier(cmd -> cmd.withName("rtsp-" + Math.random() * 100000))
|
||||
.withEnv(Map.of("MTX_LOGLEVEL", "info", "MTX_RTSPTRANSPORTS", "tcp", "MTX_RTSPADDRESS", ":" + RTSP_SRT_PORT,
|
||||
"MTX_HLS", "no", "MTX_RTSP", "yes", "MTX_WEBRTC", "yes", "MTX_SRT", "no", "MTX_RTMP", "no",
|
||||
.withEnv(Map.of("MTX_LOGLEVEL", "info", "MTX_RTSPTRANSPORTS", "tcp", "MTX_RTSPADDRESS", ":" + rtspPort,
|
||||
"MTX_HLS", "no", "MTX_RTSP", "yes", "MTX_WEBRTC", "no", "MTX_SRT", "no", "MTX_RTMP", "no",
|
||||
"MTX_API", "no"))
|
||||
.withNetworkMode("host")
|
||||
.waitingFor(Wait.forLogMessage("^.*\\[RTSP\\] listener opened on :" + RTSP_SRT_PORT + ".*$", 1));
|
||||
.waitingFor(Wait.forLogMessage("^.*\\[RTSP\\] listener opened on :" + rtspPort + ".*$", 1));
|
||||
|
||||
rtspServerContainer.start();
|
||||
containers.add(rtspServerContainer);
|
||||
|
|
@ -208,7 +214,7 @@ public class OpenViduTestE2e {
|
|||
String rtspServerIp = "host.docker.internal";
|
||||
|
||||
String ffmpegCommand = "ffmpeg -i " + fileUrl + " " + codecs + " "
|
||||
+ " -async 50 -strict -2 -f rtsp -rtsp_transport tcp rtsp://" + rtspServerIp + ":" + RTSP_SRT_PORT + "/"
|
||||
+ " -async 50 -strict -2 -f rtsp -rtsp_transport tcp rtsp://" + rtspServerIp + ":" + rtspPort + "/"
|
||||
+ RTSP_PATH;
|
||||
|
||||
// Clean adjacent white spaces or the ffmpeg command will fail
|
||||
|
|
@ -235,7 +241,7 @@ public class OpenViduTestE2e {
|
|||
waitUntilLog(rtspServerContainer, regex, 15);
|
||||
}
|
||||
|
||||
return "rtsp://host.docker.internal:" + RTSP_SRT_PORT + "/" + RTSP_PATH;
|
||||
return "rtsp://host.docker.internal:" + rtspPort + "/" + RTSP_PATH;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.time.Duration;
|
|||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Callable;
|
||||
|
|
@ -46,6 +47,7 @@ import org.junit.jupiter.api.Test;
|
|||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.Keys;
|
||||
import org.openqa.selenium.TakesScreenshot;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
|
@ -73,6 +75,8 @@ import io.openvidu.test.e2e.annotations.OnlyPion;
|
|||
import livekit.LivekitIngress.IngressInfo;
|
||||
import livekit.LivekitIngress.IngressState;
|
||||
|
||||
import static org.openqa.selenium.OutputType.BASE64;
|
||||
|
||||
/**
|
||||
* E2E tests for openvidu-testapp.
|
||||
*
|
||||
|
|
@ -161,10 +165,26 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Signal")
|
||||
void signalTest() throws Exception {
|
||||
@DisplayName("Signal Reliable DataChannel")
|
||||
void signalReliableTest() throws Exception {
|
||||
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
|
||||
log.info("Signal");
|
||||
log.info("Signal Reliable DataChannel");
|
||||
signalReliableLossyAux(user, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Signal Lossy DataChannel")
|
||||
void signalLossyTest() throws Exception {
|
||||
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
|
||||
log.info("Signal Lossy DataChannel");
|
||||
signalReliableLossyAux(user, false);
|
||||
}
|
||||
|
||||
private void signalReliableLossyAux(OpenViduTestappUser user, boolean reliable) throws Exception {
|
||||
final int expectedKind = reliable ? 0 : 1; // DataPacket_Kind: RELIABLE=0, LOSSY=1
|
||||
final String expectedKindStr = reliable ? "RELIABLE" : "LOSSY";
|
||||
final String btnClass = reliable ? ".message-reliable-btn" : ".message-lossy-btn";
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
WebElement addUserBtn = user.getDriver().findElement(By.id("add-user-btn"));
|
||||
addUserBtn.click();
|
||||
|
|
@ -178,129 +198,306 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
user.getEventManager().waitUntilEventReaches("participantConnected", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches("participantActive", "RoomEvent", 1);
|
||||
|
||||
// Broadcast signal
|
||||
Collection<Entry<String, String>> assertions = new ArrayList<>();
|
||||
List<Integer> kindAssertions = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
// Broadcast from TestParticipant0
|
||||
final CountDownLatch signalEventLatch1 = new CountDownLatch(2);
|
||||
final CountDownLatch broadcastLatch0 = new CountDownLatch(2);
|
||||
|
||||
user.getEventManager().on(1, "dataReceived", "RoomEvent", json -> {
|
||||
assertions.add(new AbstractMap.SimpleEntry<>("Message from TestParticipant0 to all room",
|
||||
assertions.add(new AbstractMap.SimpleEntry<>(
|
||||
"Message from TestParticipant0 to all room (kind: " + expectedKindStr + ")",
|
||||
json.getAsJsonObject().get("eventDescription").getAsString()));
|
||||
signalEventLatch1.countDown();
|
||||
kindAssertions.add(json.getAsJsonObject().get("eventContent").getAsJsonObject().get("kind").getAsInt());
|
||||
broadcastLatch0.countDown();
|
||||
});
|
||||
user.getEventManager().on(1, "dataReceived", "ParticipantEvent", json -> {
|
||||
assertions.add(new AbstractMap.SimpleEntry<>("Message from TestParticipant0 to all room",
|
||||
assertions.add(new AbstractMap.SimpleEntry<>(
|
||||
"Message from TestParticipant0 to all room (kind: " + expectedKindStr + ")",
|
||||
json.getAsJsonObject().get("eventDescription").getAsString()));
|
||||
signalEventLatch1.countDown();
|
||||
kindAssertions.add(json.getAsJsonObject().get("eventContent").getAsJsonObject().get("kind").getAsInt());
|
||||
broadcastLatch0.countDown();
|
||||
});
|
||||
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .message-btn")).click();
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 " + btnClass)).click();
|
||||
user.getEventManager().waitUntilEventReaches(1, "dataReceived", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches(1, "dataReceived", "ParticipantEvent", 1);
|
||||
// Do not trigger own signals
|
||||
Assertions.assertEquals(0, user.getEventManager().getNumEvents(0, "dataReceived-RoomEvent").get());
|
||||
Assertions.assertEquals(0, user.getEventManager().getNumEvents(0, "dataReceived-ParticipantEvent").get());
|
||||
|
||||
if (!signalEventLatch1.await(3, TimeUnit.SECONDS)) {
|
||||
Assertions.fail("Timeout waiting for signal event content check");
|
||||
if (!broadcastLatch0.await(3, TimeUnit.SECONDS)) {
|
||||
Assertions.fail("Timeout waiting for broadcast signal event from TestParticipant0");
|
||||
}
|
||||
assertions.forEach(assertion -> Assertions.assertEquals(assertion.getKey(), assertion.getValue()));
|
||||
kindAssertions.forEach(
|
||||
kind -> Assertions.assertEquals(expectedKind, kind, "Expected DataPacket_Kind " + expectedKind));
|
||||
user.getEventManager().off(1, "dataReceived", "RoomEvent");
|
||||
user.getEventManager().off(1, "dataReceived", "ParticipantEvent");
|
||||
assertions.clear();
|
||||
kindAssertions.clear();
|
||||
user.getEventManager().clearAllCurrentEvents();
|
||||
|
||||
// Broadcast from TestParticipant1
|
||||
final CountDownLatch signalEventLatch2 = new CountDownLatch(2);
|
||||
final CountDownLatch broadcastLatch1 = new CountDownLatch(2);
|
||||
|
||||
user.getEventManager().on(0, "dataReceived", "RoomEvent", json -> {
|
||||
assertions.add(new AbstractMap.SimpleEntry<>("Message from TestParticipant1 to all room",
|
||||
assertions.add(new AbstractMap.SimpleEntry<>(
|
||||
"Message from TestParticipant1 to all room (kind: " + expectedKindStr + ")",
|
||||
json.getAsJsonObject().get("eventDescription").getAsString()));
|
||||
signalEventLatch2.countDown();
|
||||
kindAssertions.add(json.getAsJsonObject().get("eventContent").getAsJsonObject().get("kind").getAsInt());
|
||||
broadcastLatch1.countDown();
|
||||
});
|
||||
user.getEventManager().on(0, "dataReceived", "ParticipantEvent", json -> {
|
||||
assertions.add(new AbstractMap.SimpleEntry<>("Message from TestParticipant1 to all room",
|
||||
assertions.add(new AbstractMap.SimpleEntry<>(
|
||||
"Message from TestParticipant1 to all room (kind: " + expectedKindStr + ")",
|
||||
json.getAsJsonObject().get("eventDescription").getAsString()));
|
||||
signalEventLatch2.countDown();
|
||||
kindAssertions.add(json.getAsJsonObject().get("eventContent").getAsJsonObject().get("kind").getAsInt());
|
||||
broadcastLatch1.countDown();
|
||||
});
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .message-btn")).click();
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 " + btnClass)).click();
|
||||
user.getEventManager().waitUntilEventReaches(0, "dataReceived", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches(0, "dataReceived", "ParticipantEvent", 1);
|
||||
// Do not trigger own signals
|
||||
Assertions.assertEquals(1, user.getEventManager().getNumEvents(0, "dataReceived-RoomEvent").get());
|
||||
Assertions.assertEquals(1, user.getEventManager().getNumEvents(0, "dataReceived-ParticipantEvent").get());
|
||||
|
||||
if (!signalEventLatch2.await(3, TimeUnit.SECONDS)) {
|
||||
Assertions.fail("Timeout waiting for signal event content check");
|
||||
if (!broadcastLatch1.await(3, TimeUnit.SECONDS)) {
|
||||
Assertions.fail("Timeout waiting for broadcast signal event from TestParticipant1");
|
||||
}
|
||||
assertions.forEach(assertion -> Assertions.assertEquals(assertion.getKey(), assertion.getValue()));
|
||||
kindAssertions.forEach(
|
||||
kind -> Assertions.assertEquals(expectedKind, kind, "Expected DataPacket_Kind " + expectedKind));
|
||||
user.getEventManager().off(0, "dataReceived", "RoomEvent");
|
||||
user.getEventManager().off(0, "dataReceived", "ParticipantEvent");
|
||||
assertions.clear();
|
||||
kindAssertions.clear();
|
||||
user.getEventManager().clearAllCurrentEvents();
|
||||
|
||||
// Signal specific participant
|
||||
|
||||
// Signal from TestParticipant0 to TestParticipant1
|
||||
final CountDownLatch signalEventLatch3 = new CountDownLatch(2);
|
||||
final CountDownLatch directLatch0 = new CountDownLatch(2);
|
||||
|
||||
user.getEventManager().on(1, "dataReceived", "RoomEvent", json -> {
|
||||
assertions.add(new AbstractMap.SimpleEntry<>("Message from TestParticipant0 to TestParticipant1",
|
||||
assertions.add(new AbstractMap.SimpleEntry<>(
|
||||
"Message from TestParticipant0 to TestParticipant1 (kind: " + expectedKindStr + ")",
|
||||
json.getAsJsonObject().get("eventDescription").getAsString()));
|
||||
signalEventLatch3.countDown();
|
||||
kindAssertions.add(json.getAsJsonObject().get("eventContent").getAsJsonObject().get("kind").getAsInt());
|
||||
directLatch0.countDown();
|
||||
});
|
||||
user.getEventManager().on(1, "dataReceived", "ParticipantEvent", json -> {
|
||||
assertions.add(new AbstractMap.SimpleEntry<>("Message from TestParticipant0 to TestParticipant1",
|
||||
assertions.add(new AbstractMap.SimpleEntry<>(
|
||||
"Message from TestParticipant0 to TestParticipant1 (kind: " + expectedKindStr + ")",
|
||||
json.getAsJsonObject().get("eventDescription").getAsString()));
|
||||
signalEventLatch3.countDown();
|
||||
kindAssertions.add(json.getAsJsonObject().get("eventContent").getAsJsonObject().get("kind").getAsInt());
|
||||
directLatch0.countDown();
|
||||
});
|
||||
user.getDriver()
|
||||
.findElement(By.cssSelector("#openvidu-instance-0 app-participant.remote-participant .message-btn"))
|
||||
.findElement(
|
||||
By.cssSelector("#openvidu-instance-0 app-participant.remote-participant " + btnClass))
|
||||
.click();
|
||||
user.getEventManager().waitUntilEventReaches(1, "dataReceived", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches(1, "dataReceived", "ParticipantEvent", 1);
|
||||
|
||||
// Do not trigger own signals
|
||||
Assertions.assertEquals(0, user.getEventManager().getNumEvents(0, "dataReceived-RoomEvent").get());
|
||||
Assertions.assertEquals(0, user.getEventManager().getNumEvents(0, "dataReceived-ParticipantEvent").get());
|
||||
|
||||
if (!signalEventLatch3.await(3, TimeUnit.SECONDS)) {
|
||||
Assertions.fail("Timeout waiting for signal event content check");
|
||||
if (!directLatch0.await(3, TimeUnit.SECONDS)) {
|
||||
Assertions.fail("Timeout waiting for direct signal event from TestParticipant0");
|
||||
}
|
||||
assertions.forEach(assertion -> Assertions.assertEquals(assertion.getKey(), assertion.getValue()));
|
||||
kindAssertions.forEach(
|
||||
kind -> Assertions.assertEquals(expectedKind, kind, "Expected DataPacket_Kind " + expectedKind));
|
||||
user.getEventManager().off(1, "dataReceived", "RoomEvent");
|
||||
user.getEventManager().off(1, "dataReceived", "ParticipantEvent");
|
||||
assertions.clear();
|
||||
kindAssertions.clear();
|
||||
user.getEventManager().clearAllCurrentEvents();
|
||||
|
||||
// Signal from TestParticipant1 to TestParticipant0
|
||||
final CountDownLatch signalEventLatch4 = new CountDownLatch(2);
|
||||
final CountDownLatch directLatch1 = new CountDownLatch(2);
|
||||
|
||||
user.getEventManager().on(0, "dataReceived", "RoomEvent", json -> {
|
||||
assertions.add(new AbstractMap.SimpleEntry<>("Message from TestParticipant1 to TestParticipant0",
|
||||
assertions.add(new AbstractMap.SimpleEntry<>(
|
||||
"Message from TestParticipant1 to TestParticipant0 (kind: " + expectedKindStr + ")",
|
||||
json.getAsJsonObject().get("eventDescription").getAsString()));
|
||||
signalEventLatch4.countDown();
|
||||
kindAssertions.add(json.getAsJsonObject().get("eventContent").getAsJsonObject().get("kind").getAsInt());
|
||||
directLatch1.countDown();
|
||||
});
|
||||
user.getEventManager().on(0, "dataReceived", "ParticipantEvent", json -> {
|
||||
assertions.add(new AbstractMap.SimpleEntry<>("Message from TestParticipant1 to TestParticipant0",
|
||||
assertions.add(new AbstractMap.SimpleEntry<>(
|
||||
"Message from TestParticipant1 to TestParticipant0 (kind: " + expectedKindStr + ")",
|
||||
json.getAsJsonObject().get("eventDescription").getAsString()));
|
||||
signalEventLatch4.countDown();
|
||||
kindAssertions.add(json.getAsJsonObject().get("eventContent").getAsJsonObject().get("kind").getAsInt());
|
||||
directLatch1.countDown();
|
||||
});
|
||||
user.getDriver()
|
||||
.findElement(By.cssSelector("#openvidu-instance-1 app-participant.remote-participant .message-btn"))
|
||||
.findElement(
|
||||
By.cssSelector("#openvidu-instance-1 app-participant.remote-participant " + btnClass))
|
||||
.click();
|
||||
user.getEventManager().waitUntilEventReaches(0, "dataReceived", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches(0, "dataReceived", "ParticipantEvent", 1);
|
||||
|
||||
// Do not trigger own signals
|
||||
Assertions.assertEquals(0, user.getEventManager().getNumEvents(1, "dataReceived-RoomEvent").get());
|
||||
Assertions.assertEquals(0, user.getEventManager().getNumEvents(1, "dataReceived-ParticipantEvent").get());
|
||||
|
||||
if (!signalEventLatch4.await(3, TimeUnit.SECONDS)) {
|
||||
Assertions.fail("Timeout waiting for signal event content check");
|
||||
if (!directLatch1.await(3, TimeUnit.SECONDS)) {
|
||||
Assertions.fail("Timeout waiting for direct signal event from TestParticipant1");
|
||||
}
|
||||
assertions.forEach(assertion -> Assertions.assertEquals(assertion.getKey(), assertion.getValue()));
|
||||
kindAssertions.forEach(
|
||||
kind -> Assertions.assertEquals(expectedKind, kind, "Expected DataPacket_Kind " + expectedKind));
|
||||
|
||||
gracefullyLeaveParticipants(user, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("ConnectionQualityChanged")
|
||||
void connectionQualityChangedTest() throws Exception {
|
||||
|
||||
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
|
||||
|
||||
log.info("ConnectionQualityChanged");
|
||||
|
||||
user.getDriver().findElement(By.id("auto-join-checkbox")).click();
|
||||
user.getDriver().findElement(By.id("one2one-btn")).click();
|
||||
|
||||
user.getEventManager().waitUntilEventReaches("signalConnected", "RoomEvent", 2);
|
||||
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 2);
|
||||
user.getEventManager().waitUntilEventReaches("localTrackPublished", "RoomEvent", 4);
|
||||
user.getEventManager().waitUntilEventReaches("trackSubscribed", "RoomEvent", 4);
|
||||
user.getEventManager().waitUntilEventReaches("connectionQualityChanged", "RoomEvent", 4);
|
||||
user.getEventManager().waitUntilEventReaches("connectionQualityChanged", "ParticipantEvent", 4);
|
||||
|
||||
// Expect the connection quality events to include as text content: "excellent"
|
||||
user.getDriver().findElements(By.cssSelector(".connectionQualityChanged-TestParticipant0 .event-content"))
|
||||
.forEach(el -> Assertions.assertTrue(el.getText().contains("excellent"),
|
||||
"Expected connection quality to be excellent"));
|
||||
user.getDriver().findElements(By.cssSelector(".connectionQualityChanged-TestParticipant1 .event-content"))
|
||||
.forEach(el -> Assertions.assertTrue(el.getText().contains("excellent"),
|
||||
"Expected connection quality to be excellent"));
|
||||
|
||||
gracefullyLeaveParticipants(user, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Data Tracks publish, subscribe, send and receive")
|
||||
void dataTracksTest() throws Exception {
|
||||
|
||||
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
|
||||
|
||||
log.info("Data Tracks publish, subscribe, send and receive");
|
||||
|
||||
// Two participants, no audio/video publishing
|
||||
for (int i = 0; i < 2; i++) {
|
||||
WebElement addUserBtn = user.getDriver().findElement(By.id("add-user-btn"));
|
||||
addUserBtn.click();
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-" + i + " .subscriber-checkbox")).click();
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-" + i + " .publisher-checkbox")).click();
|
||||
}
|
||||
user.getDriver().findElements(By.className("connect-btn")).forEach(el -> el.sendKeys(Keys.ENTER));
|
||||
user.getEventManager().waitUntilEventReaches("signalConnected", "RoomEvent", 2);
|
||||
user.getEventManager().waitUntilEventReaches("connected", "RoomEvent", 2);
|
||||
user.getEventManager().waitUntilEventReaches("participantConnected", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches("participantActive", "RoomEvent", 1);
|
||||
|
||||
// Participant 0 publishes a data track
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .add-data-track-btn")).click();
|
||||
|
||||
// Wait for localDataTrackPublished on participant 0 and dataTrackPublished on participant 1
|
||||
user.getEventManager().waitUntilEventReaches(0, "localDataTrackPublished", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches(1, "dataTrackPublished", "RoomEvent", 1);
|
||||
|
||||
// Verify event descriptions
|
||||
user.getDriver().findElements(By.cssSelector(".localDataTrackPublished-TestParticipant0 .event-content"))
|
||||
.forEach(el -> Assertions.assertTrue(el.getText().contains("data_track_1"),
|
||||
"Expected localDataTrackPublished to contain track name 'data_track_1'"));
|
||||
user.getDriver().findElements(By.cssSelector(".dataTrackPublished-TestParticipant1 .event-content"))
|
||||
.forEach(el -> Assertions.assertTrue(
|
||||
el.getText().contains("TestParticipant0") && el.getText().contains("data_track_1"),
|
||||
"Expected dataTrackPublished to contain publisher identity and track name"));
|
||||
|
||||
// Participant 0 does not receive its own dataTrackPublished
|
||||
Assertions.assertEquals(0, user.getEventManager().getNumEvents(0, "dataTrackPublished-RoomEvent").get(),
|
||||
"Publisher should not receive dataTrackPublished for its own data track");
|
||||
|
||||
// Participant 0 sends data frames
|
||||
org.openqa.selenium.JavascriptExecutor js = (org.openqa.selenium.JavascriptExecutor) user.getDriver();
|
||||
js.executeScript("document.querySelector('#openvidu-instance-0 .send-data-frame-btn').click()");
|
||||
js.executeScript("document.querySelector('#openvidu-instance-0 .send-data-frame-btn').click()");
|
||||
js.executeScript("document.querySelector('#openvidu-instance-0 .send-data-frame-btn').click()");
|
||||
|
||||
// Wait for frames to arrive at participant 1
|
||||
Thread.sleep(1000);
|
||||
Long frameCount = (Long) js.executeScript(
|
||||
"var el = document.querySelector('#openvidu-instance-1 .data-track-frame-count');" +
|
||||
"return el ? parseInt(el.textContent) : 0;");
|
||||
Assertions.assertEquals(frameCount, 3, "Expected 3 data track frames received, got " + frameCount);
|
||||
|
||||
String lastPayload = (String) js.executeScript(
|
||||
"var el = document.querySelector('#openvidu-instance-1 .data-track-last-payload');" +
|
||||
"return el ? el.textContent : '';");
|
||||
Assertions.assertTrue(lastPayload.contains("DataTrackFrame from TestParticipant0"),
|
||||
"Expected last payload to contain 'DataTrackFrame from TestParticipant0', got: " + lastPayload);
|
||||
|
||||
// Participant 0 unpublishes the data track
|
||||
js.executeScript("document.querySelector('#openvidu-instance-0 .unpublish-data-track-btn').click()");
|
||||
|
||||
// Wait for unpublish events
|
||||
user.getEventManager().waitUntilEventReaches(0, "localDataTrackUnpublished", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches(1, "dataTrackUnpublished", "RoomEvent", 1);
|
||||
|
||||
// Participant 0 does not receive its own dataTrackUnpublished
|
||||
Assertions.assertEquals(0, user.getEventManager().getNumEvents(0, "dataTrackUnpublished-RoomEvent").get(),
|
||||
"Publisher should not receive dataTrackUnpublished for its own data track");
|
||||
|
||||
user.getEventManager().clearAllCurrentEvents();
|
||||
|
||||
// Now participant 1 publishes a data track with custom name (bidirectional test)
|
||||
String customTrackName = "my_custom_data_track";
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .options-data-track-btn")).click();
|
||||
Thread.sleep(500);
|
||||
WebElement trackNameInput = user.getDriver().findElement(By.id("dataTrack-name"));
|
||||
trackNameInput.clear();
|
||||
trackNameInput.sendKeys(customTrackName);
|
||||
user.getDriver().findElement(By.id("close-dialog-btn")).click();
|
||||
Thread.sleep(500);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .add-data-track-btn")).click();
|
||||
|
||||
user.getEventManager().waitUntilEventReaches(1, "localDataTrackPublished", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches(0, "dataTrackPublished", "RoomEvent", 1);
|
||||
|
||||
// Verify participant 0 sees the custom track name on the remote data track
|
||||
Thread.sleep(500);
|
||||
String remoteTrackName = (String) js.executeScript(
|
||||
"var el = document.querySelector('#openvidu-instance-0 .data-track-name');" +
|
||||
"return el ? el.textContent.trim() : '';");
|
||||
Assertions.assertEquals(customTrackName, remoteTrackName,
|
||||
"Remote data track name should be '" + customTrackName + "', got: " + remoteTrackName);
|
||||
|
||||
// Participant 1 sends a data frame
|
||||
js.executeScript("document.querySelector('#openvidu-instance-1 .send-data-frame-btn').click()");
|
||||
|
||||
// Wait for frame to arrive at participant 0
|
||||
Thread.sleep(1000);
|
||||
|
||||
Long frameCount0 = (Long) js.executeScript(
|
||||
"var el = document.querySelector('#openvidu-instance-0 .data-track-frame-count');" +
|
||||
"return el ? parseInt(el.textContent) : 0;");
|
||||
Assertions.assertTrue(frameCount0 >= 1,
|
||||
"Expected at least 1 data track frame received by participant 0, got " + frameCount0);
|
||||
|
||||
String lastPayload0 = (String) js.executeScript(
|
||||
"var el = document.querySelector('#openvidu-instance-0 .data-track-last-payload');" +
|
||||
"return el ? el.textContent : '';");
|
||||
Assertions.assertTrue(lastPayload0.contains("DataTrackFrame from TestParticipant1"),
|
||||
"Expected last payload to contain 'DataTrackFrame from TestParticipant1', got: " + lastPayload0);
|
||||
|
||||
// Participant 1 unpublishes
|
||||
js.executeScript("document.querySelector('#openvidu-instance-1 .unpublish-data-track-btn').click()");
|
||||
user.getEventManager().waitUntilEventReaches(1, "localDataTrackUnpublished", "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches(0, "dataTrackUnpublished", "RoomEvent", 1);
|
||||
|
||||
gracefullyLeaveParticipants(user, 2);
|
||||
}
|
||||
|
|
@ -645,12 +842,11 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
private void forceCodecTest(OpenViduTestappUser user, String codec) throws Exception {
|
||||
this.addOnlyPublisherVideo(user, false, false, false);
|
||||
|
||||
user.getDriver().findElement(By.id("room-options-btn-0")).click();
|
||||
this.waitForBackdropAndClick(user, "#room-options-btn-0");
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.id("trackPublish-backupCodec")).click();
|
||||
user.getDriver().findElement(By.id("trackPublish-videoCodec")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.id("mat-option-" + codec.toLowerCase())).click();
|
||||
this.waitForBackdropAndClick(user, "#mat-option-" + codec.toLowerCase());
|
||||
this.waitForBackdropAndClick(user, "#close-dialog-btn");
|
||||
Thread.sleep(300);
|
||||
|
||||
|
|
@ -746,13 +942,12 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
WebElement participantNameInput = chromeUser.getDriver().findElement(By.id("participant-name-input-0"));
|
||||
participantNameInput.clear();
|
||||
participantNameInput.sendKeys("CHROME_USER");
|
||||
chromeUser.getDriver().findElement(By.id("room-options-btn-0")).click();
|
||||
this.waitForBackdropAndClick(chromeUser, "#room-options-btn-0");
|
||||
Thread.sleep(300);
|
||||
chromeUser.getDriver().findElement(By.id("trackPublish-backupCodec")).click();
|
||||
chromeUser.getDriver().findElement(By.id("trackPublish-videoCodec")).click();
|
||||
Thread.sleep(300);
|
||||
chromeUser.getDriver().findElement(By.id("mat-option-" + codec.toLowerCase())).click();
|
||||
chromeUser.getDriver().findElement(By.id("close-dialog-btn")).click();
|
||||
this.waitForBackdropAndClick(chromeUser, "#mat-option-" + codec.toLowerCase());
|
||||
this.waitForBackdropAndClick(chromeUser, "#close-dialog-btn");
|
||||
Thread.sleep(300);
|
||||
chromeUser.getDriver().findElement(By.className("connect-btn")).click();
|
||||
chromeUser.getEventManager().waitUntilEventReaches("localTrackSubscribed", "ParticipantEvent", 1);
|
||||
|
|
@ -963,13 +1158,11 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
|
||||
// Manually change video quality of first subscriber to q
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-LOW")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-LOW");
|
||||
|
||||
// Manually change video quality of second subscriber to f
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-2 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-HIGH")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-HIGH");
|
||||
|
||||
subscriberVideo1 = user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 video.remote"));
|
||||
WebElement subscriberVideo2 = user.getDriver().findElement(By.cssSelector("#openvidu-instance-2 video.remote"));
|
||||
|
|
@ -996,8 +1189,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
|
||||
// Manually change video quality of second subscriber to h
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-2 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-MEDIUM")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-MEDIUM");
|
||||
|
||||
this.waitUntilPublisherLayerActive(user, publisherVideo, "q", true);
|
||||
this.waitUntilPublisherLayerActive(user, publisherVideo, "h", true);
|
||||
|
|
@ -1159,20 +1351,17 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
|
||||
// Manually change video quality of subscriber to h
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-MEDIUM")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-MEDIUM");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, h);
|
||||
|
||||
// Manually change video quality of subscriber to q
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-LOW")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-LOW");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, q);
|
||||
|
||||
// Manually change video quality of subscriber to f
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-HIGH")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-HIGH");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, f);
|
||||
|
||||
gracefullyLeaveParticipants(user, 2);
|
||||
|
|
@ -1561,11 +1750,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
|
||||
user.getDriver().findElement(By.cssSelector("#start-" + egressType + "-egress-api-btn")).click();
|
||||
|
||||
// TODO: UNCOMMENT WHEN MEDIASOUP IS ABLE TO MANAGE ABRUPT
|
||||
// CONNECTIONSTATECHANGED DISOCONNECTED/FAILED
|
||||
// https://mediasoup.discourse.group/t/mediasoup-3-13-20-released-with-server-side-ice-consent-check-and-a-critical-fix/5864
|
||||
// user.getEventManager().waitUntilEventReaches("recordingStatusChanged",
|
||||
// "RoomEvent", 1);
|
||||
user.getEventManager().waitUntilEventReaches("recordingStatusChanged",
|
||||
"RoomEvent", 1);
|
||||
|
||||
WebElement egressIdField = user.getDriver().findElement(By.id("egress-id-field"));
|
||||
WebDriverWait wait = new WebDriverWait(user.getDriver(), Duration.ofSeconds(10));
|
||||
|
|
@ -1586,11 +1772,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
this.checkRecordingInEgressBackupFolder(egress);
|
||||
}
|
||||
|
||||
// TODO: UNCOMMENT WHEN MEDIASOUP IS ABLE TO MANAGE ABRUPT
|
||||
// CONNECTIONSTATECHANGED DISOCONNECTED/FAILED
|
||||
// https://mediasoup.discourse.group/t/mediasoup-3-13-20-released-with-server-side-ice-consent-check-and-a-critical-fix/5864
|
||||
// user.getEventManager().waitUntilEventReaches("recordingStatusChanged",
|
||||
// "RoomEvent", 2);
|
||||
user.getEventManager().waitUntilEventReaches("recordingStatusChanged",
|
||||
"RoomEvent", 2);
|
||||
}
|
||||
|
||||
private JsonObject waitUntilEgressStatus(OpenViduTestappUser user, String egressId, String egressStatus,
|
||||
|
|
@ -2420,16 +2603,13 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
// Check manual simulcast changes
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1920);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-LOW")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-LOW");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 640);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-MEDIUM")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-MEDIUM");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1280);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-HIGH")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-HIGH");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1920);
|
||||
}
|
||||
|
||||
|
|
@ -2437,28 +2617,23 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
// Check manual simulcast changes
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 960);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-LOW")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-LOW");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 480);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-MEDIUM")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-MEDIUM");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 960);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-LOW")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-LOW");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 480);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-HIGH")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-HIGH");
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 960);
|
||||
}
|
||||
|
||||
private void testNoSimulcast(OpenViduTestappUser user, WebElement subscriberVideo) throws InterruptedException {
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1920);
|
||||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 #max-video-quality")).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("mat-option.mode-LOW")).click();
|
||||
this.waitForBackdropAndClick(user, "mat-option.mode-LOW");
|
||||
// Without simulcast video should remain in high quality
|
||||
Thread.sleep(4000);
|
||||
this.waitUntilSubscriberFrameWidthIs(user, subscriberVideo, 1920);
|
||||
|
|
@ -2702,7 +2877,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-" + numberOfUser + " .subscriber-checkbox"))
|
||||
.click();
|
||||
}
|
||||
user.getDriver().findElement(By.id("room-options-btn-" + numberOfUser)).click();
|
||||
this.waitForBackdropAndClick(user, "#room-options-btn-" + numberOfUser);
|
||||
Thread.sleep(300);
|
||||
if (!hasAudio) {
|
||||
user.getDriver().findElement(By.id("audio-capture-false")).click();
|
||||
|
|
@ -2740,9 +2915,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
user.getDriver().findElement(By.cssSelector("#openvidu-instance-" + numberOfUser + " .publisher-checkbox"))
|
||||
.click();
|
||||
if (!adaptiveStream) {
|
||||
user.getDriver().findElement(By.id("room-options-btn-" + numberOfUser)).click();
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.id("room-adaptiveStream")).click();
|
||||
this.waitForBackdropAndClick(user, "#room-options-btn-" + numberOfUser);
|
||||
this.waitForBackdropAndClick(user, "#room-adaptiveStream");
|
||||
user.getDriver().findElement(By.id("close-dialog-btn")).click();
|
||||
Thread.sleep(300);
|
||||
}
|
||||
|
|
@ -2757,21 +2931,18 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
user.getDriver().findElement(By.xpath("//button[contains(@title,'Room API')]")).click();
|
||||
if (preset != null) {
|
||||
this.waitForBackdropAndClick(user, "#ingress-preset-select");
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("#mat-option-" + preset.toUpperCase())).click();
|
||||
this.waitForBackdropAndClick(user, "#mat-option-" + preset.toUpperCase());
|
||||
} else {
|
||||
if (!simulcast) {
|
||||
this.waitForBackdropAndClick(user, "#ingress-simulcast");
|
||||
Thread.sleep(300);
|
||||
}
|
||||
this.waitForBackdropAndClick(user, "#ingress-video-codec-select");
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("#mat-option-" + codec.toUpperCase())).click();
|
||||
this.waitForBackdropAndClick(user, "#mat-option-" + codec.toUpperCase());
|
||||
}
|
||||
if (urlType != null) {
|
||||
this.waitForBackdropAndClick(user, "#ingress-url-type-select");
|
||||
Thread.sleep(300);
|
||||
user.getDriver().findElement(By.cssSelector("#mat-option-" + urlType.toUpperCase())).click();
|
||||
this.waitForBackdropAndClick(user, "#mat-option-" + urlType.toUpperCase());
|
||||
}
|
||||
if (urlUri != null) {
|
||||
user.getDriver().findElement(By.cssSelector("#ingress-url-uri-field")).sendKeys(urlUri);
|
||||
|
|
@ -2797,7 +2968,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
}
|
||||
if (scalabilityMode != null) {
|
||||
user.getDriver().findElement(By.id("trackPublish-scalabilityMode")).click();
|
||||
user.getDriver().findElement(By.className("mode-" + scalabilityMode)).click();
|
||||
this.waitForBackdropAndClick(user, ".mode-" + scalabilityMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2835,20 +3006,29 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
try {
|
||||
Thread.sleep(retryIntervalMillis);
|
||||
} catch (InterruptedException e) {
|
||||
// Print screenshot
|
||||
String screenshot = "data:image/png;base64,"
|
||||
+ ((TakesScreenshot) user.getDriver()).getScreenshotAs(BASE64);
|
||||
System.out.println("INTERRUPTED EXCEPTION WHILE WAITING FOR ELEMENT TO BE CLICKABLE: " + cssSelector);
|
||||
System.out.println(screenshot);
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("Thread interrupted while waiting for backdrop to clear", e);
|
||||
}
|
||||
}
|
||||
|
||||
String screenshot = "data:image/png;base64," + ((TakesScreenshot) user.getDriver()).getScreenshotAs(BASE64);
|
||||
System.out.println("TIMEOUT WAITING FOR ELEMENT TO BE CLICKABLE (): " + cssSelector);
|
||||
System.out.println(screenshot);
|
||||
|
||||
// If we get here, we've timed out
|
||||
throw new RuntimeException("Timeout waiting for element '" + cssSelector
|
||||
+ "' to be clickable without backdrop interference after " + timeoutMillis + "ms");
|
||||
}
|
||||
|
||||
public boolean assertAllElementsHaveTracks(OpenViduTestappUser user, String selector, boolean hasAudio, boolean hasVideo) {
|
||||
public boolean assertAllElementsHaveTracks(OpenViduTestappUser user, String selector, boolean hasAudio,
|
||||
boolean hasVideo) {
|
||||
org.openqa.selenium.JavascriptExecutor js = (org.openqa.selenium.JavascriptExecutor) user.getDriver();
|
||||
String script =
|
||||
"var elements = document.querySelectorAll(arguments[0]);" +
|
||||
String script = "var elements = document.querySelectorAll(arguments[0]);" +
|
||||
"for (var i = 0; i < elements.length; i++) {" +
|
||||
" var el = elements[i];" +
|
||||
" if (!el.srcObject) return false;" +
|
||||
|
|
@ -2861,9 +3041,12 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
return (Boolean) js.executeScript(script, selector, hasAudio, hasVideo);
|
||||
}
|
||||
|
||||
public void changeElementSize(OpenViduTestappUser user, org.openqa.selenium.WebElement element, int width, int height) {
|
||||
public void changeElementSize(OpenViduTestappUser user, org.openqa.selenium.WebElement element, int width,
|
||||
int height) {
|
||||
org.openqa.selenium.JavascriptExecutor js = (org.openqa.selenium.JavascriptExecutor) user.getDriver();
|
||||
js.executeScript("arguments[0].style.width = '" + width + "px'; arguments[0].style.height = '" + height + "px';", element);
|
||||
js.executeScript(
|
||||
"arguments[0].style.width = '" + width + "px'; arguments[0].style.height = '" + height + "px';",
|
||||
element);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -10,28 +10,29 @@
|
|||
"ng": "ng",
|
||||
"start": "ng serve --ssl --host 0.0.0.0",
|
||||
"start-insecure": "ng serve --host 0.0.0.0",
|
||||
"start:ci": "ng build && http-server dist/openvidu-testapp-livekit/browser -p 4200 -a 0.0.0.0 -c-1",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^21.2.6",
|
||||
"@angular/cdk": "^21.2.4",
|
||||
"@angular/common": "^21.2.6",
|
||||
"@angular/compiler": "^21.2.6",
|
||||
"@angular/core": "^21.2.6",
|
||||
"@angular/forms": "^21.2.6",
|
||||
"@angular/material": "^21.2.4",
|
||||
"@angular/platform-browser": "^21.2.6",
|
||||
"@angular/router": "^21.2.6",
|
||||
"@livekit/protocol": "^1.45.1",
|
||||
"@angular/animations": "^21.2.9",
|
||||
"@angular/cdk": "^21.2.7",
|
||||
"@angular/common": "^21.2.9",
|
||||
"@angular/compiler": "^21.2.9",
|
||||
"@angular/core": "^21.2.9",
|
||||
"@angular/forms": "^21.2.9",
|
||||
"@angular/material": "^21.2.7",
|
||||
"@angular/platform-browser": "^21.2.9",
|
||||
"@angular/router": "^21.2.9",
|
||||
"@livekit/protocol": "^1.45.3",
|
||||
"@livekit/track-processors": "^0.7.2",
|
||||
"buffer": "^6.0.3",
|
||||
"crypto-browserify": "^3.12.1",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"livekit-client": "^2.18.0",
|
||||
"livekit-server-sdk": "^2.15.0",
|
||||
"livekit-client": "2.18.4",
|
||||
"livekit-server-sdk": "^2.15.1",
|
||||
"rxjs": "~7.8.2",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"tslib": "^2.8.1",
|
||||
|
|
@ -39,15 +40,16 @@
|
|||
"zone.js": "~0.16.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/build": "^21.2.4",
|
||||
"@angular/cli": "~21.2.4",
|
||||
"@angular/compiler-cli": "^21.2.6",
|
||||
"@angular/build": "^21.2.7",
|
||||
"@angular/cli": "~21.2.7",
|
||||
"@angular/compiler-cli": "^21.2.9",
|
||||
"@types/dom-mediacapture-transform": "^0.1.11",
|
||||
"@types/events": "^3.0.3",
|
||||
"@types/jasmine": "~6.0.0",
|
||||
"@types/json-stringify-safe": "^5.0.3",
|
||||
"@types/node": "^25.5.0",
|
||||
"jasmine-core": "~6.1.0",
|
||||
"@types/node": "^25.6.0",
|
||||
"http-server": "^14.1.1",
|
||||
"jasmine-core": "~6.2.0",
|
||||
"karma": "~6.4.4",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
"karma-coverage": "~2.2.1",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
.parent-div {
|
||||
display: grid;
|
||||
margin-bottom: 4px;
|
||||
background-color: #fcfcfc;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.data-track-name {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.bottom-div {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
.data-btn {
|
||||
border: none;
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
height: 16px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.data-btn:hover {
|
||||
color: #4d4d4d;
|
||||
}
|
||||
|
||||
.data-btn mat-icon {
|
||||
font-size: 14px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.data-track-info {
|
||||
font-size: 10px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.data-track-frame-count {
|
||||
font-weight: bold;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.data-track-last-payload {
|
||||
color: #555;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<div class="parent-div">
|
||||
<span class="data-track-name">{{getTrackName()}}</span>
|
||||
<div class="bottom-div">
|
||||
@if (localParticipant && localDataTrack) {
|
||||
<button (click)="sendDataFrame()" class="data-btn send-data-frame-btn" matTooltip="Send data frame"
|
||||
matTooltipClass="custom-tooltip">
|
||||
<mat-icon aria-label="Send data frame" class="mat-icon material-icons" role="img"
|
||||
aria-hidden="true">send</mat-icon>
|
||||
</button>
|
||||
}
|
||||
@if (localParticipant && localDataTrack) {
|
||||
<button (click)="unpublishDataTrack()" class="data-btn unpublish-data-track-btn" matTooltip="Unpublish data track"
|
||||
matTooltipClass="custom-tooltip">
|
||||
<mat-icon aria-label="Unpublish data track" class="mat-icon material-icons" role="img"
|
||||
aria-hidden="true">stop</mat-icon>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@if (frameCount > 0) {
|
||||
<div class="data-track-info">
|
||||
<span class="data-track-frame-count">{{frameCount}}</span>
|
||||
<span class="data-track-last-payload">{{lastPayload}}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
import { Component, EventEmitter, Input, Output, ChangeDetectorRef } from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import {
|
||||
LocalDataTrack,
|
||||
LocalParticipant,
|
||||
RemoteDataTrack,
|
||||
} from 'livekit-client';
|
||||
import {
|
||||
TestAppEvent,
|
||||
TestFeedService,
|
||||
} from 'src/app/services/test-feed.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-data-track',
|
||||
templateUrl: './data-track.component.html',
|
||||
styleUrl: './data-track.component.css',
|
||||
imports: [MatIconModule, MatTooltipModule],
|
||||
})
|
||||
export class DataTrackComponent {
|
||||
@Input()
|
||||
localParticipant: LocalParticipant | undefined;
|
||||
|
||||
@Input()
|
||||
index: number;
|
||||
|
||||
@Input()
|
||||
localDataTrack?: LocalDataTrack;
|
||||
|
||||
@Input()
|
||||
remoteDataTrack?: RemoteDataTrack;
|
||||
|
||||
@Output()
|
||||
newTrackEvent = new EventEmitter<TestAppEvent>();
|
||||
|
||||
@Output()
|
||||
trackUnpublished = new EventEmitter<LocalDataTrack>();
|
||||
|
||||
// Received frame info
|
||||
frameCount: number = 0;
|
||||
lastPayload: string = '';
|
||||
|
||||
private decoder = new TextDecoder();
|
||||
|
||||
constructor(
|
||||
private testFeedService: TestFeedService,
|
||||
private cdr: ChangeDetectorRef
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.remoteDataTrack) {
|
||||
this.subscribeToRemoteDataTrack(this.remoteDataTrack);
|
||||
}
|
||||
}
|
||||
|
||||
sendDataFrame() {
|
||||
if (this.localDataTrack) {
|
||||
const payload = new TextEncoder().encode(
|
||||
`DataTrackFrame from ${this.localParticipant?.identity}`
|
||||
);
|
||||
this.localDataTrack.tryPush({ payload });
|
||||
}
|
||||
}
|
||||
|
||||
async unpublishDataTrack() {
|
||||
if (this.localDataTrack) {
|
||||
const track = this.localDataTrack;
|
||||
await track.unpublish();
|
||||
this.trackUnpublished.emit(track);
|
||||
}
|
||||
}
|
||||
|
||||
private async subscribeToRemoteDataTrack(track: RemoteDataTrack) {
|
||||
const stream = track.subscribe();
|
||||
const reader = stream.getReader();
|
||||
try {
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
this.frameCount++;
|
||||
this.lastPayload = this.decoder.decode(value.payload);
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
} catch (_) {
|
||||
// Stream closed
|
||||
}
|
||||
}
|
||||
|
||||
getTrackName(): string {
|
||||
if (this.localDataTrack?.info) {
|
||||
return this.localDataTrack.info.name;
|
||||
}
|
||||
if (this.remoteDataTrack) {
|
||||
return this.remoteDataTrack.info.name;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
@ -233,6 +233,16 @@
|
|||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
@if (dataTrackName !== undefined) {
|
||||
<mat-divider></mat-divider>
|
||||
<div>
|
||||
<label>DataTrackOptions</label><br>
|
||||
<mat-form-field>
|
||||
<mat-label>Track Name</mat-label>
|
||||
<input matInput id="dataTrack-name" placeholder="data_track_1" [(ngModel)]="dataTrackName"/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ export class OptionsDialogComponent {
|
|||
allowDisablingVideo = true;
|
||||
allowDisablingScreen = true;
|
||||
|
||||
dataTrackName?: string;
|
||||
|
||||
videoOption: true | false | 'custom';
|
||||
audioOption: true | false | 'custom';
|
||||
screenOption: true | false | 'custom';
|
||||
|
|
@ -62,6 +64,7 @@ export class OptionsDialogComponent {
|
|||
allowDisablingAudio?: boolean;
|
||||
allowDisablingVideo?: boolean;
|
||||
allowDisablingScreen?: boolean;
|
||||
dataTrackName?: string;
|
||||
}>(MAT_DIALOG_DATA);
|
||||
|
||||
constructor(
|
||||
|
|
@ -114,6 +117,9 @@ export class OptionsDialogComponent {
|
|||
if (this.data.allowDisablingScreen === false) {
|
||||
this.allowDisablingScreen = false;
|
||||
}
|
||||
if (this.data.dataTrackName !== undefined) {
|
||||
this.dataTrackName = this.data.dataTrackName;
|
||||
}
|
||||
Room.getLocalDevices('videoinput').then((devices) => {
|
||||
this.inputVideoDevices = devices;
|
||||
});
|
||||
|
|
@ -152,6 +158,7 @@ export class OptionsDialogComponent {
|
|||
createLocalTracksOptions: this.createLocalTracksOptions,
|
||||
screenShareCaptureOptions: this.screenShareCaptureOptions,
|
||||
trackPublishOptions: this.trackPublishOptions,
|
||||
dataTrackName: this.dataTrackName,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ mat-card.room-card {
|
|||
cursor: pointer;
|
||||
padding: 0;
|
||||
margin-right: 4px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.room-actions button:hover {
|
||||
|
|
|
|||
|
|
@ -58,8 +58,11 @@
|
|||
<button class="peer-info-btn" (click)="openInfoDialog()" title="PCTransports info">
|
||||
<mat-icon aria-label="PCTransports info button">info</mat-icon>
|
||||
</button>
|
||||
<button class="message-btn" (click)="sendData()" title="Broadcast message to room">
|
||||
<mat-icon aria-label="Send message button">chat</mat-icon>
|
||||
<button class="message-reliable-btn" (click)="sendDataReliable()" title="Broadcast reliable message to room">
|
||||
<mat-icon aria-label="Send reliable message button">chat_bubble</mat-icon>
|
||||
</button>
|
||||
<button class="message-lossy-btn" (click)="sendDataLossy()" title="Broadcast lossy message to room">
|
||||
<mat-icon aria-label="Send lossy message button">chat_dashed</mat-icon>
|
||||
</button>
|
||||
<button class="disconnect-btn" (click)="disconnectRoom()" title="Disconnect room">
|
||||
<mat-icon aria-label="Disconnect button">clear</mat-icon>
|
||||
|
|
@ -89,7 +92,9 @@
|
|||
[index]="index"></app-participant>
|
||||
@for (participant of room.remoteParticipants | keyvalue; track participant) {
|
||||
<app-participant class="remote-participant"
|
||||
[participant]="participant.value" [room]="room" [index]="index" (sendDataToOneParticipant)="sendData($event)"></app-participant>
|
||||
[participant]="participant.value" [room]="room" [index]="index"
|
||||
(sendReliableDataToOneParticipant)="sendDataReliable($event)"
|
||||
(sendLossyDataToOneParticipant)="sendDataLossy($event)"></app-participant>
|
||||
}
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
DataPublishOptions,
|
||||
DisconnectReason,
|
||||
LocalAudioTrack,
|
||||
LocalDataTrack,
|
||||
LocalParticipant,
|
||||
LocalTrack,
|
||||
LocalTrackPublication,
|
||||
|
|
@ -28,6 +29,7 @@ import {
|
|||
MediaDeviceFailure,
|
||||
Participant,
|
||||
RemoteAudioTrack,
|
||||
RemoteDataTrack,
|
||||
RemoteParticipant,
|
||||
RemoteTrack,
|
||||
RemoteTrackPublication,
|
||||
|
|
@ -143,7 +145,7 @@ export class OpenviduInstanceComponent {
|
|||
this.participantName += this.index;
|
||||
if (this.roomConf.startSession) {
|
||||
const token = await this.roomApiService.createToken(
|
||||
{ roomJoin: true },
|
||||
{ roomJoin: true, canPublishData: true },
|
||||
this.participantName,
|
||||
this.roomName
|
||||
);
|
||||
|
|
@ -163,7 +165,7 @@ export class OpenviduInstanceComponent {
|
|||
async createTokenAndConnectRoom() {
|
||||
this.connectRoom(
|
||||
await this.roomApiService.createToken(
|
||||
{ roomJoin: true },
|
||||
{ roomJoin: true, canPublishData: true },
|
||||
this.participantName,
|
||||
this.roomName
|
||||
)
|
||||
|
|
@ -770,7 +772,8 @@ export class OpenviduInstanceComponent {
|
|||
kind?: DataPacket_Kind,
|
||||
topic?: string
|
||||
) => {
|
||||
const decodedPayload = this.decoder.decode(payload);
|
||||
let decodedPayload = this.decoder.decode(payload);
|
||||
decodedPayload += ` (kind: ${DataPacket_Kind[kind!]})`;
|
||||
this.updateEventList(
|
||||
RoomEvent.DataReceived,
|
||||
{ payload: decodedPayload, participant, kind, topic },
|
||||
|
|
@ -996,7 +999,7 @@ export class OpenviduInstanceComponent {
|
|||
if (this.roomEvents.get(RoomEvent.DCBufferStatusChanged)) {
|
||||
this.room!.on(
|
||||
RoomEvent.DCBufferStatusChanged,
|
||||
(isLow: boolean, kind: DataPacket_Kind) => {
|
||||
(isLow: boolean, kind: any) => {
|
||||
this.updateEventList(
|
||||
RoomEvent.DCBufferStatusChanged,
|
||||
{ isLow, kind },
|
||||
|
|
@ -1077,6 +1080,86 @@ export class OpenviduInstanceComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
firstTime ||
|
||||
this.roomEvents.get(RoomEvent.DataTrackPublished) !==
|
||||
oldValues.get(RoomEvent.DataTrackPublished)
|
||||
) {
|
||||
this.room?.removeAllListeners(RoomEvent.DataTrackPublished);
|
||||
if (this.roomEvents.get(RoomEvent.DataTrackPublished)) {
|
||||
this.room!.on(
|
||||
RoomEvent.DataTrackPublished,
|
||||
(track: RemoteDataTrack) => {
|
||||
this.updateEventList(
|
||||
RoomEvent.DataTrackPublished,
|
||||
{ name: track.info.name, sid: track.info.sid, publisherIdentity: track.publisherIdentity },
|
||||
`${track.publisherIdentity} (${track.info.name})`
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
firstTime ||
|
||||
this.roomEvents.get(RoomEvent.DataTrackUnpublished) !==
|
||||
oldValues.get(RoomEvent.DataTrackUnpublished)
|
||||
) {
|
||||
this.room?.removeAllListeners(RoomEvent.DataTrackUnpublished);
|
||||
if (this.roomEvents.get(RoomEvent.DataTrackUnpublished)) {
|
||||
this.room!.on(
|
||||
RoomEvent.DataTrackUnpublished,
|
||||
(sid: string) => {
|
||||
this.updateEventList(
|
||||
RoomEvent.DataTrackUnpublished,
|
||||
{ sid },
|
||||
`sid: ${sid}`
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
firstTime ||
|
||||
this.roomEvents.get(RoomEvent.LocalDataTrackPublished) !==
|
||||
oldValues.get(RoomEvent.LocalDataTrackPublished)
|
||||
) {
|
||||
this.room?.removeAllListeners(RoomEvent.LocalDataTrackPublished);
|
||||
if (this.roomEvents.get(RoomEvent.LocalDataTrackPublished)) {
|
||||
this.room!.on(
|
||||
RoomEvent.LocalDataTrackPublished,
|
||||
(track: LocalDataTrack) => {
|
||||
this.updateEventList(
|
||||
RoomEvent.LocalDataTrackPublished,
|
||||
{ name: track.info?.name, sid: track.info?.sid },
|
||||
`${track.info?.name}`
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
firstTime ||
|
||||
this.roomEvents.get(RoomEvent.LocalDataTrackUnpublished) !==
|
||||
oldValues.get(RoomEvent.LocalDataTrackUnpublished)
|
||||
) {
|
||||
this.room?.removeAllListeners(RoomEvent.LocalDataTrackUnpublished);
|
||||
if (this.roomEvents.get(RoomEvent.LocalDataTrackUnpublished)) {
|
||||
this.room!.on(
|
||||
RoomEvent.LocalDataTrackUnpublished,
|
||||
(sid: string) => {
|
||||
this.updateEventList(
|
||||
RoomEvent.LocalDataTrackUnpublished,
|
||||
{ sid },
|
||||
`sid: ${sid}`
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateEventList(
|
||||
|
|
@ -1195,14 +1278,14 @@ export class OpenviduInstanceComponent {
|
|||
});
|
||||
}
|
||||
|
||||
sendData(destinationIdentity?: string) {
|
||||
sendData(destinationIdentity?: string, reliable: boolean = true) {
|
||||
let strData = `Message from ${this.room?.localParticipant.identity}`;
|
||||
strData += destinationIdentity
|
||||
? ` to ${destinationIdentity}`
|
||||
: ' to all room';
|
||||
const data = new TextEncoder().encode(strData);
|
||||
let options: DataPublishOptions = {
|
||||
reliable: true,
|
||||
reliable,
|
||||
};
|
||||
if (destinationIdentity) {
|
||||
options.destinationIdentities = [destinationIdentity];
|
||||
|
|
@ -1210,6 +1293,14 @@ export class OpenviduInstanceComponent {
|
|||
this.room?.localParticipant.publishData(data, options);
|
||||
}
|
||||
|
||||
sendDataReliable(destinationIdentity?: string) {
|
||||
this.sendData(destinationIdentity, true);
|
||||
}
|
||||
|
||||
sendDataLossy(destinationIdentity?: string) {
|
||||
this.sendData(destinationIdentity, false);
|
||||
}
|
||||
|
||||
openInfoDialog() {
|
||||
const updateFunction = async (): Promise<string> => {
|
||||
const pub: PCTransport = this.getPublisherPC()!;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,18 @@
|
|||
<p class="participant-identity" [ngClass]="{'local-participant-identity' : participant.isLocal}">
|
||||
{{participant.identity}}</p>
|
||||
<div class="participant-buttons">
|
||||
@if (participant.isLocal) {
|
||||
<button class="add-data-track-btn" (click)="addDataTrack()" title="New data track"
|
||||
matTooltip="New data track" matTooltipClass="custom-tooltip">
|
||||
<mat-icon aria-label="New data track">stream</mat-icon>
|
||||
</button>
|
||||
}
|
||||
@if (participant.isLocal) {
|
||||
<button class="options-data-track-btn" (click)="openDataTrackOptionsDialog()"
|
||||
title="Data track options" matTooltip="Data track options" matTooltipClass="custom-tooltip">
|
||||
<mat-icon aria-label="Data track options">more_vert</mat-icon>
|
||||
</button>
|
||||
}
|
||||
@if (participant.isLocal) {
|
||||
<button class="add-audio-btn" (click)="addAudioTrack()" title="New audio track"
|
||||
matTooltip="New audio track" matTooltipClass="custom-tooltip">
|
||||
|
|
@ -46,8 +58,11 @@
|
|||
</button>
|
||||
}
|
||||
@if (!participant.isLocal) {
|
||||
<button class="message-btn" (click)="sendData()" title="Send message to this participant">
|
||||
<mat-icon aria-label="Send message button">chat</mat-icon>
|
||||
<button class="message-reliable-btn" (click)="sendDataReliable()" title="Send reliable message to this participant">
|
||||
<mat-icon aria-label="Send reliable message button">chat_bubble</mat-icon>
|
||||
</button>
|
||||
<button class="message-lossy-btn" (click)="sendDataLossy()" title="Send lossy message to this participant">
|
||||
<mat-icon aria-label="Send lossy message button">chat_dashed</mat-icon>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
|
@ -68,6 +83,24 @@
|
|||
}
|
||||
</mat-accordion>
|
||||
</div>
|
||||
<div class="data-tracks-container">
|
||||
@for (track of localDataTracks; track track.info?.sid) {
|
||||
<app-data-track
|
||||
[index]="index"
|
||||
[localDataTrack]="track"
|
||||
[localParticipant]="localParticipant"
|
||||
(trackUnpublished)="onLocalDataTrackUnpublished($event)"
|
||||
(newTrackEvent)="onTrackEvent($event)">
|
||||
</app-data-track>
|
||||
}
|
||||
@for (track of remoteDataTracks; track track.info.sid) {
|
||||
<app-data-track
|
||||
[index]="index"
|
||||
[remoteDataTrack]="track"
|
||||
(newTrackEvent)="onTrackEvent($event)">
|
||||
</app-data-track>
|
||||
}
|
||||
</div>
|
||||
<div class="audio-tracks-container">
|
||||
@for (trackPublication of participant.audioTrackPublications| keyvalue; track trackPublication) {
|
||||
<app-audio-track
|
||||
|
|
|
|||
|
|
@ -10,15 +10,18 @@ import {
|
|||
CreateLocalTracksOptions,
|
||||
DataPacket_Kind,
|
||||
LocalAudioTrack,
|
||||
LocalDataTrack,
|
||||
LocalParticipant,
|
||||
LocalTrack,
|
||||
LocalTrackPublication,
|
||||
LocalVideoTrack,
|
||||
Participant,
|
||||
ParticipantEvent,
|
||||
RemoteDataTrack,
|
||||
RemoteTrack,
|
||||
RemoteTrackPublication,
|
||||
Room,
|
||||
RoomEvent,
|
||||
ScreenShareCaptureOptions,
|
||||
SubscriptionError,
|
||||
Track,
|
||||
|
|
@ -38,13 +41,14 @@ import {
|
|||
import { OptionsDialogComponent } from '../dialogs/options-dialog/options-dialog.component';
|
||||
import { VideoTrackComponent } from '../video-track/video-track.component';
|
||||
import { AudioTrackComponent } from '../audio-track/audio-track.component';
|
||||
import { DataTrackComponent } from '../data-track/data-track.component';
|
||||
import { ParticipantEventCallbacks } from 'node_modules/livekit-client/dist/src/room/participant/Participant';
|
||||
|
||||
@Component({
|
||||
selector: 'app-participant',
|
||||
templateUrl: './participant.component.html',
|
||||
styleUrl: './participant.component.css',
|
||||
imports: [NgClass, KeyValuePipe, MatIconModule, MatTooltipModule, MatExpansionModule, VideoTrackComponent, AudioTrackComponent],
|
||||
imports: [NgClass, KeyValuePipe, MatIconModule, MatTooltipModule, MatExpansionModule, VideoTrackComponent, AudioTrackComponent, DataTrackComponent],
|
||||
})
|
||||
export class ParticipantComponent {
|
||||
@Input()
|
||||
|
|
@ -57,12 +61,20 @@ export class ParticipantComponent {
|
|||
index: number;
|
||||
|
||||
@Output()
|
||||
sendDataToOneParticipant = new EventEmitter<string>();
|
||||
sendReliableDataToOneParticipant = new EventEmitter<string>();
|
||||
|
||||
@Output()
|
||||
sendLossyDataToOneParticipant = new EventEmitter<string>();
|
||||
|
||||
localParticipant: LocalParticipant | undefined;
|
||||
|
||||
events: TestAppEvent[] = [];
|
||||
|
||||
localDataTracks: LocalDataTrack[] = [];
|
||||
remoteDataTracks: RemoteDataTrack[] = [];
|
||||
dataTrackCounter: number = 1;
|
||||
dataTrackName: string = 'data_track_1';
|
||||
|
||||
createLocalTracksOptions: CreateLocalTracksOptions;
|
||||
screenShareCaptureOptions: ScreenShareCaptureOptions = {};
|
||||
trackPublishOptions?: TrackPublishOptions;
|
||||
|
|
@ -88,6 +100,9 @@ export class ParticipantComponent {
|
|||
this.trackPublishOptions = JSON.parse(
|
||||
JSON.stringify(this.room.options.publishDefaults)
|
||||
);
|
||||
if (!this.participant.isLocal) {
|
||||
this.setupDataTrackListeners();
|
||||
}
|
||||
}
|
||||
|
||||
onTrackEvent(event: TestAppEvent) {
|
||||
|
|
@ -95,6 +110,31 @@ export class ParticipantComponent {
|
|||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
async addDataTrack() {
|
||||
const localParticipant = this.participant as LocalParticipant;
|
||||
const track = await localParticipant.publishDataTrack({ name: this.dataTrackName });
|
||||
this.localDataTracks.push(track);
|
||||
this.dataTrackCounter++;
|
||||
this.dataTrackName = 'data_track_' + this.dataTrackCounter;
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
openDataTrackOptionsDialog() {
|
||||
const dialogRef = this.dialog.open(OptionsDialogComponent, {
|
||||
data: { dataTrackName: this.dataTrackName },
|
||||
});
|
||||
dialogRef.afterClosed().subscribe((result) => {
|
||||
if (!!result) {
|
||||
this.dataTrackName = result.dataTrackName;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onLocalDataTrackUnpublished(track: LocalDataTrack) {
|
||||
this.localDataTracks = this.localDataTracks.filter((t) => t !== track);
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
async addVideoTrack() {
|
||||
const options =
|
||||
this.createLocalTracksOptions.video === true
|
||||
|
|
@ -340,7 +380,8 @@ export class ParticipantComponent {
|
|||
.on(
|
||||
ParticipantEvent.DataReceived,
|
||||
(payload: Uint8Array, kind: DataPacket_Kind) => {
|
||||
const decodedPayload = this.decoder.decode(payload);
|
||||
let decodedPayload = this.decoder.decode(payload);
|
||||
decodedPayload += ` (kind: ${DataPacket_Kind[kind]})`;
|
||||
this.updateEventList(
|
||||
ParticipantEvent.DataReceived,
|
||||
'ParticipantEvent',
|
||||
|
|
@ -468,7 +509,32 @@ export class ParticipantComponent {
|
|||
this.testFeedService.pushNewEvent({ user: this.index, event });
|
||||
}
|
||||
|
||||
sendData() {
|
||||
this.sendDataToOneParticipant.emit(this.participant.identity);
|
||||
sendDataReliable() {
|
||||
this.sendReliableDataToOneParticipant.emit(this.participant.identity);
|
||||
}
|
||||
|
||||
sendDataLossy() {
|
||||
this.sendLossyDataToOneParticipant.emit(this.participant.identity);
|
||||
}
|
||||
|
||||
private setupDataTrackListeners() {
|
||||
this.room.on(
|
||||
RoomEvent.DataTrackPublished,
|
||||
(track: RemoteDataTrack) => {
|
||||
if (track.publisherIdentity === this.participant.identity) {
|
||||
this.remoteDataTracks.push(track);
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
}
|
||||
);
|
||||
this.room.on(
|
||||
RoomEvent.DataTrackUnpublished,
|
||||
(sid: string) => {
|
||||
this.remoteDataTracks = this.remoteDataTracks.filter(
|
||||
(t) => t.info.sid !== sid
|
||||
);
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,8 @@ export class TestScenariosComponent implements OnInit, OnDestroy {
|
|||
);
|
||||
const room: Room = user.room;
|
||||
|
||||
room.setMaxListeners(300);
|
||||
|
||||
room.on(RoomEvent.SignalConnected, () => {
|
||||
this.updateEventList(RoomEvent.SignalConnected);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -53,31 +53,21 @@ video {
|
|||
line-height: 16px;
|
||||
}
|
||||
|
||||
/* Keep the form-field visually compact (16×16 clipped box).
|
||||
The CDK overlay uses the Popover API (top layer) so it is
|
||||
immune to overflow:hidden and renders at its natural size. */
|
||||
#max-video-quality {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
overflow: hidden;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Compact the form-field chrome, but exclude the CDK overlay popover
|
||||
(Angular CDK v21 renders it inside the component via the Popover API). */
|
||||
::ng-deep #max-video-quality > :not(.cdk-overlay-popover),
|
||||
::ng-deep #max-video-quality > :not(.cdk-overlay-popover) * {
|
||||
height: 16px !important;
|
||||
width: 8px !important;
|
||||
min-height: 16px !important;
|
||||
min-width: 8px !important;
|
||||
padding: 0 !important;
|
||||
::ng-deep #max-video-quality .mdc-notched-outline * {
|
||||
border-color: transparent !important;
|
||||
}
|
||||
|
||||
/* Let the dropdown panel and its options render at their natural size */
|
||||
::ng-deep #max-video-quality .cdk-overlay-popover,
|
||||
::ng-deep #max-video-quality .cdk-overlay-popover * {
|
||||
width: auto !important;
|
||||
min-width: auto !important;
|
||||
height: auto !important;
|
||||
min-height: auto !important;
|
||||
padding: revert !important;
|
||||
::ng-deep #max-video-quality .mat-mdc-form-field-subscript-wrapper {
|
||||
display: none !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:opsz,wght,FILL,GRAD@24,500,1,-25"/>
|
||||
</head>
|
||||
|
||||
<body class="mat-typography">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
/* You can add global styles to this file, and also import other style files */
|
||||
|
||||
.mat-icon {
|
||||
font-family: "Material Symbols Sharp" !important;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
|
|
@ -8,8 +13,14 @@ body {
|
|||
}
|
||||
|
||||
body {
|
||||
font-family: Roboto, Helvetica Neue Light, Helvetica Neue, Helvetica, Arial,
|
||||
Lucida Grande, sans-serif;
|
||||
font-family:
|
||||
Roboto,
|
||||
Helvetica Neue Light,
|
||||
Helvetica Neue,
|
||||
Helvetica,
|
||||
Arial,
|
||||
Lucida Grande,
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
|
|
@ -94,6 +105,7 @@ app-participant:last-child > .participant-container {
|
|||
button.mat-icon-custom .mat-mdc-button-touch-target {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.top-div {
|
||||
|
|
@ -109,3 +121,13 @@ app-options-dialog .mat-mdc-form-field-infix {
|
|||
.cdk-overlay-pane:has(.mat-mdc-select-panel) {
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
/* Disable mat-select panel CSS transitions/animations so options
|
||||
are immediately clickable (prevents ElementClickInterceptedException
|
||||
in Selenium when mdc-menu-surface intercepts clicks during animation). */
|
||||
.mat-mdc-select-panel.mdc-menu-surface {
|
||||
transition: none !important;
|
||||
animation: none !important;
|
||||
opacity: 1 !important;
|
||||
transform: none !important;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue