mirror of https://github.com/OpenVidu/openvidu.git
Compare commits
28 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
c4cdddd191 | |
|
|
444188d653 | |
|
|
f083ca0cec | |
|
|
fa434d2097 | |
|
|
9a3811d48e | |
|
|
98fc2c2d5b | |
|
|
a492515ce5 | |
|
|
5e31998776 | |
|
|
c43b3e86e3 | |
|
|
755da724b3 | |
|
|
942e5d1062 | |
|
|
483fda785a | |
|
|
617c642215 | |
|
|
83e38ae88a | |
|
|
ed64c3a305 | |
|
|
f4264a2a8a | |
|
|
5edb36670b | |
|
|
7208cb3a65 | |
|
|
6cfa44c4f1 | |
|
|
465403f8cb | |
|
|
b321d5bb69 | |
|
|
81e7400807 | |
|
|
73f84491a5 | |
|
|
59e4a14d15 | |
|
|
8dd058fd50 | |
|
|
4a5afac382 | |
|
|
8336b9e81c | |
|
|
d82d8b061a |
|
|
@ -106,6 +106,7 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
private resizeTimeout: NodeJS.Timeout;
|
private resizeTimeout: NodeJS.Timeout;
|
||||||
private videoIsAtRight: boolean = false;
|
private videoIsAtRight: boolean = false;
|
||||||
private lastLayoutWidth: number = 0;
|
private lastLayoutWidth: number = 0;
|
||||||
|
private lastLayoutHeight: number = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ignore
|
* @ignore
|
||||||
|
|
@ -130,7 +131,9 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
console.log('LayoutComponent.ngAfterViewInit');
|
console.log('LayoutComponent.ngAfterViewInit');
|
||||||
this.layoutService.initialize(this.layoutContainer.element.nativeElement);
|
this.layoutService.initialize(this.layoutContainer.element.nativeElement);
|
||||||
this.lastLayoutWidth = this.layoutContainer.element.nativeElement.getBoundingClientRect().width;
|
const rect = this.layoutContainer.element.nativeElement.getBoundingClientRect();
|
||||||
|
this.lastLayoutWidth = rect.width;
|
||||||
|
this.lastLayoutHeight = rect.height;
|
||||||
this.listenToResizeLayout();
|
this.listenToResizeLayout();
|
||||||
this.listenToCdkDrag();
|
this.listenToCdkDrag();
|
||||||
}
|
}
|
||||||
|
|
@ -217,11 +220,21 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
|
|
||||||
private listenToResizeLayout() {
|
private listenToResizeLayout() {
|
||||||
this.resizeObserver = new ResizeObserver((entries) => {
|
this.resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
const { width: parentWidth, height: parentHeight } = entries[0].contentRect;
|
||||||
|
|
||||||
clearTimeout(this.resizeTimeout);
|
clearTimeout(this.resizeTimeout);
|
||||||
|
|
||||||
this.resizeTimeout = setTimeout(() => {
|
this.resizeTimeout = setTimeout(() => {
|
||||||
|
// Always update layout when container size changes
|
||||||
|
// This ensures layout recalculates when parent containers change
|
||||||
|
const widthDiff = Math.abs(this.lastLayoutWidth - parentWidth);
|
||||||
|
const heightDiff = Math.abs(this.lastLayoutHeight - parentHeight);
|
||||||
|
if (widthDiff > 1 || heightDiff > 1) {
|
||||||
|
this.layoutService.update();
|
||||||
|
this.cd.markForCheck();
|
||||||
|
}
|
||||||
|
// Handle minimized participant positioning
|
||||||
if (this.localParticipant?.isMinimized) {
|
if (this.localParticipant?.isMinimized) {
|
||||||
const { width: parentWidth } = entries[0].contentRect;
|
|
||||||
if (this.panelService.isPanelOpened()) {
|
if (this.panelService.isPanelOpened()) {
|
||||||
if (this.lastLayoutWidth < parentWidth) {
|
if (this.lastLayoutWidth < parentWidth) {
|
||||||
// Layout is bigger than before. Maybe the settings panel(wider) has been transitioned to another panel.
|
// Layout is bigger than before. Maybe the settings panel(wider) has been transitioned to another panel.
|
||||||
|
|
@ -240,8 +253,10 @@ export class LayoutComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
this.moveStreamToRight(parentWidth);
|
this.moveStreamToRight(parentWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.lastLayoutWidth = parentWidth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.lastLayoutWidth = parentWidth;
|
||||||
|
this.lastLayoutHeight = parentHeight;
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,13 @@
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (!isVirtualBackgroundSupported()) {
|
||||||
|
<div class="not-supported-message">
|
||||||
|
<p class="warning-title">{{ 'PANEL.BACKGROUND.NOT_SUPPORTED' | translate }}</p>
|
||||||
|
<p class="warning-description">{{ 'PANEL.BACKGROUND.NOT_SUPPORTED_DESCRIPTION' | translate }}</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="effects-container" fxFlex="100%" fxLayoutAlign="space-evenly none">
|
<div class="effects-container" fxFlex="100%" fxLayoutAlign="space-evenly none">
|
||||||
<div>
|
<div>
|
||||||
<h4 class="background-title">{{ 'PANEL.BACKGROUND.BLURRED_SECTION' | translate }}</h4>
|
<h4 class="background-title">{{ 'PANEL.BACKGROUND.BLURRED_SECTION' | translate }}</h4>
|
||||||
|
|
@ -24,6 +31,7 @@
|
||||||
[class.active-effect-btn]="backgroundSelectedId === effect.id"
|
[class.active-effect-btn]="backgroundSelectedId === effect.id"
|
||||||
(click)="applyBackground(effect)"
|
(click)="applyBackground(effect)"
|
||||||
[attr.id]="effect.id + '-btn'"
|
[attr.id]="effect.id + '-btn'"
|
||||||
|
[disabled]="!isVirtualBackgroundSupported()"
|
||||||
[matTooltip]="
|
[matTooltip]="
|
||||||
effect.type === effectType.NONE
|
effect.type === effectType.NONE
|
||||||
? ('PANEL.BACKGROUND.NO_EFFECTS' | translate)
|
? ('PANEL.BACKGROUND.NO_EFFECTS' | translate)
|
||||||
|
|
@ -44,7 +52,8 @@
|
||||||
class="effect-button"
|
class="effect-button"
|
||||||
[id]="'effect-' + effect.id"
|
[id]="'effect-' + effect.id"
|
||||||
[class.active-effect-btn]="backgroundSelectedId === effect.id"
|
[class.active-effect-btn]="backgroundSelectedId === effect.id"
|
||||||
(click)="applyBackground(effect)"
|
[class.disabled]="!isVirtualBackgroundSupported()"
|
||||||
|
(click)="isVirtualBackgroundSupported() && applyBackground(effect)"
|
||||||
>
|
>
|
||||||
<img [src]="effect.thumbnail" />
|
<img [src]="effect.thumbnail" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,26 @@
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.not-supported-message {
|
||||||
|
padding: 15px;
|
||||||
|
margin: 10px;
|
||||||
|
background-color: var(--ov-warn-color, #ff9800);
|
||||||
|
border-radius: var(--ov-surface-radius);
|
||||||
|
color: var(--ov-text-surface-color);
|
||||||
|
|
||||||
|
.warning-title {
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-description {
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.effects-container {
|
.effects-container {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
@ -33,6 +53,11 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.effect-button.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
.active-effect-btn {
|
.active-effect-btn {
|
||||||
border: 2px solid var(--ov-accent-action-color);
|
border: 2px solid var(--ov-accent-action-color);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, EventEmitter, Input, OnInit, Output, Signal } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { BackgroundEffect, EffectType } from '../../../models/background-effect.model';
|
import { BackgroundEffect, EffectType } from '../../../models/background-effect.model';
|
||||||
import { PanelType } from '../../../models/panel.model';
|
import { PanelType } from '../../../models/panel.model';
|
||||||
|
|
@ -23,7 +23,7 @@ export class BackgroundEffectsPanelComponent implements OnInit {
|
||||||
effectType = EffectType;
|
effectType = EffectType;
|
||||||
backgroundImages: BackgroundEffect[] = [];
|
backgroundImages: BackgroundEffect[] = [];
|
||||||
noEffectAndBlurredBackground: BackgroundEffect[] = [];
|
noEffectAndBlurredBackground: BackgroundEffect[] = [];
|
||||||
private backgrounds: BackgroundEffect[];
|
private backgrounds: BackgroundEffect[] = [];
|
||||||
private backgroundSubs: Subscription;
|
private backgroundSubs: Subscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -38,6 +38,14 @@ export class BackgroundEffectsPanelComponent implements OnInit {
|
||||||
private cd: ChangeDetectorRef
|
private cd: ChangeDetectorRef
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed signal that reactively tracks if virtual background is supported.
|
||||||
|
* Updates automatically when browser support changes.
|
||||||
|
*/
|
||||||
|
readonly isVirtualBackgroundSupported: Signal<boolean> = computed(() =>
|
||||||
|
this.backgroundService.isVirtualBackgroundSupported()
|
||||||
|
);
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.subscribeToBackgroundSelected();
|
this.subscribeToBackgroundSelected();
|
||||||
this.backgrounds = this.backgroundService.getBackgrounds();
|
this.backgrounds = this.backgroundService.getBackgrounds();
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
<div class="prejoin-main">
|
<div class="prejoin-main">
|
||||||
<!-- Video Preview Section -->
|
<!-- Video Preview Section -->
|
||||||
<div class="video-preview-section">
|
<div class="video-preview-section">
|
||||||
<div class="video-preview-container" [@containerResize]="showBackgroundPanel ? 'compact' : 'normal'">
|
<div class="video-preview-container" [class.compact]="showBackgroundPanel">
|
||||||
<div class="video-frame">
|
<div class="video-frame">
|
||||||
<ov-media-element
|
<ov-media-element
|
||||||
[track]="videoTrack"
|
[track]="videoTrack"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,27 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
// CSS Animations (replacing Angular animations)
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.prejoin-container {
|
.prejoin-container {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: var(--ov-background-color);
|
background: var(--ov-background-color);
|
||||||
|
|
@ -89,6 +110,13 @@
|
||||||
border-radius: var(--ov-surface-radius) var(--ov-surface-radius) 0 0;
|
border-radius: var(--ov-surface-radius) var(--ov-surface-radius) 0 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: var(--ov-video-background, var(--ov-primary-action-color));
|
background: var(--ov-video-background, var(--ov-primary-action-color));
|
||||||
|
transition: height 250ms cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||||
|
|
||||||
|
// Compact state when background panel is shown
|
||||||
|
&.compact {
|
||||||
|
height: 300px;
|
||||||
|
aspect-ratio: unset;
|
||||||
|
}
|
||||||
|
|
||||||
.video-frame {
|
.video-frame {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -168,6 +196,11 @@
|
||||||
.vb-container {
|
.vb-container {
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
// Slide-in animation (replacing Angular @slideInOut)
|
||||||
|
&.slide-in {
|
||||||
|
animation: slideIn 300ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration Section
|
// Configuration Section
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,17 @@ import {
|
||||||
OnInit,
|
OnInit,
|
||||||
Output
|
Output
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
import { LocalTrack, Track } from 'livekit-client';
|
||||||
import { filter, Subject, take, takeUntil } from 'rxjs';
|
import { filter, Subject, take, takeUntil } from 'rxjs';
|
||||||
|
import { CustomDevice } from '../../models/device.model';
|
||||||
|
import { LangOption } from '../../models/lang.model';
|
||||||
import { ILogger } from '../../models/logger.model';
|
import { ILogger } from '../../models/logger.model';
|
||||||
import { CdkOverlayService } from '../../services/cdk-overlay/cdk-overlay.service';
|
import { CdkOverlayService } from '../../services/cdk-overlay/cdk-overlay.service';
|
||||||
import { OpenViduComponentsConfigService } from '../../services/config/directive-config.service';
|
import { OpenViduComponentsConfigService } from '../../services/config/directive-config.service';
|
||||||
import { LoggerService } from '../../services/logger/logger.service';
|
import { LoggerService } from '../../services/logger/logger.service';
|
||||||
import { OpenViduService } from '../../services/openvidu/openvidu.service';
|
import { OpenViduService } from '../../services/openvidu/openvidu.service';
|
||||||
import { ViewportService } from '../../services/viewport/viewport.service';
|
|
||||||
import { TranslateService } from '../../services/translate/translate.service';
|
import { TranslateService } from '../../services/translate/translate.service';
|
||||||
import { LocalTrack, Track } from 'livekit-client';
|
import { ViewportService } from '../../services/viewport/viewport.service';
|
||||||
import { CustomDevice } from '../../models/device.model';
|
|
||||||
import { LangOption } from '../../models/lang.model';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
|
@ -30,38 +29,7 @@ import { LangOption } from '../../models/lang.model';
|
||||||
templateUrl: './pre-join.component.html',
|
templateUrl: './pre-join.component.html',
|
||||||
styleUrls: ['./pre-join.component.scss'],
|
styleUrls: ['./pre-join.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
standalone: false,
|
standalone: false
|
||||||
animations: [
|
|
||||||
trigger('containerResize', [
|
|
||||||
state(
|
|
||||||
'normal',
|
|
||||||
style({
|
|
||||||
height: '*'
|
|
||||||
})
|
|
||||||
),
|
|
||||||
state(
|
|
||||||
'compact',
|
|
||||||
style({
|
|
||||||
height: '300px'
|
|
||||||
})
|
|
||||||
),
|
|
||||||
transition('normal => compact', [animate('250ms cubic-bezier(0.25, 0.8, 0.25, 1)')]),
|
|
||||||
transition('compact => normal', [animate('350ms cubic-bezier(0.25, 0.8, 0.25, 1)')])
|
|
||||||
]),
|
|
||||||
trigger('slideInOut', [
|
|
||||||
transition(':enter', [
|
|
||||||
style({
|
|
||||||
opacity: 0
|
|
||||||
}),
|
|
||||||
animate(
|
|
||||||
'300ms cubic-bezier(0.34, 1.56, 0.64, 1)',
|
|
||||||
style({
|
|
||||||
opacity: 1
|
|
||||||
})
|
|
||||||
)
|
|
||||||
])
|
|
||||||
])
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
export class PreJoinComponent implements OnInit, OnDestroy {
|
export class PreJoinComponent implements OnInit, OnDestroy {
|
||||||
@Input() set error(error: { name: string; message: string } | undefined) {
|
@Input() set error(error: { name: string; message: string } | undefined) {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
<div class="audio-device-selector" [class.compact]="compact">
|
<div class="audio-device-selector" [class.compact]="compact">
|
||||||
<!-- Unified Device Button (Compact Mode) -->
|
<!-- Unified Device Button (Compact Mode) -->
|
||||||
@if (compact) {
|
@if (compact) {
|
||||||
@if (hasAudioDevices) {
|
@if (hasAudioDevices()) {
|
||||||
<div class="unified-device-button">
|
<div class="unified-device-button">
|
||||||
<!-- Main toggle button -->
|
<!-- Main toggle button -->
|
||||||
<button
|
<button
|
||||||
mat-flat-button
|
mat-flat-button
|
||||||
class="toggle-section"
|
class="toggle-section"
|
||||||
[disabled]="!hasAudioDevices || microphoneStatusChanging"
|
[disabled]="!hasAudioDevices() || microphoneStatusChanging"
|
||||||
[class.device-enabled]="isMicrophoneEnabled"
|
[class.device-enabled]="isMicrophoneEnabled"
|
||||||
[class.device-disabled]="!isMicrophoneEnabled"
|
[class.device-disabled]="!isMicrophoneEnabled"
|
||||||
(click)="toggleMic($event)"
|
(click)="toggleMic($event)"
|
||||||
[matTooltip]="isMicrophoneEnabled ? ('TOOLBAR.MUTE_AUDIO' | translate) : ('TOOLBAR.UNMUTE_AUDIO' | translate)"
|
[matTooltip]="isMicrophoneEnabled ? ('TOOLBAR.MUTE_AUDIO' | translate) : ('TOOLBAR.UNMUTE_AUDIO' | translate)"
|
||||||
[matTooltipDisabled]="!hasAudioDevices"
|
[matTooltipDisabled]="!hasAudioDevices()"
|
||||||
id="microphone-button"
|
id="microphone-button"
|
||||||
>
|
>
|
||||||
<mat-icon [id]="isMicrophoneEnabled ? 'mic' : 'mic_off'">{{ isMicrophoneEnabled ? 'mic' : 'mic_off' }}</mat-icon>
|
<mat-icon [id]="isMicrophoneEnabled ? 'mic' : 'mic_off'">{{ isMicrophoneEnabled ? 'mic' : 'mic_off' }}</mat-icon>
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
<!-- Normal Mode - Input Style Selector -->
|
<!-- Normal Mode - Input Style Selector -->
|
||||||
<div class="normal-device-selector">
|
<div class="normal-device-selector">
|
||||||
<!-- Input-style Device Selector -->
|
<!-- Input-style Device Selector -->
|
||||||
<div class="device-input-selector" [class.disabled]="!hasAudioDevices || !isMicrophoneEnabled">
|
<div class="device-input-selector" [class.disabled]="!hasAudioDevices() || !isMicrophoneEnabled">
|
||||||
<!-- When microphone is enabled -->
|
<!-- When microphone is enabled -->
|
||||||
@if (isMicrophoneEnabled) {
|
@if (isMicrophoneEnabled) {
|
||||||
<div class="device-input-selector">
|
<div class="device-input-selector">
|
||||||
|
|
@ -50,23 +50,23 @@
|
||||||
mat-flat-button
|
mat-flat-button
|
||||||
id="audio-dropdown"
|
id="audio-dropdown"
|
||||||
class="selector-button"
|
class="selector-button"
|
||||||
[disabled]="microphoneStatusChanging || microphones.length <= 1"
|
[disabled]="microphoneStatusChanging || microphones().length <= 1"
|
||||||
[matMenuTriggerFor]="microphoneMenu"
|
[matMenuTriggerFor]="microphoneMenu"
|
||||||
[attr.aria-expanded]="false"
|
[attr.aria-expanded]="false"
|
||||||
>
|
>
|
||||||
<mat-icon class="device-icon">mic</mat-icon>
|
<mat-icon class="device-icon">mic</mat-icon>
|
||||||
<span class="selected-device-name">{{ microphoneSelected?.label || 'No microphone selected' }}</span>
|
<span class="selected-device-name">{{ microphoneSelected()?.label || 'No microphone selected' }}</span>
|
||||||
<mat-icon class="dropdown-icon" *ngIf="microphones.length > 1">expand_more</mat-icon>
|
<mat-icon class="dropdown-icon" *ngIf="microphones().length > 1">expand_more</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
@if (hasAudioDevices) {
|
@if (hasAudioDevices()) {
|
||||||
<!-- When microphone is disabled -->
|
<!-- When microphone is disabled -->
|
||||||
<div class="device-input-selector disabled">
|
<div class="device-input-selector disabled">
|
||||||
<div class="selector-button disabled">
|
<div class="selector-button disabled">
|
||||||
<mat-icon class="device-icon">mic_off</mat-icon>
|
<mat-icon class="device-icon">mic_off</mat-icon>
|
||||||
<span class="selected-device-name">
|
<span class="selected-device-name">
|
||||||
{{ !hasAudioDevices ? ('PREJOIN.NO_AUDIO_DEVICE' | translate) : 'Microphone disabled' }}
|
{{ !hasAudioDevices() ? ('PREJOIN.NO_AUDIO_DEVICE' | translate) : 'Microphone disabled' }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -84,14 +84,14 @@
|
||||||
|
|
||||||
<!-- Device Selection Menu (Shared) -->
|
<!-- Device Selection Menu (Shared) -->
|
||||||
<mat-menu #microphoneMenu="matMenu" class="device-menu">
|
<mat-menu #microphoneMenu="matMenu" class="device-menu">
|
||||||
@for (microphone of microphones; track microphone.device) {
|
@for (microphone of microphones(); track microphone.device) {
|
||||||
<button
|
<button
|
||||||
mat-menu-item
|
mat-menu-item
|
||||||
id="option-{{ microphone.label }}"
|
id="option-{{ microphone.label }}"
|
||||||
(click)="onMicrophoneSelected({ value: microphone })"
|
(click)="onMicrophoneSelected({ value: microphone })"
|
||||||
[class.selected]="microphone.device === microphoneSelected.device"
|
[class.selected]="microphone.device === microphoneSelected()?.device"
|
||||||
>
|
>
|
||||||
<mat-icon *ngIf="microphone.device === microphoneSelected.device">check</mat-icon>
|
<mat-icon *ngIf="microphone.device === microphoneSelected()?.device">check</mat-icon>
|
||||||
<span>{{ microphone.label }}</span>
|
<span>{{ microphone.label }}</span>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
:host {
|
:host {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
.audio-device-selector {
|
.audio-device-selector {
|
||||||
@include shared.device-selector-base();
|
@include shared.device-selector-base();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
import { Component, effect, EventEmitter, Input, OnInit, Output, Signal, WritableSignal } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
import { CustomDevice } from '../../../models/device.model';
|
import { CustomDevice } from '../../../models/device.model';
|
||||||
|
import { ILogger } from '../../../models/logger.model';
|
||||||
import { DeviceService } from '../../../services/device/device.service';
|
import { DeviceService } from '../../../services/device/device.service';
|
||||||
|
import { LoggerService } from '../../../services/logger/logger.service';
|
||||||
import { ParticipantService } from '../../../services/participant/participant.service';
|
import { ParticipantService } from '../../../services/participant/participant.service';
|
||||||
import { StorageService } from '../../../services/storage/storage.service';
|
import { StorageService } from '../../../services/storage/storage.service';
|
||||||
import { ParticipantModel } from '../../../models/participant.model';
|
|
||||||
import { LoggerService } from '../../../services/logger/logger.service';
|
|
||||||
import { ILogger } from '../../../models/logger.model';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
|
@ -17,19 +15,20 @@ import { ILogger } from '../../../models/logger.model';
|
||||||
styleUrls: ['./audio-devices.component.scss'],
|
styleUrls: ['./audio-devices.component.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class AudioDevicesComponent implements OnInit, OnDestroy {
|
export class AudioDevicesComponent implements OnInit {
|
||||||
@Input() compact: boolean = false;
|
@Input() compact: boolean = false;
|
||||||
@Output() onAudioDeviceChanged = new EventEmitter<CustomDevice>();
|
@Output() onAudioDeviceChanged = new EventEmitter<CustomDevice>();
|
||||||
@Output() onAudioEnabledChanged = new EventEmitter<boolean>();
|
@Output() onAudioEnabledChanged = new EventEmitter<boolean>();
|
||||||
|
|
||||||
microphoneStatusChanging: boolean;
|
microphoneStatusChanging: boolean = false;
|
||||||
hasAudioDevices: boolean;
|
isMicrophoneEnabled: boolean = false;
|
||||||
isMicrophoneEnabled: boolean;
|
|
||||||
microphoneSelected: CustomDevice | undefined;
|
|
||||||
microphones: CustomDevice[] = [];
|
|
||||||
private localParticipantSubscription: Subscription;
|
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
|
|
||||||
|
// Expose signals directly from service (reactive)
|
||||||
|
protected readonly microphones: WritableSignal<CustomDevice[]>;
|
||||||
|
protected readonly microphoneSelected: WritableSignal<CustomDevice | undefined>;
|
||||||
|
protected readonly hasAudioDevices: Signal<boolean>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private deviceSrv: DeviceService,
|
private deviceSrv: DeviceService,
|
||||||
private storageSrv: StorageService,
|
private storageSrv: StorageService,
|
||||||
|
|
@ -37,24 +36,24 @@ export class AudioDevicesComponent implements OnInit, OnDestroy {
|
||||||
private loggerSrv: LoggerService
|
private loggerSrv: LoggerService
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerSrv.get('AudioDevicesComponent');
|
this.log = this.loggerSrv.get('AudioDevicesComponent');
|
||||||
|
this.microphones = this.deviceSrv.microphones;
|
||||||
|
this.microphoneSelected = this.deviceSrv.microphoneSelected;
|
||||||
|
this.hasAudioDevices = this.deviceSrv.hasAudioDevices;
|
||||||
|
|
||||||
|
// Use effect instead of subscription for reactive updates
|
||||||
|
effect(() => {
|
||||||
|
const participant = this.participantService.localParticipantSignal();
|
||||||
|
if (participant) {
|
||||||
|
this.isMicrophoneEnabled = participant.isMicrophoneEnabled;
|
||||||
|
this.storageSrv.setMicrophoneEnabled(this.isMicrophoneEnabled);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.subscribeToParticipantMediaProperties();
|
|
||||||
this.hasAudioDevices = this.deviceSrv.hasAudioDeviceAvailable();
|
|
||||||
if (this.hasAudioDevices) {
|
|
||||||
this.microphones = this.deviceSrv.getMicrophones();
|
|
||||||
this.microphoneSelected = this.deviceSrv.getMicrophoneSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isMicrophoneEnabled = this.participantService.isMyMicrophoneEnabled();
|
this.isMicrophoneEnabled = this.participantService.isMyMicrophoneEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.microphones = [];
|
|
||||||
if (this.localParticipantSubscription) this.localParticipantSubscription.unsubscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
async toggleMic(event: any) {
|
async toggleMic(event: any) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
this.microphoneStatusChanging = true;
|
this.microphoneStatusChanging = true;
|
||||||
|
|
@ -72,8 +71,7 @@ export class AudioDevicesComponent implements OnInit, OnDestroy {
|
||||||
this.microphoneStatusChanging = true;
|
this.microphoneStatusChanging = true;
|
||||||
await this.participantService.switchMicrophone(device.device);
|
await this.participantService.switchMicrophone(device.device);
|
||||||
this.deviceSrv.setMicSelected(device.device);
|
this.deviceSrv.setMicSelected(device.device);
|
||||||
this.microphoneSelected = this.deviceSrv.getMicrophoneSelected();
|
this.onAudioDeviceChanged.emit(this.microphoneSelected());
|
||||||
this.onAudioDeviceChanged.emit(this.microphoneSelected);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.log.e('Error switching microphone', error);
|
this.log.e('Error switching microphone', error);
|
||||||
|
|
@ -89,17 +87,4 @@ export class AudioDevicesComponent implements OnInit, OnDestroy {
|
||||||
compareObjectDevices(o1: CustomDevice, o2: CustomDevice): boolean {
|
compareObjectDevices(o1: CustomDevice, o2: CustomDevice): boolean {
|
||||||
return o1.label === o2.label;
|
return o1.label === o2.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This subscription is necessary to update the microphone status when the user changes it from toolbar and
|
|
||||||
* the settings panel is opened. With this, the microphone status is updated in the settings panel.
|
|
||||||
*/
|
|
||||||
private subscribeToParticipantMediaProperties() {
|
|
||||||
this.localParticipantSubscription = this.participantService.localParticipant$.subscribe((p: ParticipantModel | undefined) => {
|
|
||||||
if (p) {
|
|
||||||
this.isMicrophoneEnabled = p.isMicrophoneEnabled;
|
|
||||||
this.storageSrv.setMicrophoneEnabled(this.isMicrophoneEnabled);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -179,13 +179,14 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
background: rgba(255, 193, 7, 0.1);
|
background: var(--ov-primary-action-color);
|
||||||
border: 1px solid rgba(255, 193, 7, 0.3);
|
border: 1px solid var(--ov-warning-color, #ff9800);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: var(--ov-warning-color, #ff9800);
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
color: var(--ov-text-primary-color);
|
||||||
|
|
||||||
.warning-icon {
|
.warning-icon {
|
||||||
|
color: var(--ov-warning-color, #ff9800);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
<div class="video-device-selector" [class.compact]="compact">
|
<div class="video-device-selector" [class.compact]="compact">
|
||||||
<!-- Unified Device Button (Compact Mode) -->
|
<!-- Unified Device Button (Compact Mode) -->
|
||||||
@if (compact) {
|
@if (compact) {
|
||||||
@if (hasVideoDevices) {
|
@if (hasVideoDevices()) {
|
||||||
<div class="unified-device-button">
|
<div class="unified-device-button">
|
||||||
<!-- Main toggle button -->
|
<!-- Main toggle button -->
|
||||||
<button
|
<button
|
||||||
mat-flat-button
|
mat-flat-button
|
||||||
class="toggle-section"
|
class="toggle-section"
|
||||||
[disabled]="!hasVideoDevices || cameraStatusChanging"
|
[disabled]="!hasVideoDevices() || cameraStatusChanging"
|
||||||
[class.device-enabled]="isCameraEnabled"
|
[class.device-enabled]="isCameraEnabled"
|
||||||
[class.device-disabled]="!isCameraEnabled"
|
[class.device-disabled]="!isCameraEnabled"
|
||||||
(click)="toggleCam($event)"
|
(click)="toggleCam($event)"
|
||||||
[matTooltip]="isCameraEnabled ? ('TOOLBAR.STOP_VIDEO' | translate) : ('TOOLBAR.START_VIDEO' | translate)"
|
[matTooltip]="isCameraEnabled ? ('TOOLBAR.STOP_VIDEO' | translate) : ('TOOLBAR.START_VIDEO' | translate)"
|
||||||
[matTooltipDisabled]="!hasVideoDevices"
|
[matTooltipDisabled]="!hasVideoDevices()"
|
||||||
id="camera-button"
|
id="camera-button"
|
||||||
>
|
>
|
||||||
<mat-icon [id]="isCameraEnabled ? 'videocam' : 'videocam_off'">
|
<mat-icon [id]="isCameraEnabled ? 'videocam' : 'videocam_off'">
|
||||||
|
|
@ -51,15 +51,15 @@
|
||||||
id="video-dropdown"
|
id="video-dropdown"
|
||||||
class="selector-button"
|
class="selector-button"
|
||||||
[matMenuTriggerFor]="cameraMenu"
|
[matMenuTriggerFor]="cameraMenu"
|
||||||
[disabled]="cameraStatusChanging || cameras.length <= 1"
|
[disabled]="cameraStatusChanging || cameras().length <= 1"
|
||||||
>
|
>
|
||||||
<mat-icon class="device-icon">videocam</mat-icon>
|
<mat-icon class="device-icon">videocam</mat-icon>
|
||||||
<span class="selected-device-name">{{ cameraSelected?.label || 'No camera selected' }}</span>
|
<span class="selected-device-name">{{ cameraSelected()?.label || 'No camera selected' }}</span>
|
||||||
<mat-icon class="dropdown-icon" *ngIf="cameras.length > 1">expand_more</mat-icon>
|
<mat-icon class="dropdown-icon" *ngIf="cameras().length > 1">expand_more</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
@if (hasVideoDevices) {
|
@if (hasVideoDevices()) {
|
||||||
<!-- Disabled state message -->
|
<!-- Disabled state message -->
|
||||||
<div class="device-input-selector disabled">
|
<div class="device-input-selector disabled">
|
||||||
<div class="selector-button disabled">
|
<div class="selector-button disabled">
|
||||||
|
|
@ -80,14 +80,14 @@
|
||||||
|
|
||||||
<!-- Device Selection Menu (Shared) -->
|
<!-- Device Selection Menu (Shared) -->
|
||||||
<mat-menu #cameraMenu="matMenu" class="device-menu">
|
<mat-menu #cameraMenu="matMenu" class="device-menu">
|
||||||
@for (camera of cameras; track camera.device) {
|
@for (camera of cameras(); track camera.device) {
|
||||||
<button
|
<button
|
||||||
mat-menu-item
|
mat-menu-item
|
||||||
id="option-{{ camera.label }}"
|
id="option-{{ camera.label }}"
|
||||||
(click)="onCameraSelected({ value: camera })"
|
(click)="onCameraSelected({ value: camera })"
|
||||||
[class.selected]="camera.device === cameraSelected?.device"
|
[class.selected]="camera.device === cameraSelected()?.device"
|
||||||
>
|
>
|
||||||
<mat-icon *ngIf="camera.device === cameraSelected?.device" class="check-icon">check</mat-icon>
|
<mat-icon *ngIf="camera.device === cameraSelected()?.device" class="check-icon">check</mat-icon>
|
||||||
<span>{{ camera.label }}</span>
|
<span>{{ camera.label }}</span>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
:host {
|
:host {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
.video-device-selector {
|
.video-device-selector {
|
||||||
@include shared.device-selector-base();
|
@include shared.device-selector-base();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
import { Component, effect, EventEmitter, Input, OnInit, Output, Signal, WritableSignal } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
import { CustomDevice } from '../../../models/device.model';
|
import { CustomDevice } from '../../../models/device.model';
|
||||||
|
import { ILogger } from '../../../models/logger.model';
|
||||||
import { DeviceService } from '../../../services/device/device.service';
|
import { DeviceService } from '../../../services/device/device.service';
|
||||||
|
import { LoggerService } from '../../../services/logger/logger.service';
|
||||||
import { ParticipantService } from '../../../services/participant/participant.service';
|
import { ParticipantService } from '../../../services/participant/participant.service';
|
||||||
import { StorageService } from '../../../services/storage/storage.service';
|
import { StorageService } from '../../../services/storage/storage.service';
|
||||||
import { ParticipantModel } from '../../../models/participant.model';
|
|
||||||
import { LoggerService } from '../../../services/logger/logger.service';
|
|
||||||
import { ILogger } from '../../../models/logger.model';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
|
@ -17,18 +15,18 @@ import { ILogger } from '../../../models/logger.model';
|
||||||
styleUrls: ['./video-devices.component.scss'],
|
styleUrls: ['./video-devices.component.scss'],
|
||||||
standalone: false
|
standalone: false
|
||||||
})
|
})
|
||||||
export class VideoDevicesComponent implements OnInit, OnDestroy {
|
export class VideoDevicesComponent implements OnInit {
|
||||||
@Input() compact: boolean = false;
|
@Input() compact: boolean = false;
|
||||||
@Output() onVideoDeviceChanged = new EventEmitter<CustomDevice>();
|
@Output() onVideoDeviceChanged = new EventEmitter<CustomDevice>();
|
||||||
@Output() onVideoEnabledChanged = new EventEmitter<boolean>();
|
@Output() onVideoEnabledChanged = new EventEmitter<boolean>();
|
||||||
@Output() onVideoDevicesLoaded = new EventEmitter<CustomDevice[]>();
|
@Output() onVideoDevicesLoaded = new EventEmitter<CustomDevice[]>();
|
||||||
|
|
||||||
cameraStatusChanging: boolean;
|
cameraStatusChanging: boolean = false;
|
||||||
isCameraEnabled: boolean;
|
isCameraEnabled: boolean = false;
|
||||||
cameraSelected: CustomDevice | undefined;
|
|
||||||
hasVideoDevices: boolean;
|
protected readonly cameras: WritableSignal<CustomDevice[]>;
|
||||||
cameras: CustomDevice[] = [];
|
protected readonly cameraSelected: WritableSignal<CustomDevice | undefined>;
|
||||||
localParticipantSubscription: Subscription;
|
protected readonly hasVideoDevices: Signal<boolean>;
|
||||||
|
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
|
|
||||||
|
|
@ -39,26 +37,26 @@ export class VideoDevicesComponent implements OnInit, OnDestroy {
|
||||||
private loggerSrv: LoggerService
|
private loggerSrv: LoggerService
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerSrv.get('VideoDevicesComponent');
|
this.log = this.loggerSrv.get('VideoDevicesComponent');
|
||||||
|
this.cameras = this.deviceSrv.cameras;
|
||||||
|
this.cameraSelected = this.deviceSrv.cameraSelected;
|
||||||
|
this.hasVideoDevices = this.deviceSrv.hasVideoDevices;
|
||||||
|
|
||||||
|
// Use effect instead of subscription for reactive updates
|
||||||
|
effect(() => {
|
||||||
|
const participant = this.participantService.localParticipantSignal();
|
||||||
|
if (participant) {
|
||||||
|
this.isCameraEnabled = participant.isCameraEnabled;
|
||||||
|
this.storageSrv.setCameraEnabled(this.isCameraEnabled);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.subscribeToParticipantMediaProperties();
|
// Emit initial device list (reactively)
|
||||||
|
this.onVideoDevicesLoaded.emit(this.cameras());
|
||||||
this.hasVideoDevices = this.deviceSrv.hasVideoDeviceAvailable();
|
|
||||||
if (this.hasVideoDevices) {
|
|
||||||
this.cameras = this.deviceSrv.getCameras();
|
|
||||||
this.cameraSelected = this.deviceSrv.getCameraSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onVideoDevicesLoaded.emit(this.cameras);
|
|
||||||
this.isCameraEnabled = this.participantService.isMyCameraEnabled();
|
this.isCameraEnabled = this.participantService.isMyCameraEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnDestroy() {
|
|
||||||
this.cameras = [];
|
|
||||||
if (this.localParticipantSubscription) this.localParticipantSubscription.unsubscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
async toggleCam(event: any) {
|
async toggleCam(event: any) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
this.cameraStatusChanging = true;
|
this.cameraStatusChanging = true;
|
||||||
|
|
@ -75,14 +73,10 @@ export class VideoDevicesComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
// Is New deviceId different from the old one?
|
// Is New deviceId different from the old one?
|
||||||
if (this.deviceSrv.needUpdateVideoTrack(device)) {
|
if (this.deviceSrv.needUpdateVideoTrack(device)) {
|
||||||
|
|
||||||
this.cameraStatusChanging = true;
|
this.cameraStatusChanging = true;
|
||||||
|
|
||||||
await this.participantService.switchCamera(device.device);
|
await this.participantService.switchCamera(device.device);
|
||||||
|
|
||||||
this.deviceSrv.setCameraSelected(device.device);
|
this.deviceSrv.setCameraSelected(device.device);
|
||||||
this.cameraSelected = device;
|
this.onVideoDeviceChanged.emit(this.cameraSelected());
|
||||||
this.onVideoDeviceChanged.emit(this.cameraSelected);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.log.e('Error switching camera', error);
|
this.log.e('Error switching camera', error);
|
||||||
|
|
@ -98,17 +92,4 @@ export class VideoDevicesComponent implements OnInit, OnDestroy {
|
||||||
compareObjectDevices(o1: CustomDevice, o2: CustomDevice): boolean {
|
compareObjectDevices(o1: CustomDevice, o2: CustomDevice): boolean {
|
||||||
return o1.label === o2.label;
|
return o1.label === o2.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This subscription is necessary to update the camera status when the user changes it from toolbar and
|
|
||||||
* the settings panel is opened. With this, the camera status is updated in the settings panel.
|
|
||||||
*/
|
|
||||||
private subscribeToParticipantMediaProperties() {
|
|
||||||
this.localParticipantSubscription = this.participantService.localParticipant$.subscribe((p: ParticipantModel | undefined) => {
|
|
||||||
if (p) {
|
|
||||||
this.isCameraEnabled = p.isCameraEnabled;
|
|
||||||
this.storageSrv.setCameraEnabled(this.isCameraEnabled);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -436,7 +436,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
private panelService: PanelService,
|
private panelService: PanelService,
|
||||||
private participantService: ParticipantService,
|
private participantService: ParticipantService,
|
||||||
private openviduService: OpenViduService,
|
private openviduService: OpenViduService,
|
||||||
private oVDevicesService: DeviceService,
|
private deviceService: DeviceService,
|
||||||
private actionService: ActionService,
|
private actionService: ActionService,
|
||||||
private loggerSrv: LoggerService,
|
private loggerSrv: LoggerService,
|
||||||
private cd: ChangeDetectorRef,
|
private cd: ChangeDetectorRef,
|
||||||
|
|
@ -517,8 +517,8 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
this.room = this.openviduService.getRoom();
|
this.room = this.openviduService.getRoom();
|
||||||
this.evalAndSetRoomName(this.libService.getRoomName());
|
this.evalAndSetRoomName(this.libService.getRoomName());
|
||||||
|
|
||||||
this.hasVideoDevices = this.oVDevicesService.hasVideoDeviceAvailable();
|
this.hasVideoDevices = this.deviceService.hasVideoDeviceAvailable();
|
||||||
this.hasAudioDevices = this.oVDevicesService.hasAudioDeviceAvailable();
|
this.hasAudioDevices = this.deviceService.hasAudioDeviceAvailable();
|
||||||
|
|
||||||
this.setupTemplates();
|
this.setupTemplates();
|
||||||
this.subscribeToToolbarDirectives();
|
this.subscribeToToolbarDirectives();
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,14 @@
|
||||||
<mat-icon class="error-icon">error</mat-icon>
|
<mat-icon class="error-icon">error</mat-icon>
|
||||||
<span>{{ componentState.error?.message }}</span>
|
<span>{{ componentState.error?.message }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
} @else if (componentState.state === 'DISCONNECTED') {
|
||||||
|
<!-- Disconnected state -->
|
||||||
|
|
||||||
|
<div id="spinner">
|
||||||
|
<mat-icon class="info-icon">check_circle</mat-icon>
|
||||||
|
<span>{{ 'ROOM.DISCONNECTED' | translate }}</span>
|
||||||
|
<p class="subtitle">{{ 'ROOM.DISCONNECTED_SUBTITLE' | translate }}</p>
|
||||||
|
</div>
|
||||||
} @else if (componentState.isRoomReady) {
|
} @else if (componentState.isRoomReady) {
|
||||||
<!-- VideoConference -->
|
<!-- VideoConference -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import { animate, style, transition, trigger } from '@angular/animations';
|
import { animate, style, transition, trigger } from '@angular/animations';
|
||||||
import {
|
import {
|
||||||
AfterViewInit,
|
AfterViewInit,
|
||||||
ChangeDetectionStrategy,
|
|
||||||
ChangeDetectorRef,
|
|
||||||
Component,
|
Component,
|
||||||
ContentChild,
|
ContentChild,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
|
|
@ -11,7 +9,16 @@ import {
|
||||||
TemplateRef,
|
TemplateRef,
|
||||||
ViewChild
|
ViewChild
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
import { Room } from 'livekit-client';
|
||||||
import { Subject, filter, skip, take, takeUntil } from 'rxjs';
|
import { Subject, filter, skip, take, takeUntil } from 'rxjs';
|
||||||
|
import {
|
||||||
|
LayoutAdditionalElementsDirective,
|
||||||
|
LeaveButtonDirective,
|
||||||
|
ParticipantPanelAfterLocalParticipantDirective,
|
||||||
|
PreJoinDirective,
|
||||||
|
SettingsPanelGeneralAdditionalElementsDirective,
|
||||||
|
ToolbarMoreOptionsAdditionalMenuItemsDirective
|
||||||
|
} from '../../directives/template/internals.directive';
|
||||||
import {
|
import {
|
||||||
ActivitiesPanelDirective,
|
ActivitiesPanelDirective,
|
||||||
AdditionalPanelsDirective,
|
AdditionalPanelsDirective,
|
||||||
|
|
@ -26,29 +33,17 @@ import {
|
||||||
ToolbarAdditionalPanelButtonsDirective,
|
ToolbarAdditionalPanelButtonsDirective,
|
||||||
ToolbarDirective
|
ToolbarDirective
|
||||||
} from '../../directives/template/openvidu-components-angular.directive';
|
} from '../../directives/template/openvidu-components-angular.directive';
|
||||||
import { ILogger } from '../../models/logger.model';
|
import { BroadcastingStartRequestedEvent, BroadcastingStopRequestedEvent } from '../../models/broadcasting.model';
|
||||||
import { VideoconferenceState, VideoconferenceStateInfo } from '../../models/videoconference-state.model';
|
|
||||||
import { ActionService } from '../../services/action/action.service';
|
|
||||||
import { OpenViduComponentsConfigService } from '../../services/config/directive-config.service';
|
|
||||||
import { DeviceService } from '../../services/device/device.service';
|
|
||||||
import { LoggerService } from '../../services/logger/logger.service';
|
|
||||||
import { OpenViduService } from '../../services/openvidu/openvidu.service';
|
|
||||||
import { StorageService } from '../../services/storage/storage.service';
|
|
||||||
import {
|
|
||||||
TemplateManagerService,
|
|
||||||
TemplateConfiguration,
|
|
||||||
ExternalDirectives,
|
|
||||||
DefaultTemplates
|
|
||||||
} from '../../services/template/template-manager.service';
|
|
||||||
import { Room } from 'livekit-client';
|
|
||||||
import { ParticipantLeftEvent, ParticipantModel } from '../../models/participant.model';
|
|
||||||
import { CustomDevice } from '../../models/device.model';
|
import { CustomDevice } from '../../models/device.model';
|
||||||
|
import { LangOption } from '../../models/lang.model';
|
||||||
|
import { ILogger } from '../../models/logger.model';
|
||||||
import {
|
import {
|
||||||
ActivitiesPanelStatusEvent,
|
ActivitiesPanelStatusEvent,
|
||||||
ChatPanelStatusEvent,
|
ChatPanelStatusEvent,
|
||||||
ParticipantsPanelStatusEvent,
|
ParticipantsPanelStatusEvent,
|
||||||
SettingsPanelStatusEvent
|
SettingsPanelStatusEvent
|
||||||
} from '../../models/panel.model';
|
} from '../../models/panel.model';
|
||||||
|
import { ParticipantLeftEvent, ParticipantModel } from '../../models/participant.model';
|
||||||
import {
|
import {
|
||||||
RecordingDeleteRequestedEvent,
|
RecordingDeleteRequestedEvent,
|
||||||
RecordingDownloadClickedEvent,
|
RecordingDownloadClickedEvent,
|
||||||
|
|
@ -56,18 +51,21 @@ import {
|
||||||
RecordingStartRequestedEvent,
|
RecordingStartRequestedEvent,
|
||||||
RecordingStopRequestedEvent
|
RecordingStopRequestedEvent
|
||||||
} from '../../models/recording.model';
|
} from '../../models/recording.model';
|
||||||
import { BroadcastingStartRequestedEvent, BroadcastingStopRequestedEvent } from '../../models/broadcasting.model';
|
import { VideoconferenceState, VideoconferenceStateInfo } from '../../models/videoconference-state.model';
|
||||||
import { LangOption } from '../../models/lang.model';
|
import { ActionService } from '../../services/action/action.service';
|
||||||
import {
|
import { OpenViduComponentsConfigService } from '../../services/config/directive-config.service';
|
||||||
LayoutAdditionalElementsDirective,
|
import { DeviceService } from '../../services/device/device.service';
|
||||||
ParticipantPanelAfterLocalParticipantDirective,
|
|
||||||
PreJoinDirective,
|
|
||||||
LeaveButtonDirective,
|
|
||||||
SettingsPanelGeneralAdditionalElementsDirective,
|
|
||||||
ToolbarMoreOptionsAdditionalMenuItemsDirective
|
|
||||||
} from '../../directives/template/internals.directive';
|
|
||||||
import { OpenViduThemeService } from '../../services/theme/theme.service';
|
|
||||||
import { E2eeService } from '../../services/e2ee/e2ee.service';
|
import { E2eeService } from '../../services/e2ee/e2ee.service';
|
||||||
|
import { LoggerService } from '../../services/logger/logger.service';
|
||||||
|
import { OpenViduService } from '../../services/openvidu/openvidu.service';
|
||||||
|
import { StorageService } from '../../services/storage/storage.service';
|
||||||
|
import {
|
||||||
|
DefaultTemplates,
|
||||||
|
ExternalDirectives,
|
||||||
|
TemplateConfiguration,
|
||||||
|
TemplateManagerService
|
||||||
|
} from '../../services/template/template-manager.service';
|
||||||
|
import { OpenViduThemeService } from '../../services/theme/theme.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The **VideoconferenceComponent** is the parent of all OpenVidu components.
|
* The **VideoconferenceComponent** is the parent of all OpenVidu components.
|
||||||
|
|
@ -982,14 +980,16 @@ export class VideoconferenceComponent implements OnDestroy, AfterViewInit {
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
_onParticipantLeft(event: ParticipantLeftEvent) {
|
_onParticipantLeft(event: ParticipantLeftEvent) {
|
||||||
// Reset to disconnected state to allow prejoin to show again if needed
|
this.onParticipantLeft.emit(event);
|
||||||
|
|
||||||
|
// Reset to disconnected state
|
||||||
|
// Set showPrejoin to false to prevent prejoin from showing and creating tracks
|
||||||
|
// This avoids the race condition where tracks are created before navigation
|
||||||
this.updateComponentState({
|
this.updateComponentState({
|
||||||
state: VideoconferenceState.DISCONNECTED,
|
state: VideoconferenceState.DISCONNECTED,
|
||||||
isRoomReady: false,
|
isRoomReady: false,
|
||||||
showPrejoin: this.libService.showPrejoin()
|
showPrejoin: false
|
||||||
});
|
});
|
||||||
|
|
||||||
this.onParticipantLeft.emit(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private subscribeToVideconferenceDirectives() {
|
private subscribeToVideconferenceDirectives() {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "正在加入房间...",
|
"JOINING": "正在加入房间...",
|
||||||
"LANDSCAPE_WARNING": "请将设备旋转到纵向以获得最佳体验"
|
"LANDSCAPE_WARNING": "请将设备旋转到纵向以获得最佳体验",
|
||||||
|
"DISCONNECTED": "您已离开房间",
|
||||||
|
"DISCONNECTED_SUBTITLE": "会话已结束"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "设置你的绰号",
|
"NICKNAME_SECTION": "设置你的绰号",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "没有效果和模糊的背景",
|
"BLURRED_SECTION": "没有效果和模糊的背景",
|
||||||
"NO_EFFECTS": "没有背景效果",
|
"NO_EFFECTS": "没有背景效果",
|
||||||
"BLURRED_EFFECT": "模糊的背景",
|
"BLURRED_EFFECT": "模糊的背景",
|
||||||
"IMAGES_SECTION": "背景图像"
|
"IMAGES_SECTION": "背景图像",
|
||||||
|
"NOT_SUPPORTED": "此浏览器不支持虚拟背景",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "您的浏览器不支持背景效果。此功能需要 GPU 加速,可能已被禁用或不可用。"
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "录音",
|
"TITLE": "录音",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "Raum beitreten...",
|
"JOINING": "Raum beitreten...",
|
||||||
"LANDSCAPE_WARNING": "Bitte drehen Sie Ihr Gerät für eine bessere Erfahrung in den Hochformatmodus"
|
"LANDSCAPE_WARNING": "Bitte drehen Sie Ihr Gerät für eine bessere Erfahrung in den Hochformatmodus",
|
||||||
|
"DISCONNECTED": "Sie haben den Raum verlassen",
|
||||||
|
"DISCONNECTED_SUBTITLE": "Die Sitzung wurde beendet"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "Legen Sie Ihren Spitznamen fest",
|
"NICKNAME_SECTION": "Legen Sie Ihren Spitznamen fest",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "Keine Effekte und unscharfer Hintergrund",
|
"BLURRED_SECTION": "Keine Effekte und unscharfer Hintergrund",
|
||||||
"NO_EFFECTS": "Kein Hintergrundeffekt",
|
"NO_EFFECTS": "Kein Hintergrundeffekt",
|
||||||
"BLURRED_EFFECT": "Unscharfer Hintergrund",
|
"BLURRED_EFFECT": "Unscharfer Hintergrund",
|
||||||
"IMAGES_SECTION": "Hintergrundbilder"
|
"IMAGES_SECTION": "Hintergrundbilder",
|
||||||
|
"NOT_SUPPORTED": "Virtuelle Hintergründe werden in diesem Browser nicht unterstützt",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "Ihr Browser unterstützt keine Hintergrundeffekte. Diese Funktion erfordert GPU-Beschleunigung, die möglicherweise deaktiviert oder nicht verfügbar ist."
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "Aufnahme",
|
"TITLE": "Aufnahme",
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "Joining room...",
|
"JOINING": "Joining room...",
|
||||||
"LANDSCAPE_WARNING": "Please rotate your device to portrait for a better experience"
|
"LANDSCAPE_WARNING": "Please rotate your device to portrait for a better experience",
|
||||||
|
"DISCONNECTED": "You have left the room",
|
||||||
|
"DISCONNECTED_SUBTITLE": "The session has ended"
|
||||||
},
|
},
|
||||||
"TOOLBAR": {
|
"TOOLBAR": {
|
||||||
"MUTE_AUDIO": "Mute your audio",
|
"MUTE_AUDIO": "Mute your audio",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "No effects and blurred background",
|
"BLURRED_SECTION": "No effects and blurred background",
|
||||||
"NO_EFFECTS": "No background effect",
|
"NO_EFFECTS": "No background effect",
|
||||||
"BLURRED_EFFECT": "Blurred background",
|
"BLURRED_EFFECT": "Blurred background",
|
||||||
"IMAGES_SECTION": "Background images"
|
"IMAGES_SECTION": "Background images",
|
||||||
|
"NOT_SUPPORTED": "Virtual backgrounds are not supported in this browser",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "Your browser does not support background effects. This feature requires GPU acceleration which may be disabled or unavailable."
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "Recording",
|
"TITLE": "Recording",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "Uniéndose a la sala...",
|
"JOINING": "Uniéndose a la sala...",
|
||||||
"LANDSCAPE_WARNING": "Por favor, gira tu dispositivo a modo retrato para una mejor experiencia"
|
"LANDSCAPE_WARNING": "Por favor, gira tu dispositivo a modo retrato para una mejor experiencia",
|
||||||
|
"DISCONNECTED": "Has salido de la sala",
|
||||||
|
"DISCONNECTED_SUBTITLE": "La sesión ha finalizado"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "Elige tu nombre",
|
"NICKNAME_SECTION": "Elige tu nombre",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "Sin efectos y fondo desenfocado",
|
"BLURRED_SECTION": "Sin efectos y fondo desenfocado",
|
||||||
"NO_EFFECTS": "Sin efecto",
|
"NO_EFFECTS": "Sin efecto",
|
||||||
"BLURRED_EFFECT": "Fondo desenfocado",
|
"BLURRED_EFFECT": "Fondo desenfocado",
|
||||||
"IMAGES_SECTION": "Imágenes de fondo"
|
"IMAGES_SECTION": "Imágenes de fondo",
|
||||||
|
"NOT_SUPPORTED": "Los efectos de fondo virtuales no son compatibles con este navegador",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "Tu navegador no admite efectos de fondo. Esta función requiere aceleración GPU que puede estar deshabilitada o no disponible."
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "Grabación",
|
"TITLE": "Grabación",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "Rejoindre la salle...",
|
"JOINING": "Rejoindre la salle...",
|
||||||
"LANDSCAPE_WARNING": "Veuillez faire pivoter votre appareil en mode portrait pour une meilleure expérience"
|
"LANDSCAPE_WARNING": "Veuillez faire pivoter votre appareil en mode portrait pour une meilleure expérience",
|
||||||
|
"DISCONNECTED": "Vous avez quitté la salle",
|
||||||
|
"DISCONNECTED_SUBTITLE": "La session est terminée"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "Définir votre surnom",
|
"NICKNAME_SECTION": "Définir votre surnom",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "Aucun effet et arrière-plan flou",
|
"BLURRED_SECTION": "Aucun effet et arrière-plan flou",
|
||||||
"NO_EFFECTS": "Aucun effet de fond",
|
"NO_EFFECTS": "Aucun effet de fond",
|
||||||
"BLURRED_EFFECT": "Arrière-plan flou",
|
"BLURRED_EFFECT": "Arrière-plan flou",
|
||||||
"IMAGES_SECTION": "Images d'arrière-plan"
|
"IMAGES_SECTION": "Images d'arrière-plan",
|
||||||
|
"NOT_SUPPORTED": "Les arrière-plans virtuels ne sont pas pris en charge dans ce navigateur",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "Votre navigateur ne prend pas en charge les effets d'arrière-plan. Cette fonctionnalité nécessite l'accélération GPU qui peut être désactivée ou non disponible."
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "Enregistrement",
|
"TITLE": "Enregistrement",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "कक्ष में शामिल हो रहा है...",
|
"JOINING": "कक्ष में शामिल हो रहा है...",
|
||||||
"LANDSCAPE_WARNING": "कृपया बेहतर अनुभव के लिए अपने डिवाइस को पोर्ट्रेट मोड में घुमाएँ"
|
"LANDSCAPE_WARNING": "कृपया बेहतर अनुभव के लिए अपने डिवाइस को पोर्ट्रेट मोड में घुमाएं",
|
||||||
|
"DISCONNECTED": "आपने कमरा छोड़ दिया है",
|
||||||
|
"DISCONNECTED_SUBTITLE": "सत्र समाप्त हो गया है"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "अपना निकनेम सेट करें",
|
"NICKNAME_SECTION": "अपना निकनेम सेट करें",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "कोई प्रभाव नहीं है और पृष्ठभूमि धुंधली है",
|
"BLURRED_SECTION": "कोई प्रभाव नहीं है और पृष्ठभूमि धुंधली है",
|
||||||
"NO_EFFECTS": "कोई पृष्ठभूमि प्रभाव नहीं है",
|
"NO_EFFECTS": "कोई पृष्ठभूमि प्रभाव नहीं है",
|
||||||
"BLURRED_EFFECT": "पृष्ठभूमि धुंधली है",
|
"BLURRED_EFFECT": "पृष्ठभूमि धुंधली है",
|
||||||
"IMAGES_SECTION": "पृष्ठभूमि छवियां"
|
"IMAGES_SECTION": "पृष्ठभूमि छवियां",
|
||||||
|
"NOT_SUPPORTED": "इस ब्राउज़र में वर्चुअल बैकग्राउंड समर्थित नहीं है",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "आपका ब्राउज़र बैकग्राउंड इफेक्ट्स का समर्थन नहीं करता है। इस सुविधा के लिए GPU त्वरण की आवश्यकता है जो अक्षम या अनुपलब्ध हो सकता है।"
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "रिकॉर्डिंग",
|
"TITLE": "रिकॉर्डिंग",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "Unendosi alla stanza...",
|
"JOINING": "Unendosi alla stanza...",
|
||||||
"LANDSCAPE_WARNING": "Per una migliore esperienza, ruota il dispositivo in modalità verticale"
|
"LANDSCAPE_WARNING": "Per una migliore esperienza, ruota il dispositivo in modalità verticale",
|
||||||
|
"DISCONNECTED": "Hai lasciato la stanza",
|
||||||
|
"DISCONNECTED_SUBTITLE": "La sessione è terminata"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "Imposta il tuo soprannome",
|
"NICKNAME_SECTION": "Imposta il tuo soprannome",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "Nessun effetto e sfondo sfocato",
|
"BLURRED_SECTION": "Nessun effetto e sfondo sfocato",
|
||||||
"NO_EFFECTS": "Nessun effetto di sfondo",
|
"NO_EFFECTS": "Nessun effetto di sfondo",
|
||||||
"BLURRED_EFFECT": "Sfondo sfocato",
|
"BLURRED_EFFECT": "Sfondo sfocato",
|
||||||
"IMAGES_SECTION": "Immagini di sfondo"
|
"IMAGES_SECTION": "Immagini di sfondo",
|
||||||
|
"NOT_SUPPORTED": "Gli sfondi virtuali non sono supportati in questo browser",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "Il tuo browser non supporta gli effetti di sfondo. Questa funzione richiede l'accelerazione GPU che potrebbe essere disabilitata o non disponibile."
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "Registrazione",
|
"TITLE": "Registrazione",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "ルームに参加しています...",
|
"JOINING": "ルームに参加しています...",
|
||||||
"LANDSCAPE_WARNING": "より良い体験のために、デバイスを縦向きに回転させてください"
|
"LANDSCAPE_WARNING": "より良い体験のために、デバイスを縦向きに回転させてください",
|
||||||
|
"DISCONNECTED": "ルームから退出しました",
|
||||||
|
"DISCONNECTED_SUBTITLE": "セッションが終了しました"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "ニックネームを設定してください",
|
"NICKNAME_SECTION": "ニックネームを設定してください",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "エフェクトなし、ぼやけた背景",
|
"BLURRED_SECTION": "エフェクトなし、ぼやけた背景",
|
||||||
"NO_EFFECTS": "背景エフェクトなし",
|
"NO_EFFECTS": "背景エフェクトなし",
|
||||||
"BLURRED_EFFECT": "ぼやけた背景",
|
"BLURRED_EFFECT": "ぼやけた背景",
|
||||||
"IMAGES_SECTION": "背景画像"
|
"IMAGES_SECTION": "背景画像",
|
||||||
|
"NOT_SUPPORTED": "このブラウザでは仮想背景はサポートされていません",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "お使いのブラウザは背景効果をサポートしていません。この機能にはGPUアクセラレーションが必要ですが、無効化されているか利用できません。"
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "レコーディング",
|
"TITLE": "レコーディング",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "De ruimte betreden...",
|
"JOINING": "De ruimte betreden...",
|
||||||
"LANDSCAPE_WARNING": "Draai uw apparaat voor een betere ervaring naar portretmodus"
|
"LANDSCAPE_WARNING": "Draai uw apparaat voor een betere ervaring naar portretmodus",
|
||||||
|
"DISCONNECTED": "U heeft de kamer verlaten",
|
||||||
|
"DISCONNECTED_SUBTITLE": "De sessie is beëindigd"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "Stel je bijnaam in",
|
"NICKNAME_SECTION": "Stel je bijnaam in",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "Geen effecten en onscherpe achtergrond",
|
"BLURRED_SECTION": "Geen effecten en onscherpe achtergrond",
|
||||||
"NO_EFFECTS": "Geen achtergrondeffect",
|
"NO_EFFECTS": "Geen achtergrondeffect",
|
||||||
"BLURRED_EFFECT": "Onscherpe achtergrond",
|
"BLURRED_EFFECT": "Onscherpe achtergrond",
|
||||||
"IMAGES_SECTION": "Achtergrondafbeeldingen"
|
"IMAGES_SECTION": "Achtergrondafbeeldingen",
|
||||||
|
"NOT_SUPPORTED": "Virtuele achtergronden worden niet ondersteund in deze browser",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "Uw browser ondersteunt geen achtergrondeffecten. Deze functie vereist GPU-versnelling die mogelijk uitgeschakeld of niet beschikbaar is."
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "Opname",
|
"TITLE": "Opname",
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@
|
||||||
},
|
},
|
||||||
"ROOM": {
|
"ROOM": {
|
||||||
"JOINING": "Entrando na sala...",
|
"JOINING": "Entrando na sala...",
|
||||||
"LANDSCAPE_WARNING": "Por favor, gire seu dispositivo para o modo retrato para uma melhor experiência"
|
"LANDSCAPE_WARNING": "Por favor, gire seu dispositivo para o modo retrato para uma melhor experiência",
|
||||||
|
"DISCONNECTED": "Você saiu da sala",
|
||||||
|
"DISCONNECTED_SUBTITLE": "A sessão foi encerrada"
|
||||||
},
|
},
|
||||||
"PREJOIN": {
|
"PREJOIN": {
|
||||||
"NICKNAME_SECTION": "Defina seu apelido",
|
"NICKNAME_SECTION": "Defina seu apelido",
|
||||||
|
|
@ -118,7 +120,9 @@
|
||||||
"BLURRED_SECTION": "Sem efeitos e fundo desfocado",
|
"BLURRED_SECTION": "Sem efeitos e fundo desfocado",
|
||||||
"NO_EFFECTS": "Sem efeito de fundo",
|
"NO_EFFECTS": "Sem efeito de fundo",
|
||||||
"BLURRED_EFFECT": "Fundo desfocado",
|
"BLURRED_EFFECT": "Fundo desfocado",
|
||||||
"IMAGES_SECTION": "Imagens de fundo"
|
"IMAGES_SECTION": "Imagens de fundo",
|
||||||
|
"NOT_SUPPORTED": "Fundos virtuais não são suportados neste navegador",
|
||||||
|
"NOT_SUPPORTED_DESCRIPTION": "Seu navegador não suporta efeitos de fundo. Este recurso requer aceleração de GPU que pode estar desabilitada ou não disponível."
|
||||||
},
|
},
|
||||||
"RECORDING": {
|
"RECORDING": {
|
||||||
"TITLE": "Gravação",
|
"TITLE": "Gravação",
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import { DeleteDialogComponent } from './components/dialogs/delete-recording.com
|
||||||
import { DialogTemplateComponent } from './components/dialogs/dialog.component';
|
import { DialogTemplateComponent } from './components/dialogs/dialog.component';
|
||||||
import { RecordingDialogComponent } from './components/dialogs/recording-dialog.component';
|
import { RecordingDialogComponent } from './components/dialogs/recording-dialog.component';
|
||||||
import { LayoutComponent } from './components/layout/layout.component';
|
import { LayoutComponent } from './components/layout/layout.component';
|
||||||
|
import { MediaElementComponent } from './components/media-element/media-element.component';
|
||||||
import { ChatPanelComponent } from './components/panel/chat-panel/chat-panel.component';
|
import { ChatPanelComponent } from './components/panel/chat-panel/chat-panel.component';
|
||||||
import { SessionComponent } from './components/session/session.component';
|
import { SessionComponent } from './components/session/session.component';
|
||||||
import { StreamComponent } from './components/stream/stream.component';
|
import { StreamComponent } from './components/stream/stream.component';
|
||||||
import { ToolbarComponent } from './components/toolbar/toolbar.component';
|
|
||||||
import { ToolbarMediaButtonsComponent } from './components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component';
|
import { ToolbarMediaButtonsComponent } from './components/toolbar/toolbar-media-buttons/toolbar-media-buttons.component';
|
||||||
import { ToolbarPanelButtonsComponent } from './components/toolbar/toolbar-panel-buttons/toolbar-panel-buttons.component';
|
import { ToolbarPanelButtonsComponent } from './components/toolbar/toolbar-panel-buttons/toolbar-panel-buttons.component';
|
||||||
import { MediaElementComponent } from './components/media-element/media-element.component';
|
import { ToolbarComponent } from './components/toolbar/toolbar.component';
|
||||||
|
|
||||||
import { LinkifyPipe } from './pipes/linkify.pipe';
|
import { LinkifyPipe } from './pipes/linkify.pipe';
|
||||||
import { RemoteParticipantTracksPipe, TrackPublishedTypesPipe } from './pipes/participant.pipe';
|
import { RemoteParticipantTracksPipe, TrackPublishedTypesPipe } from './pipes/participant.pipe';
|
||||||
|
|
@ -39,15 +39,15 @@ import { BackgroundEffectsPanelComponent } from './components/panel/background-e
|
||||||
import { SettingsPanelComponent } from './components/panel/settings-panel/settings-panel.component';
|
import { SettingsPanelComponent } from './components/panel/settings-panel/settings-panel.component';
|
||||||
import { AudioDevicesComponent } from './components/settings/audio-devices/audio-devices.component';
|
import { AudioDevicesComponent } from './components/settings/audio-devices/audio-devices.component';
|
||||||
// import { CaptionsSettingComponent } from './components/settings/captions/captions.component';
|
// import { CaptionsSettingComponent } from './components/settings/captions/captions.component';
|
||||||
|
import { LandscapeWarningComponent } from './components/landscape-warning/landscape-warning.component';
|
||||||
import { LangSelectorComponent } from './components/settings/lang-selector/lang-selector.component';
|
import { LangSelectorComponent } from './components/settings/lang-selector/lang-selector.component';
|
||||||
import { ParticipantNameInputComponent } from './components/settings/participant-name-input/participant-name-input.component';
|
import { ParticipantNameInputComponent } from './components/settings/participant-name-input/participant-name-input.component';
|
||||||
|
import { ThemeSelectorComponent } from './components/settings/theme-selector/theme-selector.component';
|
||||||
import { VideoDevicesComponent } from './components/settings/video-devices/video-devices.component';
|
import { VideoDevicesComponent } from './components/settings/video-devices/video-devices.component';
|
||||||
|
import { VideoPosterComponent } from './components/video-poster/video-poster.component';
|
||||||
import { ApiDirectiveModule } from './directives/api/api.directive.module';
|
import { ApiDirectiveModule } from './directives/api/api.directive.module';
|
||||||
import { OpenViduComponentsDirectiveModule } from './directives/template/openvidu-components-angular.directive.module';
|
import { OpenViduComponentsDirectiveModule } from './directives/template/openvidu-components-angular.directive.module';
|
||||||
import { AppMaterialModule } from './openvidu-components-angular.material.module';
|
import { AppMaterialModule } from './openvidu-components-angular.material.module';
|
||||||
import { ThemeSelectorComponent } from './components/settings/theme-selector/theme-selector.component';
|
|
||||||
import { LandscapeWarningComponent } from './components/landscape-warning/landscape-warning.component';
|
|
||||||
import { VideoPosterComponent } from './components/video-poster/video-poster.component';
|
|
||||||
|
|
||||||
const publicComponents = [
|
const publicComponents = [
|
||||||
AdminDashboardComponent,
|
AdminDashboardComponent,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { OverlayContainer } from '@angular/cdk/overlay';
|
import { OverlayContainer } from '@angular/cdk/overlay';
|
||||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||||
import { ModuleWithProviders, NgModule, Provider, EnvironmentProviders } from '@angular/core';
|
import { EnvironmentProviders, ModuleWithProviders, NgModule, Provider } from '@angular/core';
|
||||||
|
|
||||||
import { CdkOverlayContainer } from './config/custom-cdk-overlay';
|
import { CdkOverlayContainer } from './config/custom-cdk-overlay';
|
||||||
import { OpenViduComponentsConfig } from './config/openvidu-components-angular.config';
|
import { OpenViduComponentsConfig } from './config/openvidu-components-angular.config';
|
||||||
|
|
@ -8,7 +8,6 @@ import { ActionService } from './services/action/action.service';
|
||||||
import { ChatService } from './services/chat/chat.service';
|
import { ChatService } from './services/chat/chat.service';
|
||||||
import { DeviceService } from './services/device/device.service';
|
import { DeviceService } from './services/device/device.service';
|
||||||
import { DocumentService } from './services/document/document.service';
|
import { DocumentService } from './services/document/document.service';
|
||||||
import { LayoutService } from './services/layout/layout.service';
|
|
||||||
import { LoggerService } from './services/logger/logger.service';
|
import { LoggerService } from './services/logger/logger.service';
|
||||||
import { OpenViduService } from './services/openvidu/openvidu.service';
|
import { OpenViduService } from './services/openvidu/openvidu.service';
|
||||||
import { PanelService } from './services/panel/panel.service';
|
import { PanelService } from './services/panel/panel.service';
|
||||||
|
|
@ -17,13 +16,13 @@ import { PlatformService } from './services/platform/platform.service';
|
||||||
import { RecordingService } from './services/recording/recording.service';
|
import { RecordingService } from './services/recording/recording.service';
|
||||||
import { StorageService } from './services/storage/storage.service';
|
import { StorageService } from './services/storage/storage.service';
|
||||||
|
|
||||||
import { VirtualBackgroundService } from './services/virtual-background/virtual-background.service';
|
|
||||||
import { BroadcastingService } from './services/broadcasting/broadcasting.service';
|
|
||||||
import { GlobalConfigService } from './services/config/global-config.service';
|
|
||||||
import { OpenViduComponentsConfigService } from './services/config/directive-config.service';
|
|
||||||
import { OpenViduComponentsUiModule } from './openvidu-components-angular-ui.module';
|
import { OpenViduComponentsUiModule } from './openvidu-components-angular-ui.module';
|
||||||
import { ViewportService } from './services/viewport/viewport.service';
|
import { BroadcastingService } from './services/broadcasting/broadcasting.service';
|
||||||
|
import { OpenViduComponentsConfigService } from './services/config/directive-config.service';
|
||||||
|
import { GlobalConfigService } from './services/config/global-config.service';
|
||||||
import { E2eeService } from './services/e2ee/e2ee.service';
|
import { E2eeService } from './services/e2ee/e2ee.service';
|
||||||
|
import { ViewportService } from './services/viewport/viewport.service';
|
||||||
|
import { VirtualBackgroundService } from './services/virtual-background/virtual-background.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [OpenViduComponentsUiModule],
|
imports: [OpenViduComponentsUiModule],
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,467 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { computed, Injectable, OnDestroy, signal } from '@angular/core';
|
||||||
|
import { createLocalTracks, LocalTrack, Room, Track } from 'livekit-client';
|
||||||
import { CameraType, CustomDevice, DeviceType } from '../../models/device.model';
|
import { CameraType, CustomDevice, DeviceType } from '../../models/device.model';
|
||||||
import { ILogger } from '../../models/logger.model';
|
import { ILogger } from '../../models/logger.model';
|
||||||
import { LoggerService } from '../logger/logger.service';
|
import { LoggerService } from '../logger/logger.service';
|
||||||
import { PlatformService } from '../platform/platform.service';
|
import { PlatformService } from '../platform/platform.service';
|
||||||
import { StorageService } from '../storage/storage.service';
|
import { StorageService } from '../storage/storage.service';
|
||||||
import { LocalTrack, Room, createLocalTracks } from 'livekit-client';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Device availability state for each media type
|
||||||
|
*/
|
||||||
|
interface DeviceAvailabilityState {
|
||||||
|
hasDevices: boolean;
|
||||||
|
isEnabled: boolean;
|
||||||
|
permissionGranted: boolean;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Device service with improved performance and independent audio/video handling.
|
||||||
|
*
|
||||||
|
* Key improvements:
|
||||||
|
* - Smart permission requests (single prompt when possible, fallback to separate)
|
||||||
|
* - Angular Signals for reactive state management (cameras, microphones as signals)
|
||||||
|
* - Live device detection - automatically updates when devices are connected/disconnected
|
||||||
|
* - Better error handling with specific error types per device
|
||||||
|
* - Performance optimizations with caching
|
||||||
|
* - LiveKit client integration for modern track management
|
||||||
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class DeviceService {
|
export class DeviceService implements OnDestroy {
|
||||||
private devices: MediaDeviceInfo[];
|
// Reactive device lists with Signals
|
||||||
private cameras: CustomDevice[] = [];
|
readonly cameras = signal<CustomDevice[]>([]);
|
||||||
private microphones: CustomDevice[] = [];
|
readonly microphones = signal<CustomDevice[]>([]);
|
||||||
private cameraSelected?: CustomDevice;
|
readonly cameraSelected = signal<CustomDevice | undefined>(undefined);
|
||||||
private microphoneSelected?: CustomDevice;
|
readonly microphoneSelected = signal<CustomDevice | undefined>(undefined);
|
||||||
|
|
||||||
|
// Reactive state management with Signals
|
||||||
|
private readonly videoState = signal<DeviceAvailabilityState>({
|
||||||
|
hasDevices: false,
|
||||||
|
isEnabled: true,
|
||||||
|
permissionGranted: false
|
||||||
|
});
|
||||||
|
|
||||||
|
private readonly audioState = signal<DeviceAvailabilityState>({
|
||||||
|
hasDevices: false,
|
||||||
|
isEnabled: true,
|
||||||
|
permissionGranted: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Computed signals for common checks
|
||||||
|
readonly hasVideoDevices = computed(() =>
|
||||||
|
this.videoState().hasDevices && this.cameras().length > 0
|
||||||
|
);
|
||||||
|
|
||||||
|
readonly hasAudioDevices = computed(() =>
|
||||||
|
this.audioState().hasDevices && this.microphones().length > 0
|
||||||
|
);
|
||||||
|
|
||||||
|
readonly hasVideoPermission = computed(() =>
|
||||||
|
this.videoState().permissionGranted
|
||||||
|
);
|
||||||
|
|
||||||
|
readonly hasAudioPermission = computed(() =>
|
||||||
|
this.audioState().permissionGranted
|
||||||
|
);
|
||||||
|
|
||||||
|
readonly allPermissionsGranted = computed(() =>
|
||||||
|
this.videoState().permissionGranted && this.audioState().permissionGranted
|
||||||
|
);
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
private readonly CACHE_DURATION = 5000; // 5 seconds
|
||||||
|
|
||||||
|
// Internal state
|
||||||
|
private devicesCache: {
|
||||||
|
timestamp: number;
|
||||||
|
devices: MediaDeviceInfo[];
|
||||||
|
} | null = null;
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
private videoDevicesEnabled: boolean = true;
|
private initializationPromise: Promise<void> | null = null;
|
||||||
private audioDevicesEnabled: boolean = true;
|
private deviceChangeHandler: (() => void) | null = null;
|
||||||
private deviceAccessDeniedError: boolean = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private loggerSrv: LoggerService,
|
private loggerSrv: LoggerService,
|
||||||
private platformSrv: PlatformService,
|
private platformSrv: PlatformService,
|
||||||
private storageSrv: StorageService
|
private storageSrv: StorageService
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerSrv.get('DevicesService');
|
this.log = this.loggerSrv.get('DeviceService');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize media devices and select a devices checking in local storage (if exists) or
|
* Cleanup when service is destroyed
|
||||||
* first devices found by default
|
|
||||||
*/
|
*/
|
||||||
async initializeDevices() {
|
ngOnDestroy(): void {
|
||||||
|
// Remove device change listener
|
||||||
|
if (this.deviceChangeHandler && navigator.mediaDevices?.removeEventListener) {
|
||||||
|
navigator.mediaDevices.removeEventListener('devicechange', this.deviceChangeHandler);
|
||||||
|
this.deviceChangeHandler = null;
|
||||||
|
this.log.d('Device change detection disabled');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize media devices with parallel audio/video handling
|
||||||
|
* Returns a promise that resolves when initialization is complete
|
||||||
|
*/
|
||||||
|
async initializeDevices(): Promise<void> {
|
||||||
|
// Prevent multiple simultaneous initializations
|
||||||
|
if (this.initializationPromise) {
|
||||||
|
return this.initializationPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initializationPromise = this.performInitialization();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.initializationPromise;
|
||||||
|
} finally {
|
||||||
|
this.initializationPromise = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async performInitialization(): Promise<void> {
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.devices = await this.getLocalDevices();
|
// Try to get devices with parallel audio/video permission requests
|
||||||
if (this.deviceAccessDeniedError) {
|
const devices = await this.getLocalDevicesOptimized();
|
||||||
this.log.w('Media devices permissions were not granted.');
|
|
||||||
|
if (devices.length === 0) {
|
||||||
|
this.log.w('No media devices found or permissions denied');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initializeCustomDevices();
|
this.processDevices(devices);
|
||||||
this.updateSelectedDevices();
|
this.updateSelectedDevices();
|
||||||
this.log.d('Media devices', this.cameras, this.microphones);
|
|
||||||
|
// Setup live device detection
|
||||||
|
this.setupDeviceChangeDetection();
|
||||||
|
|
||||||
|
this.log.d('Media devices initialized', {
|
||||||
|
cameras: this.cameras().length,
|
||||||
|
microphones: this.microphones().length
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.log.e('Error getting media devices', error);
|
this.log.e('Error initializing devices', error);
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check and update the media devices available
|
* Optimized device retrieval with independent audio/video handling
|
||||||
|
* This solves the critical bug where audio device failure affects video device detection
|
||||||
*/
|
*/
|
||||||
async refreshDevices() {
|
private async getLocalDevicesOptimized(): Promise<MediaDeviceInfo[]> {
|
||||||
if (!this.deviceAccessDeniedError) {
|
// Check cache first
|
||||||
this.devices = await this.getLocalDevices();
|
if (this.devicesCache && Date.now() - this.devicesCache.timestamp < this.CACHE_DURATION) {
|
||||||
this.initializeCustomDevices();
|
this.log.d('Using cached devices');
|
||||||
|
return this.devicesCache.devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try parallel permission requests for better performance
|
||||||
|
const results = await this.requestPermissionsParallel();
|
||||||
|
|
||||||
|
// Get devices after permissions are granted
|
||||||
|
const devices = await this.enumerateDevices();
|
||||||
|
|
||||||
|
// Update cache
|
||||||
|
this.devicesCache = {
|
||||||
|
timestamp: Date.now(),
|
||||||
|
devices
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update state based on results
|
||||||
|
this.updateDeviceStates(results);
|
||||||
|
|
||||||
|
return devices;
|
||||||
|
} catch (error) {
|
||||||
|
this.log.e('Error getting devices', error);
|
||||||
|
|
||||||
|
// Fallback: try to enumerate devices without permissions
|
||||||
|
return await this.fallbackDeviceEnumeration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeCustomDevices(): void {
|
/**
|
||||||
this.cameras = this.devices
|
* Smart permission request strategy:
|
||||||
|
* 1. Try both together (single prompt - better UX)
|
||||||
|
* 2. If fails, try individually (fallback for granular permissions)
|
||||||
|
*
|
||||||
|
* This minimizes user friction while maintaining independence
|
||||||
|
*/
|
||||||
|
private async requestPermissionsParallel(): Promise<{
|
||||||
|
video: { success: boolean; error?: any };
|
||||||
|
audio: { success: boolean; error?: any };
|
||||||
|
}> {
|
||||||
|
const results = {
|
||||||
|
video: { success: false, error: undefined as any },
|
||||||
|
audio: { success: false, error: undefined as any }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Strategy 1: Try requesting both together (single prompt)
|
||||||
|
try {
|
||||||
|
this.log.d('Requesting both audio and video permissions together');
|
||||||
|
const tracks = await createLocalTracks({ audio: true, video: true });
|
||||||
|
|
||||||
|
// Check which tracks we got
|
||||||
|
const videoTrack = tracks.find(t => t.kind === Track.Kind.Video);
|
||||||
|
const audioTrack = tracks.find(t => t.kind === Track.Kind.Audio);
|
||||||
|
|
||||||
|
if (videoTrack) {
|
||||||
|
results.video.success = true;
|
||||||
|
this.log.d('Video permission granted');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audioTrack) {
|
||||||
|
results.audio.success = true;
|
||||||
|
this.log.d('Audio permission granted');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop tracks immediately after getting permission
|
||||||
|
tracks.forEach(t => t.stop());
|
||||||
|
|
||||||
|
// If both succeeded, return early (best case - single prompt!)
|
||||||
|
if (results.video.success && results.audio.success) {
|
||||||
|
this.log.d('Both permissions granted with single prompt');
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
this.log.w('Combined permission request failed, trying individually', error);
|
||||||
|
// Continue to fallback strategy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strategy 2: Fallback - request individually if combined request failed
|
||||||
|
// This handles cases where user denied one but might allow the other
|
||||||
|
const promises: Promise<void>[] = [];
|
||||||
|
|
||||||
|
// Try video if not already granted
|
||||||
|
if (!results.video.success) {
|
||||||
|
promises.push(
|
||||||
|
this.requestVideoPermission().then(
|
||||||
|
(tracks) => {
|
||||||
|
results.video.success = true;
|
||||||
|
tracks.forEach(t => t.stop());
|
||||||
|
this.log.d('Video permission granted individually');
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
results.video.error = error;
|
||||||
|
this.log.w('Video permission denied', error);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try audio if not already granted
|
||||||
|
if (!results.audio.success) {
|
||||||
|
promises.push(
|
||||||
|
this.requestAudioPermission().then(
|
||||||
|
(tracks) => {
|
||||||
|
results.audio.success = true;
|
||||||
|
tracks.forEach(t => t.stop());
|
||||||
|
this.log.d('Audio permission granted individually');
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
results.audio.error = error;
|
||||||
|
this.log.w('Audio permission denied', error);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for fallback requests to complete
|
||||||
|
if (promises.length > 0) {
|
||||||
|
await Promise.allSettled(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request video permission independently
|
||||||
|
*/
|
||||||
|
private async requestVideoPermission(): Promise<LocalTrack[]> {
|
||||||
|
try {
|
||||||
|
return await createLocalTracks({ audio: false, video: true });
|
||||||
|
} catch (error: any) {
|
||||||
|
this.videoState.update(state => ({
|
||||||
|
...state,
|
||||||
|
permissionGranted: false,
|
||||||
|
error: error.name || 'Unknown error'
|
||||||
|
}));
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request audio permission independently
|
||||||
|
*/
|
||||||
|
private async requestAudioPermission(): Promise<LocalTrack[]> {
|
||||||
|
try {
|
||||||
|
return await createLocalTracks({ audio: true, video: false });
|
||||||
|
} catch (error: any) {
|
||||||
|
this.audioState.update(state => ({
|
||||||
|
...state,
|
||||||
|
permissionGranted: false,
|
||||||
|
error: error.name || 'Unknown error'
|
||||||
|
}));
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerate devices using LiveKit's Room API or browser API
|
||||||
|
*/
|
||||||
|
private async enumerateDevices(): Promise<MediaDeviceInfo[]> {
|
||||||
|
try {
|
||||||
|
// Use LiveKit's Room.getLocalDevices if available, otherwise fallback to browser API
|
||||||
|
const devices = await Room.getLocalDevices();
|
||||||
|
return this.filterValidDevices(devices);
|
||||||
|
} catch (error) {
|
||||||
|
this.log.w('LiveKit device enumeration failed, using browser API', error);
|
||||||
|
|
||||||
|
// Firefox compatibility
|
||||||
|
if (this.platformSrv.isFirefox()) {
|
||||||
|
return await this.getDevicesFirefox();
|
||||||
|
}
|
||||||
|
|
||||||
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
return this.filterValidDevices(devices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Firefox-specific device enumeration
|
||||||
|
*/
|
||||||
|
private async getDevicesFirefox(): Promise<MediaDeviceInfo[]> {
|
||||||
|
try {
|
||||||
|
// Firefox may need explicit getUserMedia call
|
||||||
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
|
||||||
|
stream.getTracks().forEach(track => track.stop());
|
||||||
|
|
||||||
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
return this.filterValidDevices(devices);
|
||||||
|
} catch (error) {
|
||||||
|
this.log.w('Firefox getUserMedia failed, trying enumerate directly', error);
|
||||||
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
return this.filterValidDevices(devices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter out invalid or default devices
|
||||||
|
*/
|
||||||
|
private filterValidDevices(devices: MediaDeviceInfo[]): MediaDeviceInfo[] {
|
||||||
|
return devices.filter(
|
||||||
|
(d) => d.label && d.deviceId && d.deviceId !== 'default'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback device enumeration without permissions
|
||||||
|
*/
|
||||||
|
private async fallbackDeviceEnumeration(): Promise<MediaDeviceInfo[]> {
|
||||||
|
try {
|
||||||
|
this.log.d('Attempting device enumeration without permissions');
|
||||||
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
|
||||||
|
// Filter devices that have IDs but may not have labels
|
||||||
|
return devices.filter(d => d.deviceId && d.deviceId !== 'default');
|
||||||
|
} catch (error) {
|
||||||
|
this.log.e('Fallback device enumeration failed', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update device states based on permission results
|
||||||
|
*/
|
||||||
|
private updateDeviceStates(results: {
|
||||||
|
video: { success: boolean; error?: any };
|
||||||
|
audio: { success: boolean; error?: any };
|
||||||
|
}): void {
|
||||||
|
// Update video state
|
||||||
|
this.videoState.update(state => ({
|
||||||
|
...state,
|
||||||
|
permissionGranted: results.video.success,
|
||||||
|
error: results.video.error?.name
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Update audio state
|
||||||
|
this.audioState.update(state => ({
|
||||||
|
...state,
|
||||||
|
permissionGranted: results.audio.success,
|
||||||
|
error: results.audio.error?.name
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process raw devices into typed camera and microphone lists
|
||||||
|
*/
|
||||||
|
private processDevices(devices: MediaDeviceInfo[]): void {
|
||||||
|
// Process video devices
|
||||||
|
const camerasArray = devices
|
||||||
.filter((d) => d.kind === DeviceType.VIDEO_INPUT)
|
.filter((d) => d.kind === DeviceType.VIDEO_INPUT)
|
||||||
.map((d) => this.createCustomDevice(d, CameraType.BACK));
|
.map((d) => this.createCustomDevice(d, CameraType.BACK));
|
||||||
this.microphones = this.devices
|
|
||||||
|
// Process audio devices
|
||||||
|
const microphonesArray = devices
|
||||||
.filter((d) => d.kind === DeviceType.AUDIO_INPUT)
|
.filter((d) => d.kind === DeviceType.AUDIO_INPUT)
|
||||||
.map((d) => ({ label: d.label, device: d.deviceId }));
|
.map((d) => ({ label: d.label, device: d.deviceId }));
|
||||||
|
|
||||||
|
// Detect camera types (front/back)
|
||||||
|
this.detectCameraTypes(camerasArray);
|
||||||
|
|
||||||
|
// Update signals
|
||||||
|
this.cameras.set(camerasArray);
|
||||||
|
this.microphones.set(microphonesArray);
|
||||||
|
|
||||||
|
// Update availability states
|
||||||
|
this.updateDeviceAvailability(camerasArray.length, microphonesArray.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect camera types (front/back) based on platform and labels
|
||||||
|
*/
|
||||||
|
private detectCameraTypes(cameras: CustomDevice[]): void {
|
||||||
|
if (cameras.length === 0) return;
|
||||||
|
|
||||||
if (this.platformSrv.isMobile()) {
|
if (this.platformSrv.isMobile()) {
|
||||||
this.cameras.forEach((c) => {
|
// On mobile, detect by label
|
||||||
if (c.label.toLowerCase().includes(CameraType.FRONT.toLowerCase())) {
|
cameras.forEach((camera) => {
|
||||||
c.type = CameraType.FRONT;
|
if (camera.label.toLowerCase().includes(CameraType.FRONT.toLowerCase())) {
|
||||||
|
camera.type = CameraType.FRONT;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (this.cameras.length > 0) {
|
} else {
|
||||||
this.cameras[0].type = CameraType.FRONT;
|
// On desktop, first camera is typically front-facing
|
||||||
|
cameras[0].type = CameraType.FRONT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update device availability states
|
||||||
|
*/
|
||||||
|
private updateDeviceAvailability(cameraCount: number, microphoneCount: number): void {
|
||||||
|
this.videoState.update(state => ({
|
||||||
|
...state,
|
||||||
|
hasDevices: cameraCount > 0
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.audioState.update(state => ({
|
||||||
|
...state,
|
||||||
|
hasDevices: microphoneCount > 0
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create custom device object
|
||||||
|
*/
|
||||||
private createCustomDevice(device: MediaDeviceInfo, defaultType: CameraType): CustomDevice {
|
private createCustomDevice(device: MediaDeviceInfo, defaultType: CameraType): CustomDevice {
|
||||||
return {
|
return {
|
||||||
label: device.label,
|
label: device.label,
|
||||||
|
|
@ -90,181 +470,248 @@ export class DeviceService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateSelectedDevices() {
|
/**
|
||||||
this.cameraSelected = this.getDeviceFromStorage(this.cameras, this.storageSrv.getVideoDevice()) || this.cameras[0];
|
* Update selected devices from storage or use defaults
|
||||||
this.microphoneSelected = this.getDeviceFromStorage(this.microphones, this.storageSrv.getAudioDevice()) || this.microphones[0];
|
*/
|
||||||
|
private updateSelectedDevices(): void {
|
||||||
|
const storedCamera = this.storageSrv.getVideoDevice();
|
||||||
|
const selectedCam = this.findDeviceOrDefault(
|
||||||
|
this.cameras(),
|
||||||
|
storedCamera?.device
|
||||||
|
);
|
||||||
|
if (selectedCam) {
|
||||||
|
this.cameraSelected.set(selectedCam);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDeviceFromStorage(devices: CustomDevice[], storageDevice: CustomDevice | null): CustomDevice | undefined {
|
const storedMic = this.storageSrv.getAudioDevice();
|
||||||
if (!storageDevice) return;
|
const selectedMic = this.findDeviceOrDefault(
|
||||||
return devices.find((d) => d.device === storageDevice.device);
|
this.microphones(),
|
||||||
|
storedMic?.device
|
||||||
|
);
|
||||||
|
if (selectedMic) {
|
||||||
|
this.microphoneSelected.set(selectedMic);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* Find device by ID or return first available
|
||||||
|
*/
|
||||||
|
private findDeviceOrDefault(devices: CustomDevice[], deviceId?: string): CustomDevice | undefined {
|
||||||
|
if (devices.length === 0) return undefined;
|
||||||
|
return deviceId
|
||||||
|
? devices.find((d) => d.device === deviceId) || devices[0]
|
||||||
|
: devices[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh devices (e.g., when a device is plugged/unplugged)
|
||||||
|
*/
|
||||||
|
async refreshDevices(): Promise<void> {
|
||||||
|
// Invalidate cache
|
||||||
|
this.devicesCache = null;
|
||||||
|
|
||||||
|
const devices = await this.getLocalDevicesOptimized();
|
||||||
|
this.processDevices(devices);
|
||||||
|
this.updateSelectedDevices();
|
||||||
|
|
||||||
|
this.log.d('Devices refreshed', {
|
||||||
|
cameras: this.cameras().length,
|
||||||
|
microphones: this.microphones().length
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup live device change detection
|
||||||
|
* Automatically refreshes device list when devices are connected/disconnected
|
||||||
|
*/
|
||||||
|
private setupDeviceChangeDetection(): void {
|
||||||
|
if (!navigator.mediaDevices?.addEventListener) {
|
||||||
|
this.log.w('Device change detection not supported');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove existing listener if any
|
||||||
|
if (this.deviceChangeHandler) {
|
||||||
|
navigator.mediaDevices.removeEventListener('devicechange', this.deviceChangeHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new handler
|
||||||
|
this.deviceChangeHandler = async () => {
|
||||||
|
this.log.d('Device change detected, refreshing device list');
|
||||||
|
await this.refreshDevices();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register listener
|
||||||
|
navigator.mediaDevices.addEventListener('devicechange', this.deviceChangeHandler);
|
||||||
|
this.log.d('Device change detection enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public API methods (compatible with original DeviceService)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if camera is enabled based on storage and device availability
|
||||||
*/
|
*/
|
||||||
isCameraEnabled(): boolean {
|
isCameraEnabled(): boolean {
|
||||||
return this.hasVideoDeviceAvailable() && this.storageSrv.isCameraEnabled();
|
return this.hasVideoDeviceAvailable() && this.storageSrv.isCameraEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if microphone is enabled based on storage and device availability
|
||||||
|
*/
|
||||||
isMicrophoneEnabled(): boolean {
|
isMicrophoneEnabled(): boolean {
|
||||||
return this.hasAudioDeviceAvailable() && this.storageSrv.isMicrophoneEnabled();
|
return this.hasAudioDeviceAvailable() && this.storageSrv.isMicrophoneEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get currently selected camera
|
||||||
|
*/
|
||||||
getCameraSelected(): CustomDevice | undefined {
|
getCameraSelected(): CustomDevice | undefined {
|
||||||
return this.cameraSelected;
|
return this.cameraSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get currently selected microphone
|
||||||
|
*/
|
||||||
getMicrophoneSelected(): CustomDevice | undefined {
|
getMicrophoneSelected(): CustomDevice | undefined {
|
||||||
return this.microphoneSelected;
|
return this.microphoneSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
setCameraSelected(deviceId: any) {
|
/**
|
||||||
this.cameraSelected = this.getDeviceById(this.cameras, deviceId);
|
* Set selected camera and persist to storage
|
||||||
const saveFunction = (device) => this.storageSrv.setVideoDevice(device);
|
*/
|
||||||
this.saveDeviceToStorage(this.cameraSelected, saveFunction);
|
setCameraSelected(deviceId: string): void {
|
||||||
|
const device = this.cameras().find((c) => c.device === deviceId);
|
||||||
|
if (!device) {
|
||||||
|
this.log.w('Camera not found:', deviceId);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMicSelected(deviceId: string) {
|
this.cameraSelected.set(device);
|
||||||
this.microphoneSelected = this.getDeviceById(this.microphones, deviceId);
|
this.storageSrv.setVideoDevice(device);
|
||||||
const saveFunction = (device) => this.storageSrv.setAudioDevice(device);
|
this.log.d('Camera selected:', device.label);
|
||||||
this.saveDeviceToStorage(this.microphoneSelected, saveFunction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set selected microphone and persist to storage
|
||||||
|
*/
|
||||||
|
setMicSelected(deviceId: string): void {
|
||||||
|
const device = this.microphones().find((m) => m.device === deviceId);
|
||||||
|
if (!device) {
|
||||||
|
this.log.w('Microphone not found:', deviceId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.microphoneSelected.set(device);
|
||||||
|
this.storageSrv.setAudioDevice(device);
|
||||||
|
this.log.d('Microphone selected:', device.label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if video track needs to be updated
|
||||||
|
*/
|
||||||
needUpdateVideoTrack(newDevice: CustomDevice): boolean {
|
needUpdateVideoTrack(newDevice: CustomDevice): boolean {
|
||||||
return this.cameraSelected?.device !== newDevice.device || this.cameraSelected?.label !== newDevice.label;
|
const current = this.cameraSelected();
|
||||||
|
return (
|
||||||
|
current?.device !== newDevice.device ||
|
||||||
|
current?.label !== newDevice.label
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if audio track needs to be updated
|
||||||
|
*/
|
||||||
needUpdateAudioTrack(newDevice: CustomDevice): boolean {
|
needUpdateAudioTrack(newDevice: CustomDevice): boolean {
|
||||||
return this.microphoneSelected?.device !== newDevice.device || this.microphoneSelected?.label !== newDevice.label;
|
const current = this.microphoneSelected();
|
||||||
|
return (
|
||||||
|
current?.device !== newDevice.device ||
|
||||||
|
current?.label !== newDevice.label
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// Public API - Device Access
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of available cameras
|
||||||
|
*/
|
||||||
getCameras(): CustomDevice[] {
|
getCameras(): CustomDevice[] {
|
||||||
return this.cameras;
|
return this.cameras();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of available microphones
|
||||||
|
*/
|
||||||
getMicrophones(): CustomDevice[] {
|
getMicrophones(): CustomDevice[] {
|
||||||
return this.microphones;
|
return this.microphones();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// Public API - Device State
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if video devices are available
|
||||||
|
*/
|
||||||
hasVideoDeviceAvailable(): boolean {
|
hasVideoDeviceAvailable(): boolean {
|
||||||
return this.videoDevicesEnabled && this.cameras.length > 0;
|
return this.hasVideoDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if audio devices are available
|
||||||
|
*/
|
||||||
hasAudioDeviceAvailable(): boolean {
|
hasAudioDeviceAvailable(): boolean {
|
||||||
return this.audioDevicesEnabled && this.microphones.length > 0;
|
return this.hasAudioDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
// ==========================================
|
||||||
this.devices = [];
|
// Public API - Permission State
|
||||||
this.cameras = [];
|
// ==========================================
|
||||||
this.microphones = [];
|
|
||||||
this.cameraSelected = undefined;
|
|
||||||
this.microphoneSelected = undefined;
|
|
||||||
this.videoDevicesEnabled = true;
|
|
||||||
this.audioDevicesEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getDeviceById(devices: CustomDevice[], deviceId: string): CustomDevice | undefined {
|
/**
|
||||||
return devices.find((d) => d.device === deviceId);
|
* Check if video permission was granted
|
||||||
}
|
*/
|
||||||
|
hasVideoPermissionGranted(): boolean {
|
||||||
private saveDeviceToStorage(device: CustomDevice | undefined, saveFunction: (device: CustomDevice) => void) {
|
return this.hasVideoPermission();
|
||||||
if (device) saveFunction(device);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the local media devices (audio and video) available for the user.
|
* Check if audio permission was granted
|
||||||
*
|
|
||||||
* @returns A promise that resolves to an array of `MediaDeviceInfo` objects representing the available local devices.
|
|
||||||
*/
|
*/
|
||||||
private async getLocalDevices(): Promise<MediaDeviceInfo[]> {
|
hasAudioPermissionGranted(): boolean {
|
||||||
const strategies = this.getPermissionStrategies();
|
return this.hasAudioPermission();
|
||||||
|
|
||||||
for (const strategy of strategies) {
|
|
||||||
try {
|
|
||||||
this.log.d(`Trying strategy: audio=${strategy.audio}, video=${strategy.video}`);
|
|
||||||
const devices = await this.tryPermissionStrategy(strategy);
|
|
||||||
if (devices) {
|
|
||||||
return this.filterValidDevices(devices);
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
this.log.w(`Strategy failed: audio=${strategy.audio}, video=${strategy.video}`, error);
|
|
||||||
|
|
||||||
// If it's the last attempt and failed, we handle the error
|
|
||||||
if (strategy === strategies[strategies.length - 1]) {
|
|
||||||
return await this.handleFinalFallback(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
// ==========================================
|
||||||
}
|
// Public API - Reactive State Access
|
||||||
|
// For components that need direct signal access, use:
|
||||||
|
// - this.cameras, this.microphones (device lists)
|
||||||
|
// - this.cameraSelected, this.microphoneSelected (selections)
|
||||||
|
// - this.hasVideoDevices, this.hasAudioDevices (availability)
|
||||||
|
// - this.hasVideoPermission, this.hasAudioPermission (permissions)
|
||||||
|
// - this.allPermissionsGranted (combined permissions)
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* Clear all device data
|
||||||
* Get the list of permission strategies to try
|
|
||||||
*/
|
*/
|
||||||
protected getPermissionStrategies(): Array<{ audio: boolean; video: boolean }> {
|
clear(): void {
|
||||||
return [
|
this.cameras.set([]);
|
||||||
{ audio: true, video: true },
|
this.microphones.set([]);
|
||||||
{ audio: true, video: false },
|
this.cameraSelected.set(undefined);
|
||||||
{ audio: false, video: true }
|
this.microphoneSelected.set(undefined);
|
||||||
];
|
this.devicesCache = null;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
this.videoState.set({
|
||||||
* @internal
|
hasDevices: false,
|
||||||
* Try a specific permission strategy and return devices if successful
|
isEnabled: true,
|
||||||
*/
|
permissionGranted: false
|
||||||
protected async tryPermissionStrategy(strategy: { audio: boolean; video: boolean }): Promise<MediaDeviceInfo[] | null> {
|
});
|
||||||
const localTracks = await createLocalTracks(strategy);
|
|
||||||
localTracks.forEach((track) => track.stop());
|
|
||||||
|
|
||||||
// Permission granted
|
this.audioState.set({
|
||||||
return this.platformSrv.isFirefox() ? await this.getMediaDevicesFirefox() : await Room.getLocalDevices();
|
hasDevices: false,
|
||||||
}
|
isEnabled: true,
|
||||||
|
permissionGranted: false
|
||||||
/**
|
});
|
||||||
* @internal
|
|
||||||
* Filter devices to remove default and invalid entries
|
|
||||||
*/
|
|
||||||
protected filterValidDevices(devices: MediaDeviceInfo[]): MediaDeviceInfo[] {
|
|
||||||
return devices.filter((d: MediaDeviceInfo) => d.label && d.deviceId && d.deviceId !== 'default');
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getMediaDevicesFirefox(): Promise<MediaDeviceInfo[]> {
|
|
||||||
// Firefox requires to get user media to get the devices
|
|
||||||
await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
|
|
||||||
return navigator.mediaDevices.enumerateDevices();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleFinalFallback(error: any): Promise<MediaDeviceInfo[]> {
|
|
||||||
this.log.w('All permission strategies failed, trying device enumeration without permissions');
|
|
||||||
|
|
||||||
try {
|
|
||||||
return await this.handleFallbackByErrorType(error);
|
|
||||||
} catch (error) {
|
|
||||||
this.log.e('Complete failure getting devices', error);
|
|
||||||
this.deviceAccessDeniedError = true;
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
* Handle fallback based on error type
|
|
||||||
*/
|
|
||||||
protected async handleFallbackByErrorType(error: any): Promise<MediaDeviceInfo[]> {
|
|
||||||
if (error?.name === 'NotReadableError' || error?.name === 'AbortError') {
|
|
||||||
this.log.w('Device busy, using enumerateDevices() instead');
|
|
||||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
||||||
return devices.filter((d) => d.deviceId && d.deviceId !== 'default');
|
|
||||||
}
|
|
||||||
if (error?.name === 'NotAllowedError' || error?.name === 'SecurityError') {
|
|
||||||
this.log.w('Permission denied to access devices');
|
|
||||||
this.deviceAccessDeniedError = true;
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { OpenViduComponentsConfigService } from '../config/directive-config.service';
|
|
||||||
import { Subject, takeUntil } from 'rxjs';
|
|
||||||
import { createKeyMaterialFromString, deriveKeys } from 'livekit-client';
|
import { createKeyMaterialFromString, deriveKeys } from 'livekit-client';
|
||||||
|
import { Subject, takeUntil } from 'rxjs';
|
||||||
|
import { OpenViduComponentsConfigService } from '../config/directive-config.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Independent E2EE Service for encrypting and decrypting text-based content
|
* Independent E2EE Service for encrypting and decrypting text-based content
|
||||||
|
|
@ -12,6 +12,7 @@ import { createKeyMaterialFromString, deriveKeys } from 'livekit-client';
|
||||||
* - Uses deriveKeys from livekit-client for key derivation (HKDF)
|
* - Uses deriveKeys from livekit-client for key derivation (HKDF)
|
||||||
* - Uses Web Crypto API (AES-GCM) for actual encryption/decryption
|
* - Uses Web Crypto API (AES-GCM) for actual encryption/decryption
|
||||||
* - Generates random IV for each encryption operation
|
* - Generates random IV for each encryption operation
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,14 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, signal, Signal } from '@angular/core';
|
||||||
import { BackgroundProcessor, /*BackgroundProcessorWrapper,*/ SwitchBackgroundProcessorOptions } from '@livekit/track-processors';
|
import {
|
||||||
|
BackgroundProcessor,
|
||||||
|
supportsBackgroundProcessors,
|
||||||
|
supportsModernBackgroundProcessors,
|
||||||
|
/*BackgroundProcessorWrapper,*/ SwitchBackgroundProcessorOptions
|
||||||
|
} from '@livekit/track-processors';
|
||||||
import {
|
import {
|
||||||
AudioCaptureOptions,
|
AudioCaptureOptions,
|
||||||
ConnectionState,
|
ConnectionState,
|
||||||
|
createLocalTracks,
|
||||||
CreateLocalTracksOptions,
|
CreateLocalTracksOptions,
|
||||||
E2EEOptions,
|
E2EEOptions,
|
||||||
ExternalE2EEKeyProvider,
|
ExternalE2EEKeyProvider,
|
||||||
|
|
@ -13,8 +19,7 @@ import {
|
||||||
RoomOptions,
|
RoomOptions,
|
||||||
Track,
|
Track,
|
||||||
VideoCaptureOptions,
|
VideoCaptureOptions,
|
||||||
VideoPresets,
|
VideoPresets
|
||||||
createLocalTracks
|
|
||||||
} from 'livekit-client';
|
} from 'livekit-client';
|
||||||
import { ILogger } from '../../models/logger.model';
|
import { ILogger } from '../../models/logger.model';
|
||||||
import { OpenViduComponentsConfigService } from '../config/directive-config.service';
|
import { OpenViduComponentsConfigService } from '../config/directive-config.service';
|
||||||
|
|
@ -57,8 +62,20 @@ export class OpenViduService {
|
||||||
/**
|
/**
|
||||||
* Background processor for video tracks. Initialized in disabled mode.
|
* Background processor for video tracks. Initialized in disabled mode.
|
||||||
* This processor is shared between prejoin and in-room states.
|
* This processor is shared between prejoin and in-room states.
|
||||||
|
* Only initialized if browser supports background processing (GPU available).
|
||||||
*/
|
*/
|
||||||
private backgroundProcessor: BackgroundProcessorWrapper;
|
private backgroundProcessor?: BackgroundProcessorWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal to track if background processor is supported (requires GPU).
|
||||||
|
* Set to false if browser doesn't support it or processor initialization fails.
|
||||||
|
*/
|
||||||
|
private _isBackgroundProcessorSupported = signal(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public readonly signal for background processor support status.
|
||||||
|
*/
|
||||||
|
readonly isBackgroundProcessorSupported: Signal<boolean> = this._isBackgroundProcessorSupported.asReadonly();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
|
@ -67,11 +84,34 @@ export class OpenViduService {
|
||||||
private loggerSrv: LoggerService,
|
private loggerSrv: LoggerService,
|
||||||
private deviceService: DeviceService,
|
private deviceService: DeviceService,
|
||||||
private storageService: StorageService,
|
private storageService: StorageService,
|
||||||
private configService: OpenViduComponentsConfigService
|
private configService: OpenViduComponentsConfigService,
|
||||||
) {
|
) {
|
||||||
this.log = this.loggerSrv.get('OpenViduService');
|
this.log = this.loggerSrv.get('OpenViduService');
|
||||||
// this.isSttReadyObs = this._isSttReady.asObservable();
|
// this.isSttReadyObs = this._isSttReady.asObservable();
|
||||||
|
|
||||||
|
// Check if browser supports background processors
|
||||||
|
if (!supportsBackgroundProcessors()) {
|
||||||
|
this.log.w('Background processors not supported in this browser (GPU may be disabled)');
|
||||||
|
this._isBackgroundProcessorSupported.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only initialize processor immediately for browsers supporting modern processors
|
||||||
|
// Browsers without modern support (e.g., Firefox) will initialize on-demand
|
||||||
|
if (supportsModernBackgroundProcessors()) {
|
||||||
|
try {
|
||||||
this.backgroundProcessor = BackgroundProcessor({ mode: 'disabled' });
|
this.backgroundProcessor = BackgroundProcessor({ mode: 'disabled' });
|
||||||
|
this._isBackgroundProcessorSupported.set(true);
|
||||||
|
this.log.d('Background processor initialized at startup (modern processors supported)');
|
||||||
|
} catch (error: any) {
|
||||||
|
this.log.w('Failed to initialize background processor:', error?.message || error);
|
||||||
|
this._isBackgroundProcessorSupported.set(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Mark as supported but don't initialize yet - will be created on-demand
|
||||||
|
this._isBackgroundProcessorSupported.set(true);
|
||||||
|
this.log.d('Background processors supported but not modern - will initialize on-demand');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -273,17 +313,77 @@ export class OpenViduService {
|
||||||
return this.localTracks;
|
return this.localTracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches the background mode on the local video track.
|
* Switches the background mode on the local video track.
|
||||||
* Works both in prejoin and in-room states.
|
* Works both in prejoin and in-room states.
|
||||||
|
* For Firefox: applies processor when effect is activated to avoid performance issues
|
||||||
|
* For other browsers: processor is pre-attached, so just switch mode
|
||||||
* @param options - The switch options (mode, blurRadius, imagePath)
|
* @param options - The switch options (mode, blurRadius, imagePath)
|
||||||
* @returns Promise<void>
|
* @returns Promise<void>
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
async switchBackgroundMode(options: SwitchBackgroundProcessorOptions): Promise<void> {
|
async switchBackgroundMode(options: SwitchBackgroundProcessorOptions): Promise<void> {
|
||||||
|
if (!this.isBackgroundProcessorSupported()) {
|
||||||
|
this.log.w('Background processor not supported (GPU disabled). Virtual background is disabled.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// For browsers without modern processor support: attach processor on-demand when effect is activated
|
||||||
|
if (!supportsModernBackgroundProcessors()) {
|
||||||
|
await this.handleLazyProcessorAttachment(options.mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If processor exists, switch mode (either pre-initialized or just created on-demand)
|
||||||
|
if (this.backgroundProcessor) {
|
||||||
await this.backgroundProcessor.switchTo(options);
|
await this.backgroundProcessor.switchTo(options);
|
||||||
this.log.d('Background mode switched:', options);
|
this.log.d('Background mode switched:', options);
|
||||||
}
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
this.log.e('Failed to switch background mode:', error?.message || error);
|
||||||
|
this._isBackgroundProcessorSupported.set(false);
|
||||||
|
// Don't throw - gracefully disable virtual background instead of crashing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles lazy processor attachment for browsers without modern processor support.
|
||||||
|
* Creates and attaches processor on-demand when effect is activated.
|
||||||
|
* This is used for browsers like Firefox that don't support modern background processors.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
private async handleLazyProcessorAttachment(mode: SwitchBackgroundProcessorOptions['mode']): Promise<void> {
|
||||||
|
const videoTrack = await this.getVideoTrack();
|
||||||
|
if (!videoTrack) return;
|
||||||
|
|
||||||
|
const hasProcessor = Boolean(videoTrack.getProcessor());
|
||||||
|
const isDisabled = mode === 'disabled';
|
||||||
|
|
||||||
|
if (!isDisabled && !hasProcessor) {
|
||||||
|
try {
|
||||||
|
// Create processor on-demand if not already created
|
||||||
|
if (!this.backgroundProcessor) {
|
||||||
|
this.log.d('Creating background processor on-demand');
|
||||||
|
this.backgroundProcessor = BackgroundProcessor({ mode: 'disabled' });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log.d('Attaching processor on effect activation (lazy loading)');
|
||||||
|
await videoTrack.setProcessor(this.backgroundProcessor);
|
||||||
|
} catch (error: any) {
|
||||||
|
this.log.w('Failed to attach background processor (GPU may be disabled):', error?.message || error);
|
||||||
|
this._isBackgroundProcessorSupported.set(false);
|
||||||
|
// Continue without crashing - virtual background will be disabled
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDisabled && hasProcessor) {
|
||||||
|
this.log.d('Stopping processor on effect deactivation');
|
||||||
|
await videoTrack.stopProcessor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
|
@ -321,9 +421,12 @@ export class OpenViduService {
|
||||||
|
|
||||||
// Video device
|
// Video device
|
||||||
if (videoDeviceId === true) {
|
if (videoDeviceId === true) {
|
||||||
options.video = this.deviceService.hasVideoDeviceAvailable()
|
if (this.deviceService.hasVideoDeviceAvailable()) {
|
||||||
? { deviceId: this.deviceService.getCameraSelected()?.device || 'default' }
|
const selectedCamera = this.deviceService.getCameraSelected();
|
||||||
: false;
|
options.video = { deviceId: selectedCamera?.device || 'default' };
|
||||||
|
} else {
|
||||||
|
options.video = false;
|
||||||
|
}
|
||||||
} else if (videoDeviceId === false) {
|
} else if (videoDeviceId === false) {
|
||||||
options.video = false;
|
options.video = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -333,8 +436,8 @@ export class OpenViduService {
|
||||||
// Audio device
|
// Audio device
|
||||||
if (audioDeviceId === true) {
|
if (audioDeviceId === true) {
|
||||||
if (this.deviceService.hasAudioDeviceAvailable()) {
|
if (this.deviceService.hasAudioDeviceAvailable()) {
|
||||||
audioDeviceId = this.deviceService.getMicrophoneSelected()?.device || 'default';
|
const selectedMic = this.deviceService.getMicrophoneSelected();
|
||||||
(options.audio as AudioCaptureOptions).deviceId = audioDeviceId;
|
(options.audio as AudioCaptureOptions).deviceId = selectedMic?.device || 'default';
|
||||||
} else {
|
} else {
|
||||||
options.audio = false;
|
options.audio = false;
|
||||||
}
|
}
|
||||||
|
|
@ -358,11 +461,24 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply background processor to video track (initialized in disabled mode)
|
// Apply background processor to video track (initialized in disabled mode)
|
||||||
// This ensures the processor is attached before publishing for smooth transitions
|
// For browsers with modern processor support: attach processor immediately for smooth transitions
|
||||||
|
// For browsers without modern support: skip attachment, will be applied on-demand when effect is activated
|
||||||
const videoTrack = newLocalTracks.find((t) => t.kind === Track.Kind.Video) as LocalVideoTrack | undefined;
|
const videoTrack = newLocalTracks.find((t) => t.kind === Track.Kind.Video) as LocalVideoTrack | undefined;
|
||||||
if (videoTrack) {
|
if (videoTrack && supportsModernBackgroundProcessors()) {
|
||||||
|
if (this.isBackgroundProcessorSupported() && this.backgroundProcessor) {
|
||||||
|
try {
|
||||||
await videoTrack.setProcessor(this.backgroundProcessor);
|
await videoTrack.setProcessor(this.backgroundProcessor);
|
||||||
this.log.d('Background processor applied to newly created video track');
|
this.log.d('Background processor applied to newly created video track');
|
||||||
|
} catch (error: any) {
|
||||||
|
this.log.w('Failed to apply background processor (GPU may be disabled):', error?.message || error);
|
||||||
|
this._isBackgroundProcessorSupported.set(false);
|
||||||
|
// Continue without crashing - virtual background will be disabled
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.log.d('Background processor not supported (GPU disabled or not available)');
|
||||||
|
}
|
||||||
|
} else if (videoTrack && !supportsModernBackgroundProcessors()) {
|
||||||
|
this.log.d('Modern background processors not supported - will apply processor on-demand when effect is activated');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mute tracks if devices are disabled
|
// Mute tracks if devices are disabled
|
||||||
|
|
@ -593,6 +709,25 @@ export class OpenViduService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current video track from local tracks or room
|
||||||
|
* @returns LocalVideoTrack or undefined
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
private async getVideoTrack(): Promise<LocalVideoTrack | undefined> {
|
||||||
|
// First try to get from local tracks (prejoin state)
|
||||||
|
let videoTrack = this.localTracks.find((t) => t.kind === Track.Kind.Video) as LocalVideoTrack | undefined;
|
||||||
|
|
||||||
|
// If not found and room is connected, get from published tracks
|
||||||
|
if (!videoTrack && this.isRoomConnected()) {
|
||||||
|
const localParticipant = this.room.localParticipant;
|
||||||
|
const videoPublication = localParticipant.getTrackPublications().find((pub) => pub.kind === Track.Kind.Video);
|
||||||
|
videoTrack = videoPublication?.track as LocalVideoTrack | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return videoTrack;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts Livekit data from the provided token and returns an object containing the Livekit URL and room admin status.
|
* Extracts Livekit data from the provided token and returns an object containing the Livekit URL and room admin status.
|
||||||
* @param token - The token to extract Livekit data from.
|
* @param token - The token to extract Livekit data from.
|
||||||
|
|
|
||||||
|
|
@ -406,10 +406,9 @@ export class ParticipantService {
|
||||||
// Update Signal - create new reference to trigger reactivity
|
// Update Signal - create new reference to trigger reactivity
|
||||||
// The Observable will automatically emit via toObservable()
|
// The Observable will automatically emit via toObservable()
|
||||||
if (this.localParticipant) {
|
if (this.localParticipant) {
|
||||||
const updatedParticipant = Object.assign(
|
const updatedParticipant = Object.assign(Object.create(Object.getPrototypeOf(this.localParticipant)), {
|
||||||
Object.create(Object.getPrototypeOf(this.localParticipant)),
|
...this.localParticipant
|
||||||
{ ...this.localParticipant }
|
});
|
||||||
);
|
|
||||||
this.localParticipantWritableSignal.set(updatedParticipant);
|
this.localParticipantWritableSignal.set(updatedParticipant);
|
||||||
} else {
|
} else {
|
||||||
this.localParticipantWritableSignal.set(undefined);
|
this.localParticipantWritableSignal.set(undefined);
|
||||||
|
|
@ -460,6 +459,19 @@ export class ParticipantService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the participant with the given identity.
|
||||||
|
* @param identity
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
getParticipantByIdentity(identity: string): ParticipantModel | undefined {
|
||||||
|
if (this.localParticipant?.identity === identity) {
|
||||||
|
return this.localParticipant;
|
||||||
|
}
|
||||||
|
return this.remoteParticipants.find((p) => p.identity === identity);
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------ Remote Participants ------------------------------ */
|
/* ------------------------------ Remote Participants ------------------------------ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { computed, Injectable, Signal } from '@angular/core';
|
||||||
import { SwitchBackgroundProcessorOptions } from '@livekit/track-processors';
|
import { SwitchBackgroundProcessorOptions } from '@livekit/track-processors';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { BackgroundEffect, EffectType } from '../../models/background-effect.model';
|
import { BackgroundEffect, EffectType } from '../../models/background-effect.model';
|
||||||
|
|
@ -59,6 +59,14 @@ export class VirtualBackgroundService {
|
||||||
return this.backgrounds;
|
return this.backgrounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computed signal that checks if virtual background is supported (requires GPU).
|
||||||
|
* Reactively tracks the support status from OpenViduService.
|
||||||
|
*/
|
||||||
|
readonly isVirtualBackgroundSupported: Signal<boolean> = computed(() =>
|
||||||
|
this.openviduService.isBackgroundProcessorSupported()
|
||||||
|
);
|
||||||
|
|
||||||
isBackgroundApplied(): boolean {
|
isBackgroundApplied(): boolean {
|
||||||
const bgSelected = this.backgroundIdSelected.getValue();
|
const bgSelected = this.backgroundIdSelected.getValue();
|
||||||
return !!bgSelected && bgSelected !== 'no_effect';
|
return !!bgSelected && bgSelected !== 'no_effect';
|
||||||
|
|
@ -80,6 +88,12 @@ export class VirtualBackgroundService {
|
||||||
* The background processor is centralized in OpenViduService for consistency.
|
* The background processor is centralized in OpenViduService for consistency.
|
||||||
*/
|
*/
|
||||||
async applyBackground(bg: BackgroundEffect) {
|
async applyBackground(bg: BackgroundEffect) {
|
||||||
|
// Check if virtual background is supported before proceeding
|
||||||
|
if (!this.isVirtualBackgroundSupported()) {
|
||||||
|
this.log.w('Virtual background not supported (GPU disabled). Skipping background application.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If the background is already applied, do nothing
|
// If the background is already applied, do nothing
|
||||||
if (this.backgroundIsAlreadyApplied(bg.id)) return;
|
if (this.backgroundIsAlreadyApplied(bg.id)) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
services:
|
services:
|
||||||
|
|
||||||
caddy-proxy:
|
caddy-proxy:
|
||||||
image: docker.io/openvidu/openvidu-caddy-local:3.5.0
|
image: docker.io/openvidu/openvidu-caddy-local:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|
@ -26,6 +26,7 @@ services:
|
||||||
- 7443:7443
|
- 7443:7443
|
||||||
- 7880:7880
|
- 7880:7880
|
||||||
- 9443:9443
|
- 9443:9443
|
||||||
|
- 9080:9080
|
||||||
depends_on:
|
depends_on:
|
||||||
setup:
|
setup:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
@ -86,7 +87,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
dashboard:
|
dashboard:
|
||||||
image: docker.io/openvidu/openvidu-dashboard:3.5.0
|
image: docker.io/openvidu/openvidu-dashboard:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
- SERVER_PORT=5000
|
- SERVER_PORT=5000
|
||||||
|
|
@ -100,7 +101,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
openvidu:
|
openvidu:
|
||||||
image: docker.io/openvidu/openvidu-server:3.5.0
|
image: docker.io/openvidu/openvidu-server:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|
@ -121,7 +122,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
ingress:
|
ingress:
|
||||||
image: docker.io/openvidu/ingress:3.5.0
|
image: docker.io/openvidu/ingress:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|
@ -139,7 +140,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
egress:
|
egress:
|
||||||
image: docker.io/openvidu/egress:3.5.0
|
image: docker.io/openvidu/egress:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|
@ -154,7 +155,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
operator:
|
operator:
|
||||||
image: docker.io/openvidu/openvidu-operator:3.5.0
|
image: docker.io/openvidu/openvidu-operator:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
|
@ -177,10 +178,8 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
openvidu-meet:
|
openvidu-meet:
|
||||||
image: docker.io/openvidu/openvidu-meet:3.5.0
|
image: docker.io/openvidu/openvidu-meet:main
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
ports:
|
|
||||||
- 9080:6080
|
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -218,7 +217,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
openvidu-meet-init:
|
openvidu-meet-init:
|
||||||
image: docker.io/openvidu/openvidu-operator:3.5.0
|
image: docker.io/openvidu/openvidu-operator:main
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
environment:
|
environment:
|
||||||
- MODE=local-ready-check
|
- MODE=local-ready-check
|
||||||
|
|
|
||||||
|
|
@ -60,21 +60,6 @@ Parameters:
|
||||||
AllowedPattern: '^[A-Za-z0-9, =_.\-]*$' # Allows letters, numbers, comma, space, underscore, dot, equals, and hyphen
|
AllowedPattern: '^[A-Za-z0-9, =_.\-]*$' # Allows letters, numbers, comma, space, underscore, dot, equals, and hyphen
|
||||||
ConstraintDescription: Must be a comma-separated list of flags (for example, --flag=value, --bool-flag).
|
ConstraintDescription: Must be a comma-separated list of flags (for example, --flag=value, --bool-flag).
|
||||||
|
|
||||||
TurnDomainName:
|
|
||||||
Description: '(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls'
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
TurnOwnPublicCertificate:
|
|
||||||
Description: "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
TurnOwnPrivateCertificate:
|
|
||||||
Description: "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
# EC2 Instance configuration
|
# EC2 Instance configuration
|
||||||
InstanceType:
|
InstanceType:
|
||||||
Description: "Specifies the EC2 instance type for your OpenVidu instance"
|
Description: "Specifies the EC2 instance type for your OpenVidu instance"
|
||||||
|
|
@ -456,12 +441,6 @@ Metadata:
|
||||||
default: "(Optional) Additional Installer Flags"
|
default: "(Optional) Additional Installer Flags"
|
||||||
Parameters:
|
Parameters:
|
||||||
- AdditionalInstallFlags
|
- AdditionalInstallFlags
|
||||||
- Label:
|
|
||||||
default: (Optional) TURN server configuration with TLS
|
|
||||||
Parameters:
|
|
||||||
- TurnDomainName
|
|
||||||
- TurnOwnPublicCertificate
|
|
||||||
- TurnOwnPrivateCertificate
|
|
||||||
|
|
||||||
Conditions:
|
Conditions:
|
||||||
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ]
|
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ]
|
||||||
|
|
@ -515,7 +494,6 @@ Resources:
|
||||||
"GRAFANA_URL": "none",
|
"GRAFANA_URL": "none",
|
||||||
"MINIO_URL": "none",
|
"MINIO_URL": "none",
|
||||||
"DOMAIN_NAME": "none",
|
"DOMAIN_NAME": "none",
|
||||||
"LIVEKIT_TURN_DOMAIN_NAME": "none",
|
|
||||||
"REDIS_PASSWORD": "none",
|
"REDIS_PASSWORD": "none",
|
||||||
"MONGO_ADMIN_USERNAME": "none",
|
"MONGO_ADMIN_USERNAME": "none",
|
||||||
"MONGO_ADMIN_PASSWORD": "none",
|
"MONGO_ADMIN_PASSWORD": "none",
|
||||||
|
|
@ -618,7 +596,7 @@ Resources:
|
||||||
'/usr/local/bin/install.sh':
|
'/usr/local/bin/install.sh':
|
||||||
content: !Sub |
|
content: !Sub |
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
YQ_VERSION=v4.44.5
|
YQ_VERSION=v4.44.5
|
||||||
|
|
||||||
|
|
@ -644,7 +622,6 @@ Resources:
|
||||||
PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname)
|
PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname)
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io
|
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io"
|
|
||||||
else
|
else
|
||||||
DOMAIN=${DomainName}
|
DOMAIN=${DomainName}
|
||||||
fi
|
fi
|
||||||
|
|
@ -717,18 +694,6 @@ Resources:
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${!TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${!TURN_DOMAIN_NAME_SSLIP_IO}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${TurnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${TurnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${CertificateType}" == "selfsigned" ]]; then
|
if [[ "${CertificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -748,18 +713,6 @@ Resources:
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${TurnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${TurnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${TurnOwnPrivateCertificate}
|
|
||||||
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the final command with all arguments
|
# Construct the final command with all arguments
|
||||||
|
|
@ -856,12 +809,6 @@ Resources:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(echo $SHARED_SECRET | jq -r .LIVEKIT_TURN_DOMAIN_NAME)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${!CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Replace rest of the values
|
# Replace rest of the values
|
||||||
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!CONFIG_DIR}/openvidu.env"
|
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!CONFIG_DIR}/openvidu.env"
|
||||||
sed -i "s/MONGO_ADMIN_USERNAME=.*/MONGO_ADMIN_USERNAME=$(echo $SHARED_SECRET | jq -r .MONGO_ADMIN_USERNAME)/" "${!CONFIG_DIR}/openvidu.env"
|
sed -i "s/MONGO_ADMIN_USERNAME=.*/MONGO_ADMIN_USERNAME=$(echo $SHARED_SECRET | jq -r .MONGO_ADMIN_USERNAME)/" "${!CONFIG_DIR}/openvidu.env"
|
||||||
|
|
@ -918,7 +865,6 @@ Resources:
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"REDIS_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"REDIS_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"LIVEKIT_TURN_DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_USERNAME": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_USERNAME": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_REPLICA_SET_KEY": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_REPLICA_SET_KEY": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
|
|
@ -1114,7 +1060,7 @@ Resources:
|
||||||
BlockDeviceMappings:
|
BlockDeviceMappings:
|
||||||
- DeviceName: /dev/sda1
|
- DeviceName: /dev/sda1
|
||||||
Ebs:
|
Ebs:
|
||||||
VolumeType: gp2
|
VolumeType: gp3
|
||||||
DeleteOnTermination: true
|
DeleteOnTermination: true
|
||||||
VolumeSize: 200
|
VolumeSize: 200
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,6 @@ param ownPublicCertificate string = ''
|
||||||
@description('If certificate type is \'owncert\', this parameter will be used to specify the private certificate in base64 format')
|
@description('If certificate type is \'owncert\', this parameter will be used to specify the private certificate in base64 format')
|
||||||
param ownPrivateCertificate string = ''
|
param ownPrivateCertificate string = ''
|
||||||
|
|
||||||
@description('(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls')
|
|
||||||
param turnDomainName string = ''
|
|
||||||
|
|
||||||
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified. Provide in base64 format.')
|
|
||||||
param turnOwnPublicCertificate string = ''
|
|
||||||
|
|
||||||
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified. Provide in base64 format.')
|
|
||||||
param turnOwnPrivateCertificate string = ''
|
|
||||||
|
|
||||||
@description('Initial password for the \'admin\' user in OpenVidu Meet. If not provided, a random password will be generated.')
|
@description('Initial password for the \'admin\' user in OpenVidu Meet. If not provided, a random password will be generated.')
|
||||||
@secure()
|
@secure()
|
||||||
param initialMeetAdminPassword string = ''
|
param initialMeetAdminPassword string = ''
|
||||||
|
|
@ -161,12 +152,9 @@ resource openviduSharedInfo 'Microsoft.KeyVault/vaults@2023-07-01' = {
|
||||||
var stringInterpolationParams = {
|
var stringInterpolationParams = {
|
||||||
publicIPId: publicIPId
|
publicIPId: publicIPId
|
||||||
domainName: domainName
|
domainName: domainName
|
||||||
turnDomainName: turnDomainName
|
|
||||||
certificateType: certificateType
|
certificateType: certificateType
|
||||||
ownPublicCertificate: ownPublicCertificate
|
ownPublicCertificate: ownPublicCertificate
|
||||||
ownPrivateCertificate: ownPrivateCertificate
|
ownPrivateCertificate: ownPrivateCertificate
|
||||||
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
||||||
initialMeetAdminPassword: initialMeetAdminPassword
|
initialMeetAdminPassword: initialMeetAdminPassword
|
||||||
initialMeetApiKey: initialMeetApiKey
|
initialMeetApiKey: initialMeetApiKey
|
||||||
keyVaultName: keyVaultName
|
keyVaultName: keyVaultName
|
||||||
|
|
@ -175,7 +163,7 @@ var stringInterpolationParams = {
|
||||||
|
|
||||||
var installScriptTemplate = '''
|
var installScriptTemplate = '''
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
|
|
||||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||||
|
|
@ -198,7 +186,6 @@ if [[ "${domainName}" == '' ]]; then
|
||||||
|
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
|
||||||
else
|
else
|
||||||
DOMAIN=${domainName}
|
DOMAIN=${domainName}
|
||||||
fi
|
fi
|
||||||
|
|
@ -272,19 +259,6 @@ if [[ "${additionalInstallFlags}" != "" ]]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Turn with TLS
|
|
||||||
if [[ "${turnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${turnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${TURN_DOMAIN_NAME_SSLIP_IO}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${certificateType}" == "selfsigned" ]]; then
|
if [[ "${certificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -304,18 +278,6 @@ else
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${turnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${turnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${turnOwnPrivateCertificate}
|
|
||||||
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the final command with all arguments
|
# Construct the final command with all arguments
|
||||||
|
|
@ -374,12 +336,6 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --query value -o tsv)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the rest of the values
|
# Get the rest of the values
|
||||||
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
||||||
export MONGO_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --query value -o tsv)
|
export MONGO_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --query value -o tsv)
|
||||||
|
|
@ -452,7 +408,6 @@ CONFIG_DIR="${INSTALL_DIR}/config"
|
||||||
# Get current values of the config
|
# Get current values of the config
|
||||||
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${CONFIG_DIR}/openvidu.env")"
|
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${CONFIG_DIR}/openvidu.env")"
|
||||||
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CONFIG_DIR}/openvidu.env")"
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CONFIG_DIR}/openvidu.env")"
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${CONFIG_DIR}/openvidu.env")"
|
|
||||||
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "${CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "${CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "${CONFIG_DIR}/openvidu.env")"
|
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "${CONFIG_DIR}/openvidu.env")"
|
||||||
|
|
@ -475,7 +430,6 @@ ENABLED_MODULES="$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES "${CO
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --value $LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-PASSWORD --value $MONGO_ADMIN_PASSWORD
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-PASSWORD --value $MONGO_ADMIN_PASSWORD
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-REPLICA-SET-KEY --value $MONGO_REPLICA_SET_KEY
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-REPLICA-SET-KEY --value $MONGO_REPLICA_SET_KEY
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -331,70 +331,6 @@
|
||||||
"visible": true
|
"visible": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "parameters TURN",
|
|
||||||
"label": "(Optional) TURN server configuration with TLS",
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"name": "turnDomainName",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Domain Name",
|
|
||||||
"subLabel": "\n(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": []
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "turnOwnPublicCertificate",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Own Public Certificate",
|
|
||||||
"subLabel": "\n(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format.",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPublicCertificate)), true)]",
|
|
||||||
"message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "turnOwnPrivateCertificate",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Own Private Certificate",
|
|
||||||
"subLabel": "\n(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format.",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPrivateCertificate)), true)]",
|
|
||||||
"message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -409,9 +345,6 @@
|
||||||
"domainName": "[steps('parameters SSL').domainName]",
|
"domainName": "[steps('parameters SSL').domainName]",
|
||||||
"ownPublicCertificate": "[steps('parameters SSL').ownPublicCertificate]",
|
"ownPublicCertificate": "[steps('parameters SSL').ownPublicCertificate]",
|
||||||
"ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]",
|
"ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]",
|
||||||
"turnDomainName": "[steps('parameters TURN').turnDomainName]",
|
|
||||||
"turnOwnPublicCertificate": "[steps('parameters TURN').turnOwnPublicCertificate]",
|
|
||||||
"turnOwnPrivateCertificate": "[steps('parameters TURN').turnOwnPrivateCertificate]",
|
|
||||||
"initialMeetAdminPassword": "[steps('parameters MEET').initialMeetAdminPassword]",
|
"initialMeetAdminPassword": "[steps('parameters MEET').initialMeetAdminPassword]",
|
||||||
"initialMeetApiKey": "[steps('parameters MEET').initialMeetApiKey]",
|
"initialMeetApiKey": "[steps('parameters MEET').initialMeetApiKey]",
|
||||||
"instanceType": "[steps('parameters INSTANCE').instanceType]",
|
"instanceType": "[steps('parameters INSTANCE').instanceType]",
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ resource "google_secret_manager_secret" "openvidu_shared_info" {
|
||||||
for_each = toset([
|
for_each = toset([
|
||||||
"OPENVIDU_URL", "MEET_INITIAL_ADMIN_USER", "MEET_INITIAL_ADMIN_PASSWORD",
|
"OPENVIDU_URL", "MEET_INITIAL_ADMIN_USER", "MEET_INITIAL_ADMIN_PASSWORD",
|
||||||
"MEET_INITIAL_API_KEY", "LIVEKIT_URL", "LIVEKIT_API_KEY", "LIVEKIT_API_SECRET",
|
"MEET_INITIAL_API_KEY", "LIVEKIT_URL", "LIVEKIT_API_KEY", "LIVEKIT_API_SECRET",
|
||||||
"DASHBOARD_URL", "GRAFANA_URL", "MINIO_URL", "DOMAIN_NAME", "LIVEKIT_TURN_DOMAIN_NAME",
|
"DASHBOARD_URL", "GRAFANA_URL", "MINIO_URL", "DOMAIN_NAME",
|
||||||
"REDIS_PASSWORD", "MONGO_ADMIN_USERNAME", "MONGO_ADMIN_PASSWORD", "MONGO_REPLICA_SET_KEY",
|
"REDIS_PASSWORD", "MONGO_ADMIN_USERNAME", "MONGO_ADMIN_PASSWORD", "MONGO_REPLICA_SET_KEY",
|
||||||
"MINIO_ACCESS_KEY", "MINIO_SECRET_KEY", "DASHBOARD_ADMIN_USERNAME", "DASHBOARD_ADMIN_PASSWORD",
|
"MINIO_ACCESS_KEY", "MINIO_SECRET_KEY", "DASHBOARD_ADMIN_USERNAME", "DASHBOARD_ADMIN_PASSWORD",
|
||||||
"GRAFANA_ADMIN_USERNAME", "GRAFANA_ADMIN_PASSWORD", "ENABLED_MODULES"
|
"GRAFANA_ADMIN_USERNAME", "GRAFANA_ADMIN_PASSWORD", "ENABLED_MODULES"
|
||||||
|
|
@ -125,9 +125,6 @@ resource "google_compute_instance" "openvidu_server" {
|
||||||
ownPublicCertificate = var.ownPublicCertificate
|
ownPublicCertificate = var.ownPublicCertificate
|
||||||
ownPrivateCertificate = var.ownPrivateCertificate
|
ownPrivateCertificate = var.ownPrivateCertificate
|
||||||
additionalInstallFlags = var.additionalInstallFlags
|
additionalInstallFlags = var.additionalInstallFlags
|
||||||
turnDomainName = var.turnDomainName
|
|
||||||
turnOwnPublicCertificate = var.turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate = var.turnOwnPrivateCertificate
|
|
||||||
bucketName = local.isEmpty ? google_storage_bucket.bucket[0].name : var.bucketName
|
bucketName = local.isEmpty ? google_storage_bucket.bucket[0].name : var.bucketName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +148,7 @@ locals {
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
YQ_VERSION=v4.44.5
|
YQ_VERSION=v4.44.5
|
||||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||||
|
|
@ -183,7 +180,6 @@ if [[ "${var.domainName}" == "" ]]; then
|
||||||
EXTERNAL_IP=$(get_meta "instance/network-interfaces/0/access-configs/0/external-ip")
|
EXTERNAL_IP=$(get_meta "instance/network-interfaces/0/access-configs/0/external-ip")
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO=turn-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
|
||||||
else
|
else
|
||||||
DOMAIN="${var.domainName}"
|
DOMAIN="${var.domainName}"
|
||||||
fi
|
fi
|
||||||
|
|
@ -255,19 +251,6 @@ if [[ "${var.additionalInstallFlags}" != "" ]]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Turn with TLS
|
|
||||||
if [[ "$TURN_DOMAIN_NAME_SSLIP_IO" != "" ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "$TURN_DOMAIN_NAME_SSLIP_IO")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${var.turnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${var.turnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -286,17 +269,6 @@ else
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${var.turnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${var.turnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${var.turnOwnPrivateCertificate}
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Final command
|
# Final command
|
||||||
|
|
@ -395,12 +367,6 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(gcloud secrets versions access latest --secret=LIVEKIT_TURN_DOMAIN_NAME)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "$${CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the rest of the values
|
# Get the rest of the values
|
||||||
export REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
export REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
||||||
export MONGO_ADMIN_USERNAME=$(gcloud secrets versions access latest --secret=MONGO_ADMIN_USERNAME)
|
export MONGO_ADMIN_USERNAME=$(gcloud secrets versions access latest --secret=MONGO_ADMIN_USERNAME)
|
||||||
|
|
@ -471,7 +437,6 @@ CONFIG_DIR="$${INSTALL_DIR}/config"
|
||||||
# Get current values of the config
|
# Get current values of the config
|
||||||
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "$${CONFIG_DIR}/openvidu.env")"
|
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "$${CONFIG_DIR}/openvidu.env")"
|
||||||
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "$${CONFIG_DIR}/openvidu.env")"
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "$${CONFIG_DIR}/openvidu.env")"
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "$${CONFIG_DIR}/openvidu.env")"
|
|
||||||
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "$${CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "$${CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "$${CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "$${CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "$${CONFIG_DIR}/openvidu.env")"
|
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "$${CONFIG_DIR}/openvidu.env")"
|
||||||
|
|
@ -493,7 +458,6 @@ ENABLED_MODULES="$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES "$${C
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
echo -n "$REDIS_PASSWORD" | gcloud secrets versions add REDIS_PASSWORD --data-file=-
|
echo -n "$REDIS_PASSWORD" | gcloud secrets versions add REDIS_PASSWORD --data-file=-
|
||||||
echo -n "$DOMAIN_NAME" | gcloud secrets versions add DOMAIN_NAME --data-file=-
|
echo -n "$DOMAIN_NAME" | gcloud secrets versions add DOMAIN_NAME --data-file=-
|
||||||
echo -n "$LIVEKIT_TURN_DOMAIN_NAME" | gcloud secrets versions add LIVEKIT_TURN_DOMAIN_NAME --data-file=-
|
|
||||||
echo -n "$MONGO_ADMIN_USERNAME" | gcloud secrets versions add MONGO_ADMIN_USERNAME --data-file=-
|
echo -n "$MONGO_ADMIN_USERNAME" | gcloud secrets versions add MONGO_ADMIN_USERNAME --data-file=-
|
||||||
echo -n "$MONGO_ADMIN_PASSWORD" | gcloud secrets versions add MONGO_ADMIN_PASSWORD --data-file=-
|
echo -n "$MONGO_ADMIN_PASSWORD" | gcloud secrets versions add MONGO_ADMIN_PASSWORD --data-file=-
|
||||||
echo -n "$MONGO_REPLICA_SET_KEY" | gcloud secrets versions add MONGO_REPLICA_SET_KEY --data-file=-
|
echo -n "$MONGO_REPLICA_SET_KEY" | gcloud secrets versions add MONGO_REPLICA_SET_KEY --data-file=-
|
||||||
|
|
|
||||||
|
|
@ -106,21 +106,3 @@ variable "additionalInstallFlags" {
|
||||||
error_message = "Must be a comma-separated list of flags (for example, --flag=value, --bool-flag)."
|
error_message = "Must be a comma-separated list of flags (for example, --flag=value, --bool-flag)."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "turnDomainName" {
|
|
||||||
description = "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls"
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "turnOwnPublicCertificate" {
|
|
||||||
description = "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "turnOwnPrivateCertificate" {
|
|
||||||
description = "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
||||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
||||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.5.0}"
|
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
||||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
||||||
|
|
@ -19,7 +19,7 @@ export OPENVIDU_MEET_SERVER_IMAGE="${OPENVIDU_MEET_SERVER_IMAGE:-docker.io/openv
|
||||||
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing:${OPENVIDU_VERSION}}"
|
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-cloud:${OPENVIDU_VERSION}}"
|
||||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${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 LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
||||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
||||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.5.0}"
|
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
||||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
||||||
|
|
@ -19,7 +19,7 @@ export OPENVIDU_MEET_SERVER_IMAGE="${OPENVIDU_MEET_SERVER_IMAGE:-docker.io/openv
|
||||||
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing:${OPENVIDU_VERSION}}"
|
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-cloud:${OPENVIDU_VERSION}}"
|
||||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${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 LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
||||||
|
|
|
||||||
|
|
@ -60,21 +60,6 @@ Parameters:
|
||||||
AllowedPattern: '^[A-Za-z0-9, =_.\-]*$' # Allows letters, numbers, comma, space, underscore, dot, equals, and hyphen
|
AllowedPattern: '^[A-Za-z0-9, =_.\-]*$' # Allows letters, numbers, comma, space, underscore, dot, equals, and hyphen
|
||||||
ConstraintDescription: Must be a comma-separated list of flags (for example, --flag=value, --bool-flag).
|
ConstraintDescription: Must be a comma-separated list of flags (for example, --flag=value, --bool-flag).
|
||||||
|
|
||||||
TurnDomainName:
|
|
||||||
Description: '(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls'
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
TurnOwnPublicCertificate:
|
|
||||||
Description: "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
TurnOwnPrivateCertificate:
|
|
||||||
Description: "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
OpenViduLicense:
|
OpenViduLicense:
|
||||||
Description: "Visit https://openvidu.io/account"
|
Description: "Visit https://openvidu.io/account"
|
||||||
Type: String
|
Type: String
|
||||||
|
|
@ -861,13 +846,6 @@ Metadata:
|
||||||
default: "(Optional) Additional Installer Flags"
|
default: "(Optional) Additional Installer Flags"
|
||||||
Parameters:
|
Parameters:
|
||||||
- AdditionalInstallFlags
|
- AdditionalInstallFlags
|
||||||
- Label:
|
|
||||||
default: (Optional) TURN server configuration with TLS
|
|
||||||
Parameters:
|
|
||||||
- TurnDomainName
|
|
||||||
- TurnOwnPublicCertificate
|
|
||||||
- TurnOwnPrivateCertificate
|
|
||||||
|
|
||||||
Conditions:
|
Conditions:
|
||||||
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ]
|
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ]
|
||||||
PublicElasticIPAbsent: !Equals [!Ref PublicElasticIP, ""]
|
PublicElasticIPAbsent: !Equals [!Ref PublicElasticIP, ""]
|
||||||
|
|
@ -931,7 +909,6 @@ Resources:
|
||||||
"GRAFANA_URL": "none",
|
"GRAFANA_URL": "none",
|
||||||
"MINIO_URL": "none",
|
"MINIO_URL": "none",
|
||||||
"DOMAIN_NAME": "none",
|
"DOMAIN_NAME": "none",
|
||||||
"LIVEKIT_TURN_DOMAIN_NAME": "none",
|
|
||||||
"OPENVIDU_PRO_LICENSE": "none",
|
"OPENVIDU_PRO_LICENSE": "none",
|
||||||
"OPENVIDU_RTC_ENGINE": "none",
|
"OPENVIDU_RTC_ENGINE": "none",
|
||||||
"REDIS_PASSWORD": "none",
|
"REDIS_PASSWORD": "none",
|
||||||
|
|
@ -1136,7 +1113,7 @@ Resources:
|
||||||
content: !Sub |
|
content: !Sub |
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
YQ_VERSION=v4.44.5
|
YQ_VERSION=v4.44.5
|
||||||
|
|
||||||
|
|
@ -1163,7 +1140,6 @@ Resources:
|
||||||
PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname)
|
PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname)
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io
|
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io"
|
|
||||||
else
|
else
|
||||||
DOMAIN=${DomainName}
|
DOMAIN=${DomainName}
|
||||||
fi
|
fi
|
||||||
|
|
@ -1190,7 +1166,7 @@ Resources:
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RETRY_COUNT=RETRY_COUNT+1
|
RETRY_COUNT=$((RETRY_COUNT+1))
|
||||||
if [[ $RETRY_COUNT -ge $MAX_RETRIES ]]; then
|
if [[ $RETRY_COUNT -ge $MAX_RETRIES ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -1271,19 +1247,6 @@ Resources:
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Turn with TLS
|
|
||||||
if [[ "${!TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${!TURN_DOMAIN_NAME_SSLIP_IO}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${TurnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${TurnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${CertificateType}" == "selfsigned" ]]; then
|
if [[ "${CertificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -1303,18 +1266,6 @@ Resources:
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${TurnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${TurnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${TurnOwnPrivateCertificate}
|
|
||||||
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the final command with all arguments
|
# Construct the final command with all arguments
|
||||||
|
|
@ -1412,12 +1363,6 @@ Resources:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(echo $SHARED_SECRET | jq -r .LIVEKIT_TURN_DOMAIN_NAME)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${!CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Replace rest of the values
|
# Replace rest of the values
|
||||||
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!MASTER_NODE_CONFIG_DIR}/master_node.env"
|
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!MASTER_NODE_CONFIG_DIR}/master_node.env"
|
||||||
sed -i "s/OPENVIDU_RTC_ENGINE=.*/OPENVIDU_RTC_ENGINE=$(echo $SHARED_SECRET | jq -r .OPENVIDU_RTC_ENGINE)/" "${!CLUSTER_CONFIG_DIR}/openvidu.env"
|
sed -i "s/OPENVIDU_RTC_ENGINE=.*/OPENVIDU_RTC_ENGINE=$(echo $SHARED_SECRET | jq -r .OPENVIDU_RTC_ENGINE)/" "${!CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
|
@ -1478,7 +1423,6 @@ Resources:
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"REDIS_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${!MASTER_NODE_CONFIG_DIR}/master_node.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"REDIS_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${!MASTER_NODE_CONFIG_DIR}/master_node.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"LIVEKIT_TURN_DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_RTC_ENGINE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_RTC_ENGINE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_PRO_LICENSE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_PRO_LICENSE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_USERNAME": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_USERNAME": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
|
|
@ -1679,7 +1623,7 @@ Resources:
|
||||||
BlockDeviceMappings:
|
BlockDeviceMappings:
|
||||||
- DeviceName: /dev/sda1
|
- DeviceName: /dev/sda1
|
||||||
Ebs:
|
Ebs:
|
||||||
VolumeType: gp2
|
VolumeType: gp3
|
||||||
DeleteOnTermination: true
|
DeleteOnTermination: true
|
||||||
VolumeSize: 200
|
VolumeSize: 200
|
||||||
|
|
||||||
|
|
@ -1731,7 +1675,7 @@ Resources:
|
||||||
if [[ "$SHARED_SECRET" != "none" ]]; then
|
if [[ "$SHARED_SECRET" != "none" ]]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
RETRY_COUNT=RETRY_COUNT+1
|
RETRY_COUNT=$((RETRY_COUNT+1))
|
||||||
if [[ $RETRY_COUNT -ge $MAX_RETRIES ]]; then
|
if [[ $RETRY_COUNT -ge $MAX_RETRIES ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -1905,7 +1849,7 @@ Resources:
|
||||||
BlockDeviceMappings:
|
BlockDeviceMappings:
|
||||||
- DeviceName: /dev/sda1
|
- DeviceName: /dev/sda1
|
||||||
Ebs:
|
Ebs:
|
||||||
VolumeType: gp2
|
VolumeType: gp3
|
||||||
DeleteOnTermination: true
|
DeleteOnTermination: true
|
||||||
VolumeSize: 50
|
VolumeSize: 50
|
||||||
|
|
||||||
|
|
@ -2031,7 +1975,9 @@ Resources:
|
||||||
- Effect: Allow
|
- Effect: Allow
|
||||||
Action:
|
Action:
|
||||||
- ssm:StartAutomationExecution
|
- ssm:StartAutomationExecution
|
||||||
Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${StopMediaNodeAutomationDocument}:$DEFAULT
|
Resource:
|
||||||
|
- !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-execution/*
|
||||||
|
- !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:document/${StopMediaNodeAutomationDocument}
|
||||||
PolicyName: !Sub StopMediaNodeCloudWatchEventPolicy-${AWS::Region}-${AWS::StackName}
|
PolicyName: !Sub StopMediaNodeCloudWatchEventPolicy-${AWS::Region}-${AWS::StackName}
|
||||||
- PolicyDocument:
|
- PolicyDocument:
|
||||||
Version: '2012-10-17'
|
Version: '2012-10-17'
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,6 @@ param ownPublicCertificate string = ''
|
||||||
@description('If certificate type is \'owncert\', this parameter will be used to specify the private certificate in base64 format')
|
@description('If certificate type is \'owncert\', this parameter will be used to specify the private certificate in base64 format')
|
||||||
param ownPrivateCertificate string = ''
|
param ownPrivateCertificate string = ''
|
||||||
|
|
||||||
@description('(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls')
|
|
||||||
param turnDomainName string = ''
|
|
||||||
|
|
||||||
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified. Provide in base64 format.')
|
|
||||||
param turnOwnPublicCertificate string = ''
|
|
||||||
|
|
||||||
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified. Provide in base64 format.')
|
|
||||||
param turnOwnPrivateCertificate string = ''
|
|
||||||
|
|
||||||
@description('Visit https://openvidu.io/account')
|
@description('Visit https://openvidu.io/account')
|
||||||
@secure()
|
@secure()
|
||||||
param openviduLicense string
|
param openviduLicense string
|
||||||
|
|
@ -207,12 +198,9 @@ resource openviduSharedInfo 'Microsoft.KeyVault/vaults@2023-07-01' = {
|
||||||
var stringInterpolationParamsMaster = {
|
var stringInterpolationParamsMaster = {
|
||||||
publicIPId: publicIPId
|
publicIPId: publicIPId
|
||||||
domainName: domainName
|
domainName: domainName
|
||||||
turnDomainName: turnDomainName
|
|
||||||
certificateType: certificateType
|
certificateType: certificateType
|
||||||
ownPublicCertificate: ownPublicCertificate
|
ownPublicCertificate: ownPublicCertificate
|
||||||
ownPrivateCertificate: ownPrivateCertificate
|
ownPrivateCertificate: ownPrivateCertificate
|
||||||
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
||||||
openviduLicense: openviduLicense
|
openviduLicense: openviduLicense
|
||||||
rtcEngine: rtcEngine
|
rtcEngine: rtcEngine
|
||||||
initialMeetAdminPassword: initialMeetAdminPassword
|
initialMeetAdminPassword: initialMeetAdminPassword
|
||||||
|
|
@ -223,7 +211,7 @@ var stringInterpolationParamsMaster = {
|
||||||
|
|
||||||
var installScriptTemplateMaster = '''
|
var installScriptTemplateMaster = '''
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
|
|
||||||
# Assume azure cli is installed
|
# Assume azure cli is installed
|
||||||
|
|
@ -247,7 +235,6 @@ if [[ "${domainName}" == '' ]]; then
|
||||||
|
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
|
||||||
else
|
else
|
||||||
DOMAIN=${domainName}
|
DOMAIN=${domainName}
|
||||||
fi
|
fi
|
||||||
|
|
@ -361,19 +348,6 @@ if [[ "${additionalInstallFlags}" != "" ]]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Turn with TLS
|
|
||||||
if [[ "${turnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${turnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${TURN_DOMAIN_NAME_SSLIP_IO}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${certificateType}" == "selfsigned" ]]; then
|
if [[ "${certificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -393,18 +367,6 @@ else
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${turnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${turnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${turnOwnPrivateCertificate}
|
|
||||||
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the final command with all arguments
|
# Construct the final command with all arguments
|
||||||
|
|
@ -462,12 +424,6 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --query value -o tsv)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the rest of the values
|
# Get the rest of the values
|
||||||
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
||||||
export OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
export OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
||||||
|
|
@ -542,7 +498,6 @@ MASTER_NODE_CONFIG_DIR="${INSTALL_DIR}/config/node"
|
||||||
# Get current values of the config
|
# Get current values of the config
|
||||||
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${MASTER_NODE_CONFIG_DIR}/master_node.env")"
|
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${MASTER_NODE_CONFIG_DIR}/master_node.env")"
|
||||||
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
||||||
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
|
@ -566,7 +521,6 @@ ENABLED_MODULES="$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES "${CL
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --value $LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --value $OPENVIDU_RTC_ENGINE
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --value $OPENVIDU_RTC_ENGINE
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --value $OPENVIDU_PRO_LICENSE
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --value $OPENVIDU_PRO_LICENSE
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -505,70 +505,6 @@
|
||||||
"visible": true
|
"visible": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "parameters TURN",
|
|
||||||
"label": "(Optional) TURN server configuration with TLS",
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"name": "turnDomainName",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Domain Name",
|
|
||||||
"subLabel": "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": []
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "turnOwnPublicCertificate",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Own Public Certificate",
|
|
||||||
"subLabel": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format.",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPublicCertificate)), true)]",
|
|
||||||
"message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "turnOwnPrivateCertificate",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Own Private Certificate",
|
|
||||||
"subLabel": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format.",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPrivateCertificate)), true)]",
|
|
||||||
"message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -583,9 +519,6 @@
|
||||||
"domainName": "[steps('parameters SSL').domainName]",
|
"domainName": "[steps('parameters SSL').domainName]",
|
||||||
"ownPublicCertificate": "[steps('parameters SSL').ownPublicCertificate]",
|
"ownPublicCertificate": "[steps('parameters SSL').ownPublicCertificate]",
|
||||||
"ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]",
|
"ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]",
|
||||||
"turnDomainName": "[steps('parameters TURN').turnDomainName]",
|
|
||||||
"turnOwnPublicCertificate": "[steps('parameters TURN').turnOwnPublicCertificate]",
|
|
||||||
"turnOwnPrivateCertificate": "[steps('parameters TURN').turnOwnPrivateCertificate]",
|
|
||||||
"openviduLicense": "[steps('parameters OPENVIDU').openviduLicense]",
|
"openviduLicense": "[steps('parameters OPENVIDU').openviduLicense]",
|
||||||
"rtcEngine": "[steps('parameters OPENVIDU').rtcEngine]",
|
"rtcEngine": "[steps('parameters OPENVIDU').rtcEngine]",
|
||||||
"initialMeetAdminPassword": "[steps('parameters MEET').initialMeetAdminPassword]",
|
"initialMeetAdminPassword": "[steps('parameters MEET').initialMeetAdminPassword]",
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ resource "google_secret_manager_secret" "openvidu_shared_info" {
|
||||||
for_each = toset([
|
for_each = toset([
|
||||||
"OPENVIDU_URL", "MEET_INITIAL_ADMIN_USER", "MEET_INITIAL_ADMIN_PASSWORD",
|
"OPENVIDU_URL", "MEET_INITIAL_ADMIN_USER", "MEET_INITIAL_ADMIN_PASSWORD",
|
||||||
"MEET_INITIAL_API_KEY", "LIVEKIT_URL", "LIVEKIT_API_KEY", "LIVEKIT_API_SECRET",
|
"MEET_INITIAL_API_KEY", "LIVEKIT_URL", "LIVEKIT_API_KEY", "LIVEKIT_API_SECRET",
|
||||||
"DASHBOARD_URL", "GRAFANA_URL", "MINIO_URL", "DOMAIN_NAME", "LIVEKIT_TURN_DOMAIN_NAME",
|
"DASHBOARD_URL", "GRAFANA_URL", "MINIO_URL", "DOMAIN_NAME",
|
||||||
"OPENVIDU_PRO_LICENSE", "OPENVIDU_RTC_ENGINE", "REDIS_PASSWORD", "MONGO_ADMIN_USERNAME",
|
"OPENVIDU_PRO_LICENSE", "OPENVIDU_RTC_ENGINE", "REDIS_PASSWORD", "MONGO_ADMIN_USERNAME",
|
||||||
"MONGO_ADMIN_PASSWORD", "MONGO_REPLICA_SET_KEY", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY",
|
"MONGO_ADMIN_PASSWORD", "MONGO_REPLICA_SET_KEY", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY",
|
||||||
"DASHBOARD_ADMIN_USERNAME", "DASHBOARD_ADMIN_PASSWORD", "GRAFANA_ADMIN_USERNAME",
|
"DASHBOARD_ADMIN_USERNAME", "DASHBOARD_ADMIN_PASSWORD", "GRAFANA_ADMIN_USERNAME",
|
||||||
|
|
@ -167,9 +167,6 @@ resource "google_compute_instance" "openvidu_master_node" {
|
||||||
initialMeetAdminPassword = var.initialMeetAdminPassword
|
initialMeetAdminPassword = var.initialMeetAdminPassword
|
||||||
initialMeetApiKey = var.initialMeetApiKey
|
initialMeetApiKey = var.initialMeetApiKey
|
||||||
additionalInstallFlags = var.additionalInstallFlags
|
additionalInstallFlags = var.additionalInstallFlags
|
||||||
turnDomainName = var.turnDomainName
|
|
||||||
turnOwnPublicCertificate = var.turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate = var.turnOwnPrivateCertificate
|
|
||||||
bucketName = local.isEmpty ? google_storage_bucket.bucket[0].name : var.bucketName
|
bucketName = local.isEmpty ? google_storage_bucket.bucket[0].name : var.bucketName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -620,7 +617,7 @@ locals {
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
YQ_VERSION=v4.44.5
|
YQ_VERSION=v4.44.5
|
||||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||||
|
|
@ -652,7 +649,6 @@ if [[ "${var.domainName}" == "" ]]; then
|
||||||
EXTERNAL_IP=$(get_meta "instance/network-interfaces/0/access-configs/0/external-ip")
|
EXTERNAL_IP=$(get_meta "instance/network-interfaces/0/access-configs/0/external-ip")
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO=turn-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
|
||||||
else
|
else
|
||||||
DOMAIN="${var.domainName}"
|
DOMAIN="${var.domainName}"
|
||||||
fi
|
fi
|
||||||
|
|
@ -738,19 +734,6 @@ if [[ "${var.additionalInstallFlags}" != "" ]]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Turn with TLS
|
|
||||||
if [[ "$TURN_DOMAIN_NAME_SSLIP_IO" != "" ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "$TURN_DOMAIN_NAME_SSLIP_IO")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${var.turnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${var.turnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -769,17 +752,6 @@ else
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${var.turnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${var.turnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${var.turnOwnPrivateCertificate}
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Final command
|
# Final command
|
||||||
|
|
@ -879,12 +851,6 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(gcloud secrets versions access latest --secret=LIVEKIT_TURN_DOMAIN_NAME)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the rest of the values
|
# Get the rest of the values
|
||||||
export REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
export REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
||||||
export OPENVIDU_RTC_ENGINE=$(gcloud secrets versions access latest --secret=OPENVIDU_RTC_ENGINE)
|
export OPENVIDU_RTC_ENGINE=$(gcloud secrets versions access latest --secret=OPENVIDU_RTC_ENGINE)
|
||||||
|
|
@ -960,7 +926,6 @@ MASTER_NODE_CONFIG_DIR="$${INSTALL_DIR}/config/node"
|
||||||
# Get current values of the config
|
# Get current values of the config
|
||||||
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "$${MASTER_NODE_CONFIG_DIR}/master_node.env")"
|
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "$${MASTER_NODE_CONFIG_DIR}/master_node.env")"
|
||||||
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
||||||
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
|
@ -984,7 +949,6 @@ ENABLED_MODULES="$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES "$${C
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
echo -n "$REDIS_PASSWORD" | gcloud secrets versions add REDIS_PASSWORD --data-file=-
|
echo -n "$REDIS_PASSWORD" | gcloud secrets versions add REDIS_PASSWORD --data-file=-
|
||||||
echo -n "$DOMAIN_NAME" | gcloud secrets versions add DOMAIN_NAME --data-file=-
|
echo -n "$DOMAIN_NAME" | gcloud secrets versions add DOMAIN_NAME --data-file=-
|
||||||
echo -n "$LIVEKIT_TURN_DOMAIN_NAME" | gcloud secrets versions add LIVEKIT_TURN_DOMAIN_NAME --data-file=-
|
|
||||||
echo -n "$OPENVIDU_RTC_ENGINE" | gcloud secrets versions add OPENVIDU_RTC_ENGINE --data-file=-
|
echo -n "$OPENVIDU_RTC_ENGINE" | gcloud secrets versions add OPENVIDU_RTC_ENGINE --data-file=-
|
||||||
echo -n "$OPENVIDU_PRO_LICENSE" | gcloud secrets versions add OPENVIDU_PRO_LICENSE --data-file=-
|
echo -n "$OPENVIDU_PRO_LICENSE" | gcloud secrets versions add OPENVIDU_PRO_LICENSE --data-file=-
|
||||||
echo -n "$MONGO_ADMIN_USERNAME" | gcloud secrets versions add MONGO_ADMIN_USERNAME --data-file=-
|
echo -n "$MONGO_ADMIN_USERNAME" | gcloud secrets versions add MONGO_ADMIN_USERNAME --data-file=-
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ variable "minNumberOfMediaNodes" {
|
||||||
variable "maxNumberOfMediaNodes" {
|
variable "maxNumberOfMediaNodes" {
|
||||||
description = "Maximum number of media nodes to deploy"
|
description = "Maximum number of media nodes to deploy"
|
||||||
type = number
|
type = number
|
||||||
default = 2
|
default = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "scaleTargetCPU" {
|
variable "scaleTargetCPU" {
|
||||||
|
|
@ -152,21 +152,3 @@ variable "additionalInstallFlags" {
|
||||||
error_message = "Must be a comma-separated list of flags (for example, --flag=value, --bool-flag)."
|
error_message = "Must be a comma-separated list of flags (for example, --flag=value, --bool-flag)."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "turnDomainName" {
|
|
||||||
description = "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls"
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "turnOwnPublicCertificate" {
|
|
||||||
description = "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "turnOwnPrivateCertificate" {
|
|
||||||
description = "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
||||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
||||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.5.0}"
|
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
||||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
||||||
|
|
@ -19,7 +19,7 @@ export OPENVIDU_MEET_SERVER_IMAGE="${OPENVIDU_MEET_SERVER_IMAGE:-docker.io/openv
|
||||||
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing:${OPENVIDU_VERSION}}"
|
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-cloud:${OPENVIDU_VERSION}}"
|
||||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${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 LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
||||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
||||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.5.0}"
|
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
||||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
||||||
|
|
@ -19,7 +19,7 @@ export OPENVIDU_MEET_SERVER_IMAGE="${OPENVIDU_MEET_SERVER_IMAGE:-docker.io/openv
|
||||||
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing:${OPENVIDU_VERSION}}"
|
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-cloud:${OPENVIDU_VERSION}}"
|
||||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${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 LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,6 @@ Parameters:
|
||||||
AllowedPattern: '.+'
|
AllowedPattern: '.+'
|
||||||
ConstraintDescription: The Load Balancer domain name must be defined
|
ConstraintDescription: The Load Balancer domain name must be defined
|
||||||
|
|
||||||
TurnDomainName:
|
|
||||||
Description: '(Optional) Domain name for the TURN server with TLS.'
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
TurnCertificateARN:
|
|
||||||
Description: '(Optional) Amazon certificate arn resource to load into the TURN LoadBalancer'
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
OpenViduLicense:
|
OpenViduLicense:
|
||||||
Description: "Visit https://openvidu.io/account"
|
Description: "Visit https://openvidu.io/account"
|
||||||
Type: String
|
Type: String
|
||||||
|
|
@ -848,14 +838,8 @@ Metadata:
|
||||||
default: "(Optional) Additional Installer Flags"
|
default: "(Optional) Additional Installer Flags"
|
||||||
Parameters:
|
Parameters:
|
||||||
- AdditionalInstallFlags
|
- AdditionalInstallFlags
|
||||||
- Label:
|
|
||||||
default: (Optional) TURN server configuration with TLS
|
|
||||||
Parameters:
|
|
||||||
- TurnDomainName
|
|
||||||
- TurnCertificateARN
|
|
||||||
|
|
||||||
Conditions:
|
Conditions:
|
||||||
TurnTLSIsEnabled: !Or [!Not [!Equals [!Ref TurnDomainName, ""]], !Not [!Equals [!Ref TurnCertificateARN, ""]]]
|
|
||||||
CreateRecordingsBucket: !Equals [!Ref S3AppDataBucketName, ""]
|
CreateRecordingsBucket: !Equals [!Ref S3AppDataBucketName, ""]
|
||||||
CreateClusterDataBucket: !Equals [!Ref S3ClusterDataBucketName, ""]
|
CreateClusterDataBucket: !Equals [!Ref S3ClusterDataBucketName, ""]
|
||||||
IsMasterGraviton: !Or
|
IsMasterGraviton: !Or
|
||||||
|
|
@ -880,22 +864,6 @@ Conditions:
|
||||||
- !Equals [ !Select [ 0, !Split ['.', !Ref MediaNodeInstanceType ]], 'm7g']
|
- !Equals [ !Select [ 0, !Split ['.', !Ref MediaNodeInstanceType ]], 'm7g']
|
||||||
- !Equals [ !Select [ 0, !Split ['.', !Ref MediaNodeInstanceType ]], 'm7gd']
|
- !Equals [ !Select [ 0, !Split ['.', !Ref MediaNodeInstanceType ]], 'm7gd']
|
||||||
- !Equals [ !Select [ 0, !Split ['.', !Ref MediaNodeInstanceType ]], 'm8g']
|
- !Equals [ !Select [ 0, !Split ['.', !Ref MediaNodeInstanceType ]], 'm8g']
|
||||||
# ---
|
|
||||||
# Experimental TURN TLS with main domain
|
|
||||||
ExperimentalTurnTLSWithMainDomain:
|
|
||||||
Fn::Not:
|
|
||||||
- Fn::Equals:
|
|
||||||
- !Ref AdditionalInstallFlags
|
|
||||||
- !Select [0, !Split ["--experimental-turn-tls-with-main-domain", !Ref AdditionalInstallFlags]]
|
|
||||||
NotExperimentalTurnTLSWithMainDomain:
|
|
||||||
Fn::Or:
|
|
||||||
- Fn::Equals:
|
|
||||||
- !Ref AdditionalInstallFlags
|
|
||||||
- !Select [0, !Split ["--experimental-turn-tls-with-main-domain", !Ref AdditionalInstallFlags]]
|
|
||||||
- Fn::Equals:
|
|
||||||
- !Ref AdditionalInstallFlags
|
|
||||||
- ""
|
|
||||||
# ---
|
|
||||||
|
|
||||||
Mappings:
|
Mappings:
|
||||||
ArmImage:
|
ArmImage:
|
||||||
|
|
@ -933,7 +901,6 @@ Resources:
|
||||||
"GRAFANA_URL": "none",
|
"GRAFANA_URL": "none",
|
||||||
"MINIO_URL": "none",
|
"MINIO_URL": "none",
|
||||||
"DOMAIN_NAME": "none",
|
"DOMAIN_NAME": "none",
|
||||||
"LIVEKIT_TURN_DOMAIN_NAME": "none",
|
|
||||||
"OPENVIDU_PRO_LICENSE": "none",
|
"OPENVIDU_PRO_LICENSE": "none",
|
||||||
"OPENVIDU_RTC_ENGINE": "none",
|
"OPENVIDU_RTC_ENGINE": "none",
|
||||||
"REDIS_PASSWORD": "none",
|
"REDIS_PASSWORD": "none",
|
||||||
|
|
@ -1249,7 +1216,7 @@ Resources:
|
||||||
content: !Sub |
|
content: !Sub |
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
set -e
|
set -e
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
YQ_VERSION=v4.44.5
|
YQ_VERSION=v4.44.5
|
||||||
|
|
||||||
|
|
@ -1324,9 +1291,6 @@ Resources:
|
||||||
# If the private IP is the same as the first master node, generate the secrets
|
# If the private IP is the same as the first master node, generate the secrets
|
||||||
if [[ $MASTER_NODE_NUM -eq 1 ]] && [[ "$ALL_SECRETS_GENERATED" == "false" ]]; then
|
if [[ $MASTER_NODE_NUM -eq 1 ]] && [[ "$ALL_SECRETS_GENERATED" == "false" ]]; then
|
||||||
DOMAIN="$(/usr/local/bin/store_secret.sh save DOMAIN_NAME "${DomainName}")"
|
DOMAIN="$(/usr/local/bin/store_secret.sh save DOMAIN_NAME "${DomainName}")"
|
||||||
if [[ -n "${TurnDomainName}" ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${TurnDomainName}")"
|
|
||||||
fi
|
|
||||||
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/store_secret.sh save OPENVIDU_PRO_LICENSE "${OpenViduLicense}")"
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/store_secret.sh save OPENVIDU_PRO_LICENSE "${OpenViduLicense}")"
|
||||||
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/store_secret.sh save OPENVIDU_RTC_ENGINE "${RTCEngine}")"
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/store_secret.sh save OPENVIDU_RTC_ENGINE "${RTCEngine}")"
|
||||||
# Store version so media nodes can use it to install the same version
|
# Store version so media nodes can use it to install the same version
|
||||||
|
|
@ -1411,7 +1375,6 @@ Resources:
|
||||||
MASTER_NODE_PRIVATE_IP_LIST="$MASTER_NODE_1_PRIVATE_IP,$MASTER_NODE_2_PRIVATE_IP,$MASTER_NODE_3_PRIVATE_IP,$MASTER_NODE_4_PRIVATE_IP"
|
MASTER_NODE_PRIVATE_IP_LIST="$MASTER_NODE_1_PRIVATE_IP,$MASTER_NODE_2_PRIVATE_IP,$MASTER_NODE_3_PRIVATE_IP,$MASTER_NODE_4_PRIVATE_IP"
|
||||||
|
|
||||||
DOMAIN=$(echo "$SHARED_SECRET" | jq -r '.DOMAIN_NAME')
|
DOMAIN=$(echo "$SHARED_SECRET" | jq -r '.DOMAIN_NAME')
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(echo "$SHARED_SECRET" | jq -r '.LIVEKIT_TURN_DOMAIN_NAME')
|
|
||||||
OPENVIDU_PRO_LICENSE=$(echo "$SHARED_SECRET" | jq -r '.OPENVIDU_PRO_LICENSE')
|
OPENVIDU_PRO_LICENSE=$(echo "$SHARED_SECRET" | jq -r '.OPENVIDU_PRO_LICENSE')
|
||||||
OPENVIDU_RTC_ENGINE=$(echo "$SHARED_SECRET" | jq -r '.OPENVIDU_RTC_ENGINE')
|
OPENVIDU_RTC_ENGINE=$(echo "$SHARED_SECRET" | jq -r '.OPENVIDU_RTC_ENGINE')
|
||||||
REDIS_PASSWORD=$(echo "$SHARED_SECRET" | jq -r '.REDIS_PASSWORD')
|
REDIS_PASSWORD=$(echo "$SHARED_SECRET" | jq -r '.REDIS_PASSWORD')
|
||||||
|
|
@ -1480,10 +1443,6 @@ Resources:
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${!LIVEKIT_TURN_DOMAIN_NAME}" != "none" ]]; then
|
|
||||||
COMMON_ARGS+=("--turn-domain-name='${!LIVEKIT_TURN_DOMAIN_NAME}'")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Construct the final command
|
# Construct the final command
|
||||||
FINAL_COMMAND="$INSTALL_COMMAND $(printf "%s " "${!COMMON_ARGS[@]}")"
|
FINAL_COMMAND="$INSTALL_COMMAND $(printf "%s " "${!COMMON_ARGS[@]}")"
|
||||||
|
|
||||||
|
|
@ -1584,12 +1543,6 @@ Resources:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(echo $SHARED_SECRET | jq -r .LIVEKIT_TURN_DOMAIN_NAME)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${!CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Replace rest of the values
|
# Replace rest of the values
|
||||||
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!MASTER_NODE_CONFIG_DIR}/master_node.env"
|
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!MASTER_NODE_CONFIG_DIR}/master_node.env"
|
||||||
sed -i "s/OPENVIDU_RTC_ENGINE=.*/OPENVIDU_RTC_ENGINE=$(echo $SHARED_SECRET | jq -r .OPENVIDU_RTC_ENGINE)/" "${!CLUSTER_CONFIG_DIR}/openvidu.env"
|
sed -i "s/OPENVIDU_RTC_ENGINE=.*/OPENVIDU_RTC_ENGINE=$(echo $SHARED_SECRET | jq -r .OPENVIDU_RTC_ENGINE)/" "${!CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
|
@ -1649,7 +1602,6 @@ Resources:
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"REDIS_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${!MASTER_NODE_CONFIG_DIR}/master_node.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"REDIS_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${!MASTER_NODE_CONFIG_DIR}/master_node.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"LIVEKIT_TURN_DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_RTC_ENGINE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_RTC_ENGINE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_PRO_LICENSE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_PRO_LICENSE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_USERNAME": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_USERNAME": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
|
|
@ -2235,11 +2187,7 @@ Resources:
|
||||||
LaunchTemplateId: !Ref OpenViduMediaNodeLaunchTemplate
|
LaunchTemplateId: !Ref OpenViduMediaNodeLaunchTemplate
|
||||||
Version: !GetAtt OpenViduMediaNodeLaunchTemplate.DefaultVersionNumber
|
Version: !GetAtt OpenViduMediaNodeLaunchTemplate.DefaultVersionNumber
|
||||||
TargetGroupARNs:
|
TargetGroupARNs:
|
||||||
Fn::If:
|
- !Ref OpenViduMediaNodeRTMPTG
|
||||||
- TurnTLSIsEnabled
|
|
||||||
- - !Ref OpenViduMediaNodeRTMPTG
|
|
||||||
- !Ref OpenViduMediaNodeTurnTLSTG
|
|
||||||
- - !Ref OpenViduMediaNodeRTMPTG
|
|
||||||
MinSize: !Ref MinNumberOfMediaNodes
|
MinSize: !Ref MinNumberOfMediaNodes
|
||||||
MaxSize: !Ref MaxNumberOfMediaNodes
|
MaxSize: !Ref MaxNumberOfMediaNodes
|
||||||
DesiredCapacity: !Ref InitialNumberOfMediaNodes
|
DesiredCapacity: !Ref InitialNumberOfMediaNodes
|
||||||
|
|
@ -2353,7 +2301,9 @@ Resources:
|
||||||
- Effect: Allow
|
- Effect: Allow
|
||||||
Action:
|
Action:
|
||||||
- ssm:StartAutomationExecution
|
- ssm:StartAutomationExecution
|
||||||
Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${StopMediaNodeAutomationDocument}:$DEFAULT
|
Resource:
|
||||||
|
- !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-execution/*
|
||||||
|
- !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:document/${StopMediaNodeAutomationDocument}
|
||||||
PolicyName: !Sub StopMediaNodeCloudWatchEventPolicy-${AWS::Region}-${AWS::StackName}
|
PolicyName: !Sub StopMediaNodeCloudWatchEventPolicy-${AWS::Region}-${AWS::StackName}
|
||||||
- PolicyDocument:
|
- PolicyDocument:
|
||||||
Version: '2012-10-17'
|
Version: '2012-10-17'
|
||||||
|
|
@ -2700,27 +2650,6 @@ Resources:
|
||||||
ToPort: 9092
|
ToPort: 9092
|
||||||
SourceSecurityGroupId: !Ref OpenViduLoadBalancerSG
|
SourceSecurityGroupId: !Ref OpenViduLoadBalancerSG
|
||||||
|
|
||||||
OpenViduLoadBalancerTurnTLSToMediaNodeIngressSG:
|
|
||||||
Type: AWS::EC2::SecurityGroupIngress
|
|
||||||
Condition: TurnTLSIsEnabled
|
|
||||||
Properties:
|
|
||||||
GroupId: !Ref OpenViduMediaNodeSG
|
|
||||||
IpProtocol: tcp
|
|
||||||
FromPort: 5349
|
|
||||||
ToPort: 5349
|
|
||||||
SourceSecurityGroupId: !Ref OpenViduTurnTLSLoadBalancerSG
|
|
||||||
|
|
||||||
OpenViduLoadBalancerTurnTLSToMediaNodeHealthCheckSG:
|
|
||||||
Type: AWS::EC2::SecurityGroupIngress
|
|
||||||
Condition: TurnTLSIsEnabled
|
|
||||||
Properties:
|
|
||||||
GroupId: !Ref OpenViduMediaNodeSG
|
|
||||||
IpProtocol: tcp
|
|
||||||
FromPort: 7880
|
|
||||||
ToPort: 7880
|
|
||||||
SourceSecurityGroupId: !Ref OpenViduTurnTLSLoadBalancerSG
|
|
||||||
|
|
||||||
|
|
||||||
OpenViduMasterToMediaNodeServerIngressSG:
|
OpenViduMasterToMediaNodeServerIngressSG:
|
||||||
Type: AWS::EC2::SecurityGroupIngress
|
Type: AWS::EC2::SecurityGroupIngress
|
||||||
Properties:
|
Properties:
|
||||||
|
|
@ -2739,11 +2668,8 @@ Resources:
|
||||||
ToPort: 8080
|
ToPort: 8080
|
||||||
SourceSecurityGroupId: !Ref OpenViduMasterNodeSG
|
SourceSecurityGroupId: !Ref OpenViduMasterNodeSG
|
||||||
|
|
||||||
# ---
|
|
||||||
# Experimental TURN TLS with main domain
|
|
||||||
OpenViduTurnTLSMasterNodeToMediaNodeIngressSG:
|
OpenViduTurnTLSMasterNodeToMediaNodeIngressSG:
|
||||||
Type: AWS::EC2::SecurityGroupIngress
|
Type: AWS::EC2::SecurityGroupIngress
|
||||||
Condition: ExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
Properties:
|
||||||
GroupId: !Ref OpenViduMediaNodeSG
|
GroupId: !Ref OpenViduMediaNodeSG
|
||||||
IpProtocol: tcp
|
IpProtocol: tcp
|
||||||
|
|
@ -2753,14 +2679,12 @@ Resources:
|
||||||
|
|
||||||
OpenViduTurnTLSLoadBalancerToMediaNodeIngressSG:
|
OpenViduTurnTLSLoadBalancerToMediaNodeIngressSG:
|
||||||
Type: AWS::EC2::SecurityGroupIngress
|
Type: AWS::EC2::SecurityGroupIngress
|
||||||
Condition: ExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
Properties:
|
||||||
GroupId: !Ref OpenViduMasterNodeSG
|
GroupId: !Ref OpenViduMasterNodeSG
|
||||||
IpProtocol: tcp
|
IpProtocol: tcp
|
||||||
FromPort: 443
|
FromPort: 443
|
||||||
ToPort: 443
|
ToPort: 443
|
||||||
SourceSecurityGroupId: !Ref OpenViduLoadBalancerSG
|
SourceSecurityGroupId: !Ref OpenViduLoadBalancerSG
|
||||||
# ---
|
|
||||||
|
|
||||||
OpenViduLoadBalancerSG:
|
OpenViduLoadBalancerSG:
|
||||||
Type: AWS::EC2::SecurityGroup
|
Type: AWS::EC2::SecurityGroup
|
||||||
|
|
@ -2794,23 +2718,6 @@ Resources:
|
||||||
ToPort: 1935
|
ToPort: 1935
|
||||||
CidrIpv6: ::/0
|
CidrIpv6: ::/0
|
||||||
|
|
||||||
OpenViduTurnTLSLoadBalancerSG:
|
|
||||||
Type: AWS::EC2::SecurityGroup
|
|
||||||
Condition: TurnTLSIsEnabled
|
|
||||||
Properties:
|
|
||||||
GroupDescription: Security group for the Load Balancer for TURN with TLS
|
|
||||||
GroupName: !Sub openvidu-ha-turn-tls-lb-sg-${AWS::Region}-${AWS::StackName}
|
|
||||||
VpcId: !Ref OpenViduVPC
|
|
||||||
SecurityGroupIngress:
|
|
||||||
- IpProtocol: tcp
|
|
||||||
FromPort: 443
|
|
||||||
ToPort: 443
|
|
||||||
CidrIp: 0.0.0.0/0
|
|
||||||
- IpProtocol: tcp
|
|
||||||
FromPort: 443
|
|
||||||
ToPort: 443
|
|
||||||
CidrIpv6: ::/0
|
|
||||||
|
|
||||||
LoadBalancer:
|
LoadBalancer:
|
||||||
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
|
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
|
||||||
DependsOn:
|
DependsOn:
|
||||||
|
|
@ -2831,54 +2738,8 @@ Resources:
|
||||||
- Key: Name
|
- Key: Name
|
||||||
Value: !Sub ${AWS::StackName} - OpenVidu HA - Load Balancer
|
Value: !Sub ${AWS::StackName} - OpenVidu HA - Load Balancer
|
||||||
|
|
||||||
TurnTLSLoadBalancer:
|
|
||||||
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
|
|
||||||
Condition: TurnTLSIsEnabled
|
|
||||||
Properties:
|
|
||||||
Name:
|
|
||||||
Fn::Join:
|
|
||||||
# Generate a not too long and unique load balancer name
|
|
||||||
# Getting a unique identifier from the stack id
|
|
||||||
- ''
|
|
||||||
- - OpenViduHA-TurnTLS-
|
|
||||||
- !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]
|
|
||||||
Subnets: !Ref OpenViduMediaNodeSubnets
|
|
||||||
SecurityGroups:
|
|
||||||
- !Ref OpenViduTurnTLSLoadBalancerSG
|
|
||||||
Type: network
|
|
||||||
Tags:
|
|
||||||
- Key: Name
|
|
||||||
Value: !Sub ${AWS::StackName} - OpenVidu HA - TURN with TLS Load Balancer
|
|
||||||
|
|
||||||
OpenViduMasterNodeHTTPListener:
|
|
||||||
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
|
||||||
Condition: NotExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
|
||||||
DefaultActions:
|
|
||||||
- Type: forward
|
|
||||||
TargetGroupArn: !Ref OpenViduMasterNodeHTTPTG
|
|
||||||
LoadBalancerArn: !Ref LoadBalancer
|
|
||||||
Port: 80
|
|
||||||
Protocol: TCP
|
|
||||||
|
|
||||||
OpenViduMasterNodeListener:
|
|
||||||
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
|
||||||
Condition: NotExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
|
||||||
DefaultActions:
|
|
||||||
- Type: forward
|
|
||||||
TargetGroupArn: !Ref OpenViduMasterNodeTG
|
|
||||||
LoadBalancerArn: !Ref LoadBalancer
|
|
||||||
Port: 443
|
|
||||||
Protocol: TLS
|
|
||||||
Certificates:
|
|
||||||
- CertificateArn: !Ref OpenViduCertificateARN
|
|
||||||
|
|
||||||
# ---
|
|
||||||
# Experimental TURN TLS with main domain
|
|
||||||
OpenViduMasterNodeWithTurnTLSHTTPListener:
|
OpenViduMasterNodeWithTurnTLSHTTPListener:
|
||||||
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
||||||
Condition: ExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
Properties:
|
||||||
DefaultActions:
|
DefaultActions:
|
||||||
- Type: forward
|
- Type: forward
|
||||||
|
|
@ -2889,7 +2750,6 @@ Resources:
|
||||||
|
|
||||||
OpenViduMasterNodeWithTurnTLSListener:
|
OpenViduMasterNodeWithTurnTLSListener:
|
||||||
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
||||||
Condition: ExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
Properties:
|
||||||
DefaultActions:
|
DefaultActions:
|
||||||
- Type: forward
|
- Type: forward
|
||||||
|
|
@ -2899,7 +2759,6 @@ Resources:
|
||||||
Protocol: TLS
|
Protocol: TLS
|
||||||
Certificates:
|
Certificates:
|
||||||
- CertificateArn: !Ref OpenViduCertificateARN
|
- CertificateArn: !Ref OpenViduCertificateARN
|
||||||
# ---
|
|
||||||
|
|
||||||
OpenViduRTMPMediaNodeListener:
|
OpenViduRTMPMediaNodeListener:
|
||||||
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
||||||
|
|
@ -2913,22 +2772,8 @@ Resources:
|
||||||
Certificates:
|
Certificates:
|
||||||
- CertificateArn: !Ref OpenViduCertificateARN
|
- CertificateArn: !Ref OpenViduCertificateARN
|
||||||
|
|
||||||
OpenViduTurnTLSMediaNodeListener:
|
|
||||||
Type: 'AWS::ElasticLoadBalancingV2::Listener'
|
|
||||||
Condition: TurnTLSIsEnabled
|
|
||||||
Properties:
|
|
||||||
DefaultActions:
|
|
||||||
- Type: forward
|
|
||||||
TargetGroupArn: !Ref OpenViduMediaNodeTurnTLSTG
|
|
||||||
LoadBalancerArn: !Ref TurnTLSLoadBalancer
|
|
||||||
Port: 443
|
|
||||||
Protocol: TLS
|
|
||||||
Certificates:
|
|
||||||
- CertificateArn: !Ref TurnCertificateARN
|
|
||||||
|
|
||||||
OpenViduMasterNodeHTTPTG:
|
OpenViduMasterNodeHTTPTG:
|
||||||
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
||||||
Condition: NotExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
Properties:
|
||||||
Name:
|
Name:
|
||||||
Fn::Join:
|
Fn::Join:
|
||||||
|
|
@ -2962,47 +2807,8 @@ Resources:
|
||||||
- Key: Name
|
- Key: Name
|
||||||
Value: !Sub ${AWS::StackName} - OpenVidu HA - Master HTTP Target Group
|
Value: !Sub ${AWS::StackName} - OpenVidu HA - Master HTTP Target Group
|
||||||
|
|
||||||
OpenViduMasterNodeTG:
|
|
||||||
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
|
||||||
Condition: NotExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
|
||||||
Name:
|
|
||||||
Fn::Join:
|
|
||||||
# Generate a not too long and unique target id
|
|
||||||
# Getting a unique identifier from the stack id
|
|
||||||
- ''
|
|
||||||
- - OpenVidu-
|
|
||||||
- !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]
|
|
||||||
TargetType: instance
|
|
||||||
Targets:
|
|
||||||
- Id: !Ref OpenViduMasterNode1
|
|
||||||
- Id: !Ref OpenViduMasterNode2
|
|
||||||
- Id: !Ref OpenViduMasterNode3
|
|
||||||
- Id: !Ref OpenViduMasterNode4
|
|
||||||
VpcId: !Ref OpenViduVPC
|
|
||||||
Port: 7880
|
|
||||||
Protocol: TCP
|
|
||||||
Matcher:
|
|
||||||
HttpCode: '200'
|
|
||||||
HealthCheckIntervalSeconds: 10
|
|
||||||
HealthCheckPath: /health/caddy
|
|
||||||
HealthCheckProtocol: HTTP
|
|
||||||
HealthCheckPort: '7880'
|
|
||||||
HealthCheckTimeoutSeconds: 5
|
|
||||||
HealthyThresholdCount: 3
|
|
||||||
UnhealthyThresholdCount: 4
|
|
||||||
TargetGroupAttributes:
|
|
||||||
- Key: deregistration_delay.timeout_seconds
|
|
||||||
Value: 60
|
|
||||||
Tags:
|
|
||||||
- Key: Name
|
|
||||||
Value: !Sub ${AWS::StackName} - OpenVidu HA - Master Target Group
|
|
||||||
|
|
||||||
# ---
|
|
||||||
# Experimental TURN TLS with main domain
|
|
||||||
OpenViduMasterNodeWithTurnTLSTG:
|
OpenViduMasterNodeWithTurnTLSTG:
|
||||||
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
||||||
Condition: ExperimentalTurnTLSWithMainDomain
|
|
||||||
Properties:
|
Properties:
|
||||||
Name:
|
Name:
|
||||||
Fn::Join:
|
Fn::Join:
|
||||||
|
|
@ -3035,7 +2841,6 @@ Resources:
|
||||||
Tags:
|
Tags:
|
||||||
- Key: Name
|
- Key: Name
|
||||||
Value: !Sub ${AWS::StackName} - OpenVidu HA - TURN TLS Master Target Group
|
Value: !Sub ${AWS::StackName} - OpenVidu HA - TURN TLS Master Target Group
|
||||||
# ---
|
|
||||||
|
|
||||||
OpenViduMediaNodeRTMPTG:
|
OpenViduMediaNodeRTMPTG:
|
||||||
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
||||||
|
|
@ -3067,33 +2872,6 @@ Resources:
|
||||||
- Key: Name
|
- Key: Name
|
||||||
Value: !Sub ${AWS::StackName} - OpenVidu HA - RTMP Target Group
|
Value: !Sub ${AWS::StackName} - OpenVidu HA - RTMP Target Group
|
||||||
|
|
||||||
OpenViduMediaNodeTurnTLSTG:
|
|
||||||
Type: AWS::ElasticLoadBalancingV2::TargetGroup
|
|
||||||
Condition: TurnTLSIsEnabled
|
|
||||||
Properties:
|
|
||||||
Name:
|
|
||||||
Fn::Join:
|
|
||||||
# Generate a not too long and unique target id
|
|
||||||
# Getting a unique identifier from the stack id
|
|
||||||
- ''
|
|
||||||
- - OVTurnTLS-
|
|
||||||
- !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]
|
|
||||||
VpcId: !Ref OpenViduVPC
|
|
||||||
Port: 5349
|
|
||||||
Protocol: TCP
|
|
||||||
Matcher:
|
|
||||||
HttpCode: '200'
|
|
||||||
HealthCheckIntervalSeconds: 10
|
|
||||||
HealthCheckPath: /
|
|
||||||
HealthCheckProtocol: HTTP
|
|
||||||
HealthCheckPort: '7880'
|
|
||||||
HealthCheckTimeoutSeconds: 5
|
|
||||||
HealthyThresholdCount: 3
|
|
||||||
UnhealthyThresholdCount: 4
|
|
||||||
Tags:
|
|
||||||
- Key: Name
|
|
||||||
Value: !Sub ${AWS::StackName} - OpenVidu HA - TURN TLS Target Group
|
|
||||||
|
|
||||||
Outputs:
|
Outputs:
|
||||||
ServicesAndCredentials:
|
ServicesAndCredentials:
|
||||||
Description: Services and credentials
|
Description: Services and credentials
|
||||||
|
|
|
||||||
|
|
@ -25,15 +25,6 @@ param ownPrivateCertificate string = ''
|
||||||
@description('Name of the PublicIPAddress resource in Azure when using certificateType \'owncert\' or \'letsencrypt\'')
|
@description('Name of the PublicIPAddress resource in Azure when using certificateType \'owncert\' or \'letsencrypt\'')
|
||||||
param publicIpAddressObject object
|
param publicIpAddressObject object
|
||||||
|
|
||||||
@description('(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls')
|
|
||||||
param turnDomainName string = ''
|
|
||||||
|
|
||||||
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified. Provide in base64 format.')
|
|
||||||
param turnOwnPublicCertificate string = ''
|
|
||||||
|
|
||||||
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified. Provide in base64 format.')
|
|
||||||
param turnOwnPrivateCertificate string = ''
|
|
||||||
|
|
||||||
@description('Visit https://openvidu.io/account')
|
@description('Visit https://openvidu.io/account')
|
||||||
@secure()
|
@secure()
|
||||||
param openviduLicense string
|
param openviduLicense string
|
||||||
|
|
@ -95,8 +86,20 @@ var isEmptyDomain = domainName == ''
|
||||||
// The pattern checks for 'p' followed by optional letters (like 'l', 'd', 's') before '_v' version suffix
|
// The pattern checks for 'p' followed by optional letters (like 'l', 'd', 's') before '_v' version suffix
|
||||||
var masterNodeInstanceTypeLower = toLower(masterNodeInstanceType)
|
var masterNodeInstanceTypeLower = toLower(masterNodeInstanceType)
|
||||||
var mediaNodeInstanceTypeLower = toLower(mediaNodeInstanceType)
|
var mediaNodeInstanceTypeLower = toLower(mediaNodeInstanceType)
|
||||||
var isMasterArm64 = contains(masterNodeInstanceTypeLower, 'ps_v') || contains(masterNodeInstanceTypeLower, 'pls_v') || contains(masterNodeInstanceTypeLower, 'pds_v') || contains(masterNodeInstanceTypeLower, 'plds_v') || contains(masterNodeInstanceTypeLower, 'psv') || contains(masterNodeInstanceTypeLower, 'plsv') || contains(masterNodeInstanceTypeLower, 'pdsv') || contains(masterNodeInstanceTypeLower, 'pldsv')
|
var isMasterArm64 = contains(masterNodeInstanceTypeLower, 'ps_v') || contains(masterNodeInstanceTypeLower, 'pls_v') || contains(
|
||||||
var isMediaArm64 = contains(mediaNodeInstanceTypeLower, 'ps_v') || contains(mediaNodeInstanceTypeLower, 'pls_v') || contains(mediaNodeInstanceTypeLower, 'pds_v') || contains(mediaNodeInstanceTypeLower, 'plds_v') || contains(mediaNodeInstanceTypeLower, 'psv') || contains(mediaNodeInstanceTypeLower, 'plsv') || contains(mediaNodeInstanceTypeLower, 'pdsv') || contains(mediaNodeInstanceTypeLower, 'pldsv')
|
masterNodeInstanceTypeLower,
|
||||||
|
'pds_v'
|
||||||
|
) || contains(masterNodeInstanceTypeLower, 'plds_v') || contains(masterNodeInstanceTypeLower, 'psv') || contains(
|
||||||
|
masterNodeInstanceTypeLower,
|
||||||
|
'plsv'
|
||||||
|
) || contains(masterNodeInstanceTypeLower, 'pdsv') || contains(masterNodeInstanceTypeLower, 'pldsv')
|
||||||
|
var isMediaArm64 = contains(mediaNodeInstanceTypeLower, 'ps_v') || contains(mediaNodeInstanceTypeLower, 'pls_v') || contains(
|
||||||
|
mediaNodeInstanceTypeLower,
|
||||||
|
'pds_v'
|
||||||
|
) || contains(mediaNodeInstanceTypeLower, 'plds_v') || contains(mediaNodeInstanceTypeLower, 'psv') || contains(
|
||||||
|
mediaNodeInstanceTypeLower,
|
||||||
|
'plsv'
|
||||||
|
) || contains(mediaNodeInstanceTypeLower, 'pdsv') || contains(mediaNodeInstanceTypeLower, 'pldsv')
|
||||||
|
|
||||||
var masterUbuntuSku = isMasterArm64 ? 'server-arm64' : 'server'
|
var masterUbuntuSku = isMasterArm64 ? 'server-arm64' : 'server'
|
||||||
var mediaUbuntuSku = isMediaArm64 ? 'server-arm64' : 'server'
|
var mediaUbuntuSku = isMediaArm64 ? 'server-arm64' : 'server'
|
||||||
|
|
@ -145,8 +148,6 @@ var mediaNodeVMSettings = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var turnTLSIsEnabled = turnDomainName != ''
|
|
||||||
|
|
||||||
var keyVaultName = '${stackName}-keyvault'
|
var keyVaultName = '${stackName}-keyvault'
|
||||||
|
|
||||||
var location = resourceGroup().location
|
var location = resourceGroup().location
|
||||||
|
|
@ -226,12 +227,9 @@ resource openviduSharedInfo 'Microsoft.KeyVault/vaults@2023-07-01' = {
|
||||||
var stringInterpolationParamsMaster1 = {
|
var stringInterpolationParamsMaster1 = {
|
||||||
publicIPId: publicIPId
|
publicIPId: publicIPId
|
||||||
domainName: domainName
|
domainName: domainName
|
||||||
turnDomainName: turnDomainName
|
|
||||||
certificateType: certificateType
|
certificateType: certificateType
|
||||||
ownPublicCertificate: ownPublicCertificate
|
ownPublicCertificate: ownPublicCertificate
|
||||||
ownPrivateCertificate: ownPrivateCertificate
|
ownPrivateCertificate: ownPrivateCertificate
|
||||||
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
||||||
openviduLicense: openviduLicense
|
openviduLicense: openviduLicense
|
||||||
rtcEngine: rtcEngine
|
rtcEngine: rtcEngine
|
||||||
initialMeetAdminPassword: initialMeetAdminPassword
|
initialMeetAdminPassword: initialMeetAdminPassword
|
||||||
|
|
@ -244,12 +242,9 @@ var stringInterpolationParamsMaster1 = {
|
||||||
var stringInterpolationParamsMaster2 = {
|
var stringInterpolationParamsMaster2 = {
|
||||||
publicIPId: publicIPId
|
publicIPId: publicIPId
|
||||||
domainName: domainName
|
domainName: domainName
|
||||||
turnDomainName: turnDomainName
|
|
||||||
certificateType: certificateType
|
certificateType: certificateType
|
||||||
ownPublicCertificate: ownPublicCertificate
|
ownPublicCertificate: ownPublicCertificate
|
||||||
ownPrivateCertificate: ownPrivateCertificate
|
ownPrivateCertificate: ownPrivateCertificate
|
||||||
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
||||||
openviduLicense: openviduLicense
|
openviduLicense: openviduLicense
|
||||||
rtcEngine: rtcEngine
|
rtcEngine: rtcEngine
|
||||||
initialMeetAdminPassword: initialMeetAdminPassword
|
initialMeetAdminPassword: initialMeetAdminPassword
|
||||||
|
|
@ -262,12 +257,9 @@ var stringInterpolationParamsMaster2 = {
|
||||||
var stringInterpolationParamsMaster3 = {
|
var stringInterpolationParamsMaster3 = {
|
||||||
publicIPId: publicIPId
|
publicIPId: publicIPId
|
||||||
domainName: domainName
|
domainName: domainName
|
||||||
turnDomainName: turnDomainName
|
|
||||||
certificateType: certificateType
|
certificateType: certificateType
|
||||||
ownPublicCertificate: ownPublicCertificate
|
ownPublicCertificate: ownPublicCertificate
|
||||||
ownPrivateCertificate: ownPrivateCertificate
|
ownPrivateCertificate: ownPrivateCertificate
|
||||||
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
||||||
openviduLicense: openviduLicense
|
openviduLicense: openviduLicense
|
||||||
rtcEngine: rtcEngine
|
rtcEngine: rtcEngine
|
||||||
initialMeetAdminPassword: initialMeetAdminPassword
|
initialMeetAdminPassword: initialMeetAdminPassword
|
||||||
|
|
@ -280,12 +272,9 @@ var stringInterpolationParamsMaster3 = {
|
||||||
var stringInterpolationParamsMaster4 = {
|
var stringInterpolationParamsMaster4 = {
|
||||||
publicIPId: publicIPId
|
publicIPId: publicIPId
|
||||||
domainName: domainName
|
domainName: domainName
|
||||||
turnDomainName: turnDomainName
|
|
||||||
certificateType: certificateType
|
certificateType: certificateType
|
||||||
ownPublicCertificate: ownPublicCertificate
|
ownPublicCertificate: ownPublicCertificate
|
||||||
ownPrivateCertificate: ownPrivateCertificate
|
ownPrivateCertificate: ownPrivateCertificate
|
||||||
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
||||||
openviduLicense: openviduLicense
|
openviduLicense: openviduLicense
|
||||||
rtcEngine: rtcEngine
|
rtcEngine: rtcEngine
|
||||||
initialMeetAdminPassword: initialMeetAdminPassword
|
initialMeetAdminPassword: initialMeetAdminPassword
|
||||||
|
|
@ -298,7 +287,7 @@ var stringInterpolationParamsMaster4 = {
|
||||||
var installScriptTemplateMaster = '''
|
var installScriptTemplateMaster = '''
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
set -e
|
set -e
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
|
|
||||||
# Assume azure cli is installed
|
# Assume azure cli is installed
|
||||||
|
|
@ -361,7 +350,6 @@ if [[ $MASTER_NODE_NUM -eq 1 ]] && [[ "$ALL_SECRETS_GENERATED" == "" || "$ALL_SE
|
||||||
|
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
|
||||||
else
|
else
|
||||||
DOMAIN=${domainName}
|
DOMAIN=${domainName}
|
||||||
fi
|
fi
|
||||||
|
|
@ -380,16 +368,6 @@ if [[ $MASTER_NODE_NUM -eq 1 ]] && [[ "$ALL_SECRETS_GENERATED" == "" || "$ALL_SE
|
||||||
MEET_INITIAL_API_KEY="$(/usr/local/bin/store_secret.sh save MEET-INITIAL-API-KEY "")"
|
MEET_INITIAL_API_KEY="$(/usr/local/bin/store_secret.sh save MEET-INITIAL-API-KEY "")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Configure TURN server domain name
|
|
||||||
if [[ -n "${turnDomainName}" ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${turnDomainName}")"
|
|
||||||
elif [[ "${TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${TURN_DOMAIN_NAME_SSLIP_IO}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Store usernames and generate random passwords
|
# Store usernames and generate random passwords
|
||||||
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/store_secret.sh save OPENVIDU-PRO-LICENSE "${openviduLicense}")"
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/store_secret.sh save OPENVIDU-PRO-LICENSE "${openviduLicense}")"
|
||||||
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/store_secret.sh save OPENVIDU-RTC-ENGINE "${rtcEngine}")"
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/store_secret.sh save OPENVIDU-RTC-ENGINE "${rtcEngine}")"
|
||||||
|
|
@ -435,9 +413,6 @@ MASTER_NODE_4_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName}
|
||||||
MASTER_NODE_PRIVATE_IP_LIST="$MASTER_NODE_1_PRIVATE_IP,$MASTER_NODE_2_PRIVATE_IP,$MASTER_NODE_3_PRIVATE_IP,$MASTER_NODE_4_PRIVATE_IP"
|
MASTER_NODE_PRIVATE_IP_LIST="$MASTER_NODE_1_PRIVATE_IP,$MASTER_NODE_2_PRIVATE_IP,$MASTER_NODE_3_PRIVATE_IP,$MASTER_NODE_4_PRIVATE_IP"
|
||||||
|
|
||||||
DOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)
|
DOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)
|
||||||
if [[ -n "${turnDomainName}" ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --query value -o tsv)
|
|
||||||
fi
|
|
||||||
OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
||||||
OPENVIDU_PRO_LICENSE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --query value -o tsv)
|
OPENVIDU_PRO_LICENSE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --query value -o tsv)
|
||||||
REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
||||||
|
|
@ -507,10 +482,6 @@ if [[ "${additionalInstallFlags}" != "" ]]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $LIVEKIT_TURN_DOMAIN_NAME != "" ]]; then
|
|
||||||
COMMON_ARGS+=("--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${certificateType}" == "selfsigned" ]]; then
|
if [[ "${certificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -530,18 +501,6 @@ else
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${turnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${turnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${turnOwnPrivateCertificate}
|
|
||||||
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the final command
|
# Construct the final command
|
||||||
|
|
@ -559,12 +518,16 @@ az login --identity --allow-no-subscriptions > /dev/null
|
||||||
|
|
||||||
# Generate URLs
|
# Generate URLs
|
||||||
DOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)
|
DOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)
|
||||||
|
OPENVIDU_URL="https://${DOMAIN}/"
|
||||||
|
LIVEKIT_URL="wss://${DOMAIN}/"
|
||||||
DASHBOARD_URL="https://${DOMAIN}/dashboard/"
|
DASHBOARD_URL="https://${DOMAIN}/dashboard/"
|
||||||
GRAFANA_URL="https://${DOMAIN}/grafana/"
|
GRAFANA_URL="https://${DOMAIN}/grafana/"
|
||||||
MINIO_URL="https://${DOMAIN}/minio-console/"
|
MINIO_URL="https://${DOMAIN}/minio-console/"
|
||||||
|
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN
|
||||||
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-URL --value $OPENVIDU_URL
|
||||||
|
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-URL --value $LIVEKIT_URL
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-URL --value $DASHBOARD_URL
|
az keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-URL --value $DASHBOARD_URL
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-URL --value $GRAFANA_URL
|
az keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-URL --value $GRAFANA_URL
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name MINIO-URL --value $MINIO_URL
|
az keyvault secret set --vault-name ${keyVaultName} --name MINIO-URL --value $MINIO_URL
|
||||||
|
|
@ -594,12 +557,6 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --query value -o tsv)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the rest of the values
|
# Get the rest of the values
|
||||||
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
||||||
export OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
export OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
||||||
|
|
@ -645,12 +602,16 @@ fi
|
||||||
sed -i "s/ENABLED_MODULES=.*/ENABLED_MODULES=$ENABLED_MODULES/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
sed -i "s/ENABLED_MODULES=.*/ENABLED_MODULES=$ENABLED_MODULES/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
|
||||||
# Update URLs in secret
|
# Update URLs in secret
|
||||||
|
OPENVIDU_URL="https://${DOMAIN}/"
|
||||||
|
LIVEKIT_URL="wss://${DOMAIN}/"
|
||||||
DASHBOARD_URL="https://${DOMAIN}/dashboard/"
|
DASHBOARD_URL="https://${DOMAIN}/dashboard/"
|
||||||
GRAFANA_URL="https://${DOMAIN}/grafana/"
|
GRAFANA_URL="https://${DOMAIN}/grafana/"
|
||||||
MINIO_URL="https://${DOMAIN}/minio-console/"
|
MINIO_URL="https://${DOMAIN}/minio-console/"
|
||||||
|
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN
|
||||||
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-URL --value $OPENVIDU_URL
|
||||||
|
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-URL --value $LIVEKIT_URL
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-URL --value $DASHBOARD_URL
|
az keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-URL --value $DASHBOARD_URL
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-URL --value $GRAFANA_URL
|
az keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-URL --value $GRAFANA_URL
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name MINIO-URL --value $MINIO_URL
|
az keyvault secret set --vault-name ${keyVaultName} --name MINIO-URL --value $MINIO_URL
|
||||||
|
|
@ -670,7 +631,6 @@ MASTER_NODE_CONFIG_DIR="${INSTALL_DIR}/config/node"
|
||||||
# Get current values of the config
|
# Get current values of the config
|
||||||
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${MASTER_NODE_CONFIG_DIR}/master_node.env")"
|
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${MASTER_NODE_CONFIG_DIR}/master_node.env")"
|
||||||
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
||||||
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
|
@ -694,7 +654,6 @@ ENABLED_MODULES="$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES "${CL
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --value $LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --value $OPENVIDU_RTC_ENGINE
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --value $OPENVIDU_RTC_ENGINE
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --value $OPENVIDU_PRO_LICENSE
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --value $OPENVIDU_PRO_LICENSE
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
||||||
|
|
@ -903,9 +862,6 @@ var blobStorageParams = {
|
||||||
storageAccountName: isEmptyStorageAccountName ? storageAccount.name : existingStorageAccount.name
|
storageAccountName: isEmptyStorageAccountName ? storageAccount.name : existingStorageAccount.name
|
||||||
storageAccountKey: listKeys(storageAccount.id, '2021-04-01').keys[0].value
|
storageAccountKey: listKeys(storageAccount.id, '2021-04-01').keys[0].value
|
||||||
storageAccountContainerName: isEmptyAppDataContainerName ? 'openvidu-appdata' : '${appDataContainerName}'
|
storageAccountContainerName: isEmptyAppDataContainerName ? 'openvidu-appdata' : '${appDataContainerName}'
|
||||||
storageAccountClusterContainerName: isEmptyClusterContainerName
|
|
||||||
? 'openvidu-clusterdata'
|
|
||||||
: '${clusterDataContainerName}'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var config_blobStorageScript = reduce(
|
var config_blobStorageScript = reduce(
|
||||||
|
|
@ -2784,44 +2740,6 @@ resource loadBalancerToMediaHealthcheckIngress 'Microsoft.Network/networkSecurit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource loadBalancerToMediaTurnTlsIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = if (turnTLSIsEnabled == true) {
|
|
||||||
parent: openviduMediaNodeNSG
|
|
||||||
name: 'loadbalancer_to_mediaNode_TURN_TLS_INGRESS'
|
|
||||||
properties: {
|
|
||||||
protocol: 'Tcp'
|
|
||||||
sourceAddressPrefix: 'AzureLoadBalancer'
|
|
||||||
sourcePortRange: '*'
|
|
||||||
destinationApplicationSecurityGroups: [
|
|
||||||
{
|
|
||||||
id: openviduMediaNodeASG.id
|
|
||||||
}
|
|
||||||
]
|
|
||||||
destinationPortRange: '5349'
|
|
||||||
access: 'Allow'
|
|
||||||
priority: 180
|
|
||||||
direction: 'Inbound'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource loadBalancerToMediaTurnTlsHealthCheckIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = if (turnTLSIsEnabled == true) {
|
|
||||||
parent: openviduMediaNodeNSG
|
|
||||||
name: 'masterNode_to_mediaNode_TURN_TLSHEALTHCHECK_INGRESS'
|
|
||||||
properties: {
|
|
||||||
protocol: 'Tcp'
|
|
||||||
sourceAddressPrefix: 'AzureLoadBalancer'
|
|
||||||
sourcePortRange: '*'
|
|
||||||
destinationApplicationSecurityGroups: [
|
|
||||||
{
|
|
||||||
id: openviduMediaNodeASG.id
|
|
||||||
}
|
|
||||||
]
|
|
||||||
destinationPortRange: '7880'
|
|
||||||
access: 'Allow'
|
|
||||||
priority: 190
|
|
||||||
direction: 'Inbound'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource masterToMediaServerIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
resource masterToMediaServerIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
||||||
parent: openviduMediaNodeNSG
|
parent: openviduMediaNodeNSG
|
||||||
name: 'masterNode_to_mediaNode_SERVER_INGRESS'
|
name: 'masterNode_to_mediaNode_SERVER_INGRESS'
|
||||||
|
|
@ -2868,6 +2786,29 @@ resource masterToMediaClientIngress 'Microsoft.Network/networkSecurityGroups/sec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource masterToMediaTurnTlsIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
||||||
|
parent: openviduMediaNodeNSG
|
||||||
|
name: 'masterNode_to_mediaNode_TURN_TLS_INGRESS'
|
||||||
|
properties: {
|
||||||
|
protocol: 'Tcp'
|
||||||
|
sourceApplicationSecurityGroups: [
|
||||||
|
{
|
||||||
|
id: openviduMasterNodeASG.id
|
||||||
|
}
|
||||||
|
]
|
||||||
|
sourcePortRange: '*'
|
||||||
|
destinationApplicationSecurityGroups: [
|
||||||
|
{
|
||||||
|
id: openviduMediaNodeASG.id
|
||||||
|
}
|
||||||
|
]
|
||||||
|
destinationPortRange: '5349'
|
||||||
|
access: 'Allow'
|
||||||
|
priority: 220
|
||||||
|
direction: 'Inbound'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------- STORAGE ACCOUNT ----------------------------------------*/
|
/*------------------------------------------- STORAGE ACCOUNT ----------------------------------------*/
|
||||||
|
|
||||||
@description('Name of an existing storage account. It is essential that this parameter is filled just when you want to save recordings and still using the same container after an update. If not specified, a new storage account will be generated.')
|
@description('Name of an existing storage account. It is essential that this parameter is filled just when you want to save recordings and still using the same container after an update. If not specified, a new storage account will be generated.')
|
||||||
|
|
@ -2913,18 +2854,4 @@ resource blobContainer 'Microsoft.Storage/storageAccounts/blobServices/container
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@description('Name of the bucket where OpenVidu will store the recordings if a new Storage account is being creating. If not specified, a default bucket will be created. If you want to use an existing storage account, fill this parameter with the name of the container where the recordings are stored.')
|
|
||||||
param clusterDataContainerName string = ''
|
|
||||||
|
|
||||||
var isEmptyClusterContainerName = clusterDataContainerName == ''
|
|
||||||
|
|
||||||
resource clusterDatablobContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = if (isEmptyStorageAccountName == true) {
|
|
||||||
name: isEmptyClusterContainerName
|
|
||||||
? '${storageAccount.name}/default/openvidu-clusterdata'
|
|
||||||
: '${storageAccount.name}/default/${clusterDataContainerName}'
|
|
||||||
properties: {
|
|
||||||
publicAccess: 'None'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*------------------------------------------- OUTPUTS -------------------------------------------*/
|
/*------------------------------------------- OUTPUTS -------------------------------------------*/
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -520,70 +520,6 @@
|
||||||
"visible": true
|
"visible": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "parameters TURN",
|
|
||||||
"label": "(Optional) TURN server configuration with TLS",
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"name": "turnDomainName",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Domain Name",
|
|
||||||
"subLabel": "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": []
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "turnOwnPublicCertificate",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Own Public Certificate",
|
|
||||||
"subLabel": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format.",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPublicCertificate)), true)]",
|
|
||||||
"message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "turnOwnPrivateCertificate",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Own Private Certificate",
|
|
||||||
"subLabel": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format.",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPrivateCertificate)), true)]",
|
|
||||||
"message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -598,9 +534,6 @@
|
||||||
"ownPublicCertificate": "[steps('parameters SSL').ownPublicCertificate]",
|
"ownPublicCertificate": "[steps('parameters SSL').ownPublicCertificate]",
|
||||||
"ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]",
|
"ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]",
|
||||||
"publicIpAddressObject": "[steps('parameters SSL').publicIpAddressObject]",
|
"publicIpAddressObject": "[steps('parameters SSL').publicIpAddressObject]",
|
||||||
"turnDomainName": "[steps('parameters TURN').turnDomainName]",
|
|
||||||
"turnOwnPublicCertificate": "[steps('parameters TURN').turnOwnPublicCertificate]",
|
|
||||||
"turnOwnPrivateCertificate": "[steps('parameters TURN').turnOwnPrivateCertificate]",
|
|
||||||
"openviduLicense": "[steps('parameters OPENVIDU').openviduLicense]",
|
"openviduLicense": "[steps('parameters OPENVIDU').openviduLicense]",
|
||||||
"rtcEngine": "[steps('parameters OPENVIDU').rtcEngine]",
|
"rtcEngine": "[steps('parameters OPENVIDU').rtcEngine]",
|
||||||
"initialMeetAdminPassword": "[steps('parameters MEET').initialMeetAdminPassword]",
|
"initialMeetAdminPassword": "[steps('parameters MEET').initialMeetAdminPassword]",
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ resource "google_secret_manager_secret" "openvidu_shared_info" {
|
||||||
for_each = toset([
|
for_each = toset([
|
||||||
"OPENVIDU_URL", "MEET_INITIAL_ADMIN_USER", "MEET_INITIAL_ADMIN_PASSWORD",
|
"OPENVIDU_URL", "MEET_INITIAL_ADMIN_USER", "MEET_INITIAL_ADMIN_PASSWORD",
|
||||||
"MEET_INITIAL_API_KEY", "LIVEKIT_URL", "LIVEKIT_API_KEY", "LIVEKIT_API_SECRET",
|
"MEET_INITIAL_API_KEY", "LIVEKIT_URL", "LIVEKIT_API_KEY", "LIVEKIT_API_SECRET",
|
||||||
"DASHBOARD_URL", "GRAFANA_URL", "MINIO_URL", "DOMAIN_NAME", "LIVEKIT_TURN_DOMAIN_NAME",
|
"DASHBOARD_URL", "GRAFANA_URL", "MINIO_URL", "DOMAIN_NAME",
|
||||||
"OPENVIDU_PRO_LICENSE", "OPENVIDU_RTC_ENGINE", "REDIS_PASSWORD", "MONGO_ADMIN_USERNAME",
|
"OPENVIDU_PRO_LICENSE", "OPENVIDU_RTC_ENGINE", "REDIS_PASSWORD", "MONGO_ADMIN_USERNAME",
|
||||||
"MONGO_ADMIN_PASSWORD", "MONGO_REPLICA_SET_KEY", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY",
|
"MONGO_ADMIN_PASSWORD", "MONGO_REPLICA_SET_KEY", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY",
|
||||||
"DASHBOARD_ADMIN_USERNAME", "DASHBOARD_ADMIN_PASSWORD", "GRAFANA_ADMIN_USERNAME",
|
"DASHBOARD_ADMIN_USERNAME", "DASHBOARD_ADMIN_PASSWORD", "GRAFANA_ADMIN_USERNAME",
|
||||||
|
|
@ -314,9 +314,6 @@ resource "google_compute_instance" "openvidu_master_node_1" {
|
||||||
certificateType = var.certificateType
|
certificateType = var.certificateType
|
||||||
ownPublicCertificate = var.ownPublicCertificate
|
ownPublicCertificate = var.ownPublicCertificate
|
||||||
ownPrivateCertificate = var.ownPrivateCertificate
|
ownPrivateCertificate = var.ownPrivateCertificate
|
||||||
turnDomainName = var.turnDomainName
|
|
||||||
turnOwnPublicCertificate = var.turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate = var.turnOwnPrivateCertificate
|
|
||||||
openviduLicense = var.openviduLicense
|
openviduLicense = var.openviduLicense
|
||||||
rtcEngine = var.rtcEngine
|
rtcEngine = var.rtcEngine
|
||||||
initialMeetAdminPassword = var.initialMeetAdminPassword
|
initialMeetAdminPassword = var.initialMeetAdminPassword
|
||||||
|
|
@ -367,9 +364,6 @@ resource "google_compute_instance" "openvidu_master_node_2" {
|
||||||
certificateType = var.certificateType
|
certificateType = var.certificateType
|
||||||
ownPublicCertificate = var.ownPublicCertificate
|
ownPublicCertificate = var.ownPublicCertificate
|
||||||
ownPrivateCertificate = var.ownPrivateCertificate
|
ownPrivateCertificate = var.ownPrivateCertificate
|
||||||
turnDomainName = var.turnDomainName
|
|
||||||
turnOwnPublicCertificate = var.turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate = var.turnOwnPrivateCertificate
|
|
||||||
openviduLicense = var.openviduLicense
|
openviduLicense = var.openviduLicense
|
||||||
rtcEngine = var.rtcEngine
|
rtcEngine = var.rtcEngine
|
||||||
initialMeetAdminPassword = var.initialMeetAdminPassword
|
initialMeetAdminPassword = var.initialMeetAdminPassword
|
||||||
|
|
@ -422,9 +416,6 @@ resource "google_compute_instance" "openvidu_master_node_3" {
|
||||||
certificateType = var.certificateType
|
certificateType = var.certificateType
|
||||||
ownPublicCertificate = var.ownPublicCertificate
|
ownPublicCertificate = var.ownPublicCertificate
|
||||||
ownPrivateCertificate = var.ownPrivateCertificate
|
ownPrivateCertificate = var.ownPrivateCertificate
|
||||||
turnDomainName = var.turnDomainName
|
|
||||||
turnOwnPublicCertificate = var.turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate = var.turnOwnPrivateCertificate
|
|
||||||
openviduLicense = var.openviduLicense
|
openviduLicense = var.openviduLicense
|
||||||
rtcEngine = var.rtcEngine
|
rtcEngine = var.rtcEngine
|
||||||
initialMeetAdminPassword = var.initialMeetAdminPassword
|
initialMeetAdminPassword = var.initialMeetAdminPassword
|
||||||
|
|
@ -477,9 +468,6 @@ resource "google_compute_instance" "openvidu_master_node_4" {
|
||||||
certificateType = var.certificateType
|
certificateType = var.certificateType
|
||||||
ownPublicCertificate = var.ownPublicCertificate
|
ownPublicCertificate = var.ownPublicCertificate
|
||||||
ownPrivateCertificate = var.ownPrivateCertificate
|
ownPrivateCertificate = var.ownPrivateCertificate
|
||||||
turnDomainName = var.turnDomainName
|
|
||||||
turnOwnPublicCertificate = var.turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate = var.turnOwnPrivateCertificate
|
|
||||||
openviduLicense = var.openviduLicense
|
openviduLicense = var.openviduLicense
|
||||||
rtcEngine = var.rtcEngine
|
rtcEngine = var.rtcEngine
|
||||||
initialMeetAdminPassword = var.initialMeetAdminPassword
|
initialMeetAdminPassword = var.initialMeetAdminPassword
|
||||||
|
|
@ -952,7 +940,7 @@ locals {
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
YQ_VERSION=v4.44.5
|
YQ_VERSION=v4.44.5
|
||||||
|
|
||||||
|
|
@ -995,7 +983,6 @@ if [[ $MASTER_NODE_NUM -eq 1 ]] && [[ "$ALL_SECRETS_GENERATED" == "false" ]]; th
|
||||||
EXTERNAL_IP=$(gcloud compute addresses describe "${lower("${var.stackName}-nlb-ip")}" --region ${var.region} --format="get(address)")
|
EXTERNAL_IP=$(gcloud compute addresses describe "${lower("${var.stackName}-nlb-ip")}" --region ${var.region} --format="get(address)")
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io"
|
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io"
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io"
|
|
||||||
else
|
else
|
||||||
DOMAIN="${var.domainName}"
|
DOMAIN="${var.domainName}"
|
||||||
fi
|
fi
|
||||||
|
|
@ -1013,13 +1000,6 @@ if [[ $MASTER_NODE_NUM -eq 1 ]] && [[ "$ALL_SECRETS_GENERATED" == "false" ]]; th
|
||||||
MEET_INITIAL_API_KEY="$(/usr/local/bin/store_secret.sh save MEET_INITIAL_API_KEY "${var.initialMeetApiKey}")"
|
MEET_INITIAL_API_KEY="$(/usr/local/bin/store_secret.sh save MEET_INITIAL_API_KEY "${var.initialMeetApiKey}")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Configure TURN server domain name
|
|
||||||
if [[ -n "${var.turnDomainName}" ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${var.turnDomainName}")"
|
|
||||||
elif [[ "$${TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "$${TURN_DOMAIN_NAME_SSLIP_IO}")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Store usernames and generate random passwords
|
# Store usernames and generate random passwords
|
||||||
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/store_secret.sh save OPENVIDU_PRO_LICENSE "${var.openviduLicense}")"
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/store_secret.sh save OPENVIDU_PRO_LICENSE "${var.openviduLicense}")"
|
||||||
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/store_secret.sh save OPENVIDU_RTC_ENGINE "${var.rtcEngine}")"
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/store_secret.sh save OPENVIDU_RTC_ENGINE "${var.rtcEngine}")"
|
||||||
|
|
@ -1065,7 +1045,6 @@ MASTER_NODE_4_PRIVATE_IP=$(gcloud secrets versions access latest --secret=MASTER
|
||||||
MASTER_NODE_PRIVATE_IP_LIST="$MASTER_NODE_1_PRIVATE_IP,$MASTER_NODE_2_PRIVATE_IP,$MASTER_NODE_3_PRIVATE_IP,$MASTER_NODE_4_PRIVATE_IP"
|
MASTER_NODE_PRIVATE_IP_LIST="$MASTER_NODE_1_PRIVATE_IP,$MASTER_NODE_2_PRIVATE_IP,$MASTER_NODE_3_PRIVATE_IP,$MASTER_NODE_4_PRIVATE_IP"
|
||||||
|
|
||||||
DOMAIN=$(gcloud secrets versions access latest --secret=DOMAIN_NAME)
|
DOMAIN=$(gcloud secrets versions access latest --secret=DOMAIN_NAME)
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(gcloud secrets versions access latest --secret=LIVEKIT_TURN_DOMAIN_NAME)
|
|
||||||
OPENVIDU_PRO_LICENSE=$(gcloud secrets versions access latest --secret=OPENVIDU_PRO_LICENSE)
|
OPENVIDU_PRO_LICENSE=$(gcloud secrets versions access latest --secret=OPENVIDU_PRO_LICENSE)
|
||||||
OPENVIDU_RTC_ENGINE=$(gcloud secrets versions access latest --secret=OPENVIDU_RTC_ENGINE)
|
OPENVIDU_RTC_ENGINE=$(gcloud secrets versions access latest --secret=OPENVIDU_RTC_ENGINE)
|
||||||
REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
||||||
|
|
@ -1132,10 +1111,6 @@ if [[ "${var.additionalInstallFlags}" != "" ]]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$LIVEKIT_TURN_DOMAIN_NAME" != "" ]]; then
|
|
||||||
COMMON_ARGS+=("--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -1155,18 +1130,6 @@ else
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${var.turnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${var.turnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${var.turnOwnPrivateCertificate}
|
|
||||||
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the final command
|
# Construct the final command
|
||||||
|
|
@ -1246,6 +1209,178 @@ gcloud secrets versions access latest --secret=MINIO_URL
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
echo "Error updating secret_manager"
|
echo "Error updating secret_manager"
|
||||||
fi
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
update_config_from_secret_script = <<-EOF
|
||||||
|
#!/bin/bash -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Configure gcloud with instance service account
|
||||||
|
gcloud auth activate-service-account --key-file=/dev/null 2>/dev/null || true
|
||||||
|
|
||||||
|
# Installation directory
|
||||||
|
INSTALL_DIR="/opt/openvidu"
|
||||||
|
CLUSTER_CONFIG_DIR="$${INSTALL_DIR}/config/cluster"
|
||||||
|
MASTER_NODE_CONFIG_DIR="$${INSTALL_DIR}/config/node"
|
||||||
|
|
||||||
|
# Replace DOMAIN_NAME
|
||||||
|
export DOMAIN=$(gcloud secrets versions access latest --secret=DOMAIN_NAME)
|
||||||
|
if [[ -n "$DOMAIN" ]]; then
|
||||||
|
sed -i "s/DOMAIN_NAME=.*/DOMAIN_NAME=$DOMAIN/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the rest of the values
|
||||||
|
export REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
||||||
|
export OPENVIDU_RTC_ENGINE=$(gcloud secrets versions access latest --secret=OPENVIDU_RTC_ENGINE)
|
||||||
|
export OPENVIDU_PRO_LICENSE=$(gcloud secrets versions access latest --secret=OPENVIDU_PRO_LICENSE)
|
||||||
|
export MONGO_ADMIN_USERNAME=$(gcloud secrets versions access latest --secret=MONGO_ADMIN_USERNAME)
|
||||||
|
export MONGO_ADMIN_PASSWORD=$(gcloud secrets versions access latest --secret=MONGO_ADMIN_PASSWORD)
|
||||||
|
export MONGO_REPLICA_SET_KEY=$(gcloud secrets versions access latest --secret=MONGO_REPLICA_SET_KEY)
|
||||||
|
export DASHBOARD_ADMIN_USERNAME=$(gcloud secrets versions access latest --secret=DASHBOARD_ADMIN_USERNAME)
|
||||||
|
export DASHBOARD_ADMIN_PASSWORD=$(gcloud secrets versions access latest --secret=DASHBOARD_ADMIN_PASSWORD)
|
||||||
|
export MINIO_ACCESS_KEY=$(gcloud secrets versions access latest --secret=MINIO_ACCESS_KEY)
|
||||||
|
export MINIO_SECRET_KEY=$(gcloud secrets versions access latest --secret=MINIO_SECRET_KEY)
|
||||||
|
export GRAFANA_ADMIN_USERNAME=$(gcloud secrets versions access latest --secret=GRAFANA_ADMIN_USERNAME)
|
||||||
|
export GRAFANA_ADMIN_PASSWORD=$(gcloud secrets versions access latest --secret=GRAFANA_ADMIN_PASSWORD)
|
||||||
|
export LIVEKIT_API_KEY=$(gcloud secrets versions access latest --secret=LIVEKIT_API_KEY)
|
||||||
|
export LIVEKIT_API_SECRET=$(gcloud secrets versions access latest --secret=LIVEKIT_API_SECRET)
|
||||||
|
export MEET_INITIAL_ADMIN_USER=$(gcloud secrets versions access latest --secret=MEET_INITIAL_ADMIN_USER)
|
||||||
|
export MEET_INITIAL_ADMIN_PASSWORD=$(gcloud secrets versions access latest --secret=MEET_INITIAL_ADMIN_PASSWORD)
|
||||||
|
if [[ "${var.initialMeetApiKey}" != '' ]]; then
|
||||||
|
export MEET_INITIAL_API_KEY=$(gcloud secrets versions access latest --secret=MEET_INITIAL_API_KEY)
|
||||||
|
fi
|
||||||
|
export ENABLED_MODULES=$(gcloud secrets versions access latest --secret=ENABLED_MODULES)
|
||||||
|
|
||||||
|
# Replace rest of the values
|
||||||
|
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$REDIS_PASSWORD/" "$${MASTER_NODE_CONFIG_DIR}/master_node.env"
|
||||||
|
sed -i "s/OPENVIDU_RTC_ENGINE=.*/OPENVIDU_RTC_ENGINE=$OPENVIDU_RTC_ENGINE/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/OPENVIDU_PRO_LICENSE=.*/OPENVIDU_PRO_LICENSE=$OPENVIDU_PRO_LICENSE/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/MONGO_ADMIN_USERNAME=.*/MONGO_ADMIN_USERNAME=$MONGO_ADMIN_USERNAME/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/MONGO_ADMIN_PASSWORD=.*/MONGO_ADMIN_PASSWORD=$MONGO_ADMIN_PASSWORD/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/MONGO_REPLICA_SET_KEY=.*/MONGO_REPLICA_SET_KEY=$MONGO_REPLICA_SET_KEY/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/DASHBOARD_ADMIN_USERNAME=.*/DASHBOARD_ADMIN_USERNAME=$DASHBOARD_ADMIN_USERNAME/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/DASHBOARD_ADMIN_PASSWORD=.*/DASHBOARD_ADMIN_PASSWORD=$DASHBOARD_ADMIN_PASSWORD/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/MINIO_ACCESS_KEY=.*/MINIO_ACCESS_KEY=$MINIO_ACCESS_KEY/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/MINIO_SECRET_KEY=.*/MINIO_SECRET_KEY=$MINIO_SECRET_KEY/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/GRAFANA_ADMIN_USERNAME=.*/GRAFANA_ADMIN_USERNAME=$GRAFANA_ADMIN_USERNAME/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/GRAFANA_ADMIN_PASSWORD=.*/GRAFANA_ADMIN_PASSWORD=$GRAFANA_ADMIN_PASSWORD/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/LIVEKIT_API_KEY=.*/LIVEKIT_API_KEY=$LIVEKIT_API_KEY/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/LIVEKIT_API_SECRET=.*/LIVEKIT_API_SECRET=$LIVEKIT_API_SECRET/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
sed -i "s/MEET_INITIAL_ADMIN_USER=.*/MEET_INITIAL_ADMIN_USER=$MEET_INITIAL_ADMIN_USER/" "$${CLUSTER_CONFIG_DIR}/master_node/meet.env"
|
||||||
|
sed -i "s/MEET_INITIAL_ADMIN_PASSWORD=.*/MEET_INITIAL_ADMIN_PASSWORD=$MEET_INITIAL_ADMIN_PASSWORD/" "$${CLUSTER_CONFIG_DIR}/master_node/meet.env"
|
||||||
|
if [[ "${var.initialMeetApiKey}" != '' ]]; then
|
||||||
|
sed -i "s/MEET_INITIAL_API_KEY=.*/MEET_INITIAL_API_KEY=$MEET_INITIAL_API_KEY/" "$${CLUSTER_CONFIG_DIR}/master_node/meet.env"
|
||||||
|
fi
|
||||||
|
sed -i "s/ENABLED_MODULES=.*/ENABLED_MODULES=$ENABLED_MODULES/" "$${CLUSTER_CONFIG_DIR}/openvidu.env"
|
||||||
|
|
||||||
|
# Update URLs in secret
|
||||||
|
OPENVIDU_URL="https://$${DOMAIN}/"
|
||||||
|
LIVEKIT_URL="wss://$${DOMAIN}/"
|
||||||
|
DASHBOARD_URL="https://$${DOMAIN}/dashboard/"
|
||||||
|
GRAFANA_URL="https://$${DOMAIN}/grafana/"
|
||||||
|
MINIO_URL="https://$${DOMAIN}/minio-console/"
|
||||||
|
|
||||||
|
# Update shared secret
|
||||||
|
echo -n "$DOMAIN" | gcloud secrets versions add DOMAIN_NAME --data-file=-
|
||||||
|
echo -n "$OPENVIDU_URL" | gcloud secrets versions add OPENVIDU_URL --data-file=-
|
||||||
|
echo -n "$LIVEKIT_URL" | gcloud secrets versions add LIVEKIT_URL --data-file=-
|
||||||
|
echo -n "$DASHBOARD_URL" | gcloud secrets versions add DASHBOARD_URL --data-file=-
|
||||||
|
echo -n "$GRAFANA_URL" | gcloud secrets versions add GRAFANA_URL --data-file=-
|
||||||
|
echo -n "$MINIO_URL" | gcloud secrets versions add MINIO_URL --data-file=-
|
||||||
|
EOF
|
||||||
|
|
||||||
|
update_secret_from_config_script = <<-EOF
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Configure gcloud with instance service account
|
||||||
|
gcloud auth activate-service-account --key-file=/dev/null 2>/dev/null || true
|
||||||
|
|
||||||
|
# Installation directory
|
||||||
|
INSTALL_DIR="/opt/openvidu"
|
||||||
|
CLUSTER_CONFIG_DIR="$${INSTALL_DIR}/config/cluster"
|
||||||
|
MASTER_NODE_CONFIG_DIR="$${INSTALL_DIR}/config/node"
|
||||||
|
|
||||||
|
# Get current values of the config
|
||||||
|
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "$${MASTER_NODE_CONFIG_DIR}/master_node.env")"
|
||||||
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
MINIO_ACCESS_KEY="$(/usr/local/bin/get_value_from_config.sh MINIO_ACCESS_KEY "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
MINIO_SECRET_KEY="$(/usr/local/bin/get_value_from_config.sh MINIO_SECRET_KEY "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
DASHBOARD_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh DASHBOARD_ADMIN_USERNAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
DASHBOARD_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh DASHBOARD_ADMIN_PASSWORD "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
GRAFANA_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh GRAFANA_ADMIN_USERNAME "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
GRAFANA_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh GRAFANA_ADMIN_PASSWORD "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
LIVEKIT_API_KEY="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_API_KEY "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
LIVEKIT_API_SECRET="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_API_SECRET "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
MEET_INITIAL_ADMIN_USER="$(/usr/local/bin/get_value_from_config.sh MEET_INITIAL_ADMIN_USER "$${CLUSTER_CONFIG_DIR}/master_node/meet.env")"
|
||||||
|
MEET_INITIAL_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MEET_INITIAL_ADMIN_PASSWORD "$${CLUSTER_CONFIG_DIR}/master_node/meet.env")"
|
||||||
|
if [[ "${var.initialMeetApiKey}" != '' ]]; then
|
||||||
|
MEET_INITIAL_API_KEY="$(/usr/local/bin/get_value_from_config.sh MEET_INITIAL_API_KEY "$${CLUSTER_CONFIG_DIR}/master_node/meet.env")"
|
||||||
|
fi
|
||||||
|
ENABLED_MODULES="$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES "$${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
||||||
|
|
||||||
|
# Update shared secret
|
||||||
|
echo -n "$REDIS_PASSWORD" | gcloud secrets versions add REDIS_PASSWORD --data-file=-
|
||||||
|
echo -n "$DOMAIN_NAME" | gcloud secrets versions add DOMAIN_NAME --data-file=-
|
||||||
|
echo -n "$OPENVIDU_RTC_ENGINE" | gcloud secrets versions add OPENVIDU_RTC_ENGINE --data-file=-
|
||||||
|
echo -n "$OPENVIDU_PRO_LICENSE" | gcloud secrets versions add OPENVIDU_PRO_LICENSE --data-file=-
|
||||||
|
echo -n "$MONGO_ADMIN_USERNAME" | gcloud secrets versions add MONGO_ADMIN_USERNAME --data-file=-
|
||||||
|
echo -n "$MONGO_ADMIN_PASSWORD" | gcloud secrets versions add MONGO_ADMIN_PASSWORD --data-file=-
|
||||||
|
echo -n "$MONGO_REPLICA_SET_KEY" | gcloud secrets versions add MONGO_REPLICA_SET_KEY --data-file=-
|
||||||
|
echo -n "$MINIO_ACCESS_KEY" | gcloud secrets versions add MINIO_ACCESS_KEY --data-file=-
|
||||||
|
echo -n "$MINIO_SECRET_KEY" | gcloud secrets versions add MINIO_SECRET_KEY --data-file=-
|
||||||
|
echo -n "$DASHBOARD_ADMIN_USERNAME" | gcloud secrets versions add DASHBOARD_ADMIN_USERNAME --data-file=-
|
||||||
|
echo -n "$DASHBOARD_ADMIN_PASSWORD" | gcloud secrets versions add DASHBOARD_ADMIN_PASSWORD --data-file=-
|
||||||
|
echo -n "$GRAFANA_ADMIN_USERNAME" | gcloud secrets versions add GRAFANA_ADMIN_USERNAME --data-file=-
|
||||||
|
echo -n "$GRAFANA_ADMIN_PASSWORD" | gcloud secrets versions add GRAFANA_ADMIN_PASSWORD --data-file=-
|
||||||
|
echo -n "$LIVEKIT_API_KEY" | gcloud secrets versions add LIVEKIT_API_KEY --data-file=-
|
||||||
|
echo -n "$LIVEKIT_API_SECRET" | gcloud secrets versions add LIVEKIT_API_SECRET --data-file=-
|
||||||
|
echo -n "$MEET_INITIAL_ADMIN_USER" | gcloud secrets versions add MEET_INITIAL_ADMIN_USER --data-file=-
|
||||||
|
echo -n "$MEET_INITIAL_ADMIN_PASSWORD" | gcloud secrets versions add MEET_INITIAL_ADMIN_PASSWORD --data-file=-
|
||||||
|
if [[ "${var.initialMeetApiKey}" != '' ]]; then
|
||||||
|
echo -n "$MEET_INITIAL_API_KEY" | gcloud secrets versions add MEET_INITIAL_API_KEY --data-file=-
|
||||||
|
fi
|
||||||
|
echo -n "$ENABLED_MODULES" | gcloud secrets versions add ENABLED_MODULES --data-file=-
|
||||||
|
EOF
|
||||||
|
|
||||||
|
get_value_from_config_script = <<-EOF
|
||||||
|
#!/bin/bash -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Function to get the value of a given key from the environment file
|
||||||
|
get_value() {
|
||||||
|
local key="$1"
|
||||||
|
local file_path="$2"
|
||||||
|
# Use grep to find the line with the key, ignoring lines starting with #
|
||||||
|
# Use awk to split on '=' and print the second field, which is the value
|
||||||
|
local value=$(grep -E "^\s*$key\s*=" "$file_path" | awk -F= '{print $2}' | sed 's/#.*//; s/^\s*//; s/\s*$//')
|
||||||
|
# If the value is empty, return "none"
|
||||||
|
if [ -z "$value" ]; then
|
||||||
|
echo "none"
|
||||||
|
else
|
||||||
|
echo "$value"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if the correct number of arguments are supplied
|
||||||
|
if [ "$#" -ne 2 ]; then
|
||||||
|
echo "Usage: $0 <key> <file_path>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the key and file path from the arguments
|
||||||
|
key="$1"
|
||||||
|
file_path="$2"
|
||||||
|
|
||||||
|
# Get and print the value
|
||||||
|
get_value "$key" "$file_path"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
store_secret_script = <<-EOF
|
store_secret_script = <<-EOF
|
||||||
|
|
@ -1326,6 +1461,25 @@ ${local.after_install_script}
|
||||||
AFTER_INSTALL_EOF
|
AFTER_INSTALL_EOF
|
||||||
chmod +x /usr/local/bin/after_install.sh
|
chmod +x /usr/local/bin/after_install.sh
|
||||||
|
|
||||||
|
# update_config_from_secret.sh
|
||||||
|
cat > /usr/local/bin/update_config_from_secret.sh << 'UPDATE_CONFIG_EOF'
|
||||||
|
${local.update_config_from_secret_script}
|
||||||
|
UPDATE_CONFIG_EOF
|
||||||
|
chmod +x /usr/local/bin/update_config_from_secret.sh
|
||||||
|
|
||||||
|
# update_secret_from_config.sh
|
||||||
|
cat > /usr/local/bin/update_secret_from_config.sh << 'UPDATE_SECRET_EOF'
|
||||||
|
${local.update_secret_from_config_script}
|
||||||
|
UPDATE_SECRET_EOF
|
||||||
|
chmod +x /usr/local/bin/update_secret_from_config.sh
|
||||||
|
|
||||||
|
# get_value_from_config.sh
|
||||||
|
cat > /usr/local/bin/get_value_from_config.sh << 'GET_VALUE_EOF'
|
||||||
|
${local.get_value_from_config_script}
|
||||||
|
GET_VALUE_EOF
|
||||||
|
chmod +x /usr/local/bin/get_value_from_config.sh
|
||||||
|
|
||||||
|
|
||||||
cat > /usr/local/bin/store_secret.sh << 'STORE_SECRET_EOF'
|
cat > /usr/local/bin/store_secret.sh << 'STORE_SECRET_EOF'
|
||||||
${local.store_secret_script}
|
${local.store_secret_script}
|
||||||
STORE_SECRET_EOF
|
STORE_SECRET_EOF
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ variable "minNumberOfMediaNodes" {
|
||||||
variable "maxNumberOfMediaNodes" {
|
variable "maxNumberOfMediaNodes" {
|
||||||
description = "Maximum number of media nodes to deploy"
|
description = "Maximum number of media nodes to deploy"
|
||||||
type = number
|
type = number
|
||||||
default = 2
|
default = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "scaleTargetCPU" {
|
variable "scaleTargetCPU" {
|
||||||
|
|
@ -168,21 +168,3 @@ variable "additionalInstallFlags" {
|
||||||
error_message = "Must be a comma-separated list of flags (for example, --flag=value, --bool-flag)."
|
error_message = "Must be a comma-separated list of flags (for example, --flag=value, --bool-flag)."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "turnDomainName" {
|
|
||||||
description = "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls"
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "turnOwnPublicCertificate" {
|
|
||||||
description = "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "turnOwnPrivateCertificate" {
|
|
||||||
description = "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
||||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
||||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.5.0}"
|
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
||||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
||||||
|
|
@ -19,7 +19,7 @@ export OPENVIDU_MEET_SERVER_IMAGE="${OPENVIDU_MEET_SERVER_IMAGE:-docker.io/openv
|
||||||
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing:${OPENVIDU_VERSION}}"
|
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-cloud:${OPENVIDU_VERSION}}"
|
||||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${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 LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
||||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
||||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.5.0}"
|
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
||||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
||||||
|
|
@ -19,7 +19,7 @@ export OPENVIDU_MEET_SERVER_IMAGE="${OPENVIDU_MEET_SERVER_IMAGE:-docker.io/openv
|
||||||
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing:${OPENVIDU_VERSION}}"
|
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-cloud:${OPENVIDU_VERSION}}"
|
||||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${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 LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
services:
|
services:
|
||||||
caddy-proxy:
|
caddy-proxy:
|
||||||
image: docker.io/openvidu/openvidu-caddy-local:3.5.0
|
image: docker.io/openvidu/openvidu-caddy-local:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|
@ -26,6 +26,7 @@ services:
|
||||||
- 7443:7443
|
- 7443:7443
|
||||||
- 7880:7880
|
- 7880:7880
|
||||||
- 9443:9443
|
- 9443:9443
|
||||||
|
- 9080:9080
|
||||||
depends_on:
|
depends_on:
|
||||||
setup:
|
setup:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
@ -86,7 +87,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
dashboard:
|
dashboard:
|
||||||
image: docker.io/openvidu/openvidu-dashboard:3.5.0
|
image: docker.io/openvidu/openvidu-dashboard:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
@ -100,7 +101,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
openvidu:
|
openvidu:
|
||||||
image: docker.io/openvidu/openvidu-server-pro:3.5.0
|
image: docker.io/openvidu/openvidu-server-pro:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|
@ -123,7 +124,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
ingress:
|
ingress:
|
||||||
image: docker.io/openvidu/ingress:3.5.0
|
image: docker.io/openvidu/ingress:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|
@ -141,7 +142,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
egress:
|
egress:
|
||||||
image: docker.io/openvidu/egress:3.5.0
|
image: docker.io/openvidu/egress:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
|
|
@ -155,7 +156,7 @@ services:
|
||||||
setup:
|
setup:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
operator:
|
operator:
|
||||||
image: docker.io/openvidu/openvidu-operator:3.5.0
|
image: docker.io/openvidu/openvidu-operator:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
|
@ -179,10 +180,8 @@ services:
|
||||||
|
|
||||||
|
|
||||||
openvidu-meet:
|
openvidu-meet:
|
||||||
image: docker.io/openvidu/openvidu-meet:3.5.0
|
image: docker.io/openvidu/openvidu-meet:main
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
ports:
|
|
||||||
- 9080:6080
|
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- host.docker.internal:host-gateway
|
- host.docker.internal:host-gateway
|
||||||
environment:
|
environment:
|
||||||
|
|
@ -220,7 +219,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
openvidu-v2compatibility:
|
openvidu-v2compatibility:
|
||||||
image: docker.io/openvidu/openvidu-v2compatibility:3.5.0
|
image: docker.io/openvidu/openvidu-v2compatibility:main
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
entrypoint: /bin/sh /scripts/entrypoint_openvidu_v2_compat.sh
|
entrypoint: /bin/sh /scripts/entrypoint_openvidu_v2_compat.sh
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
|
|
@ -257,7 +256,7 @@ services:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|
||||||
openvidu-meet-init:
|
openvidu-meet-init:
|
||||||
image: docker.io/openvidu/openvidu-operator:3.5.0
|
image: docker.io/openvidu/openvidu-operator:main
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
environment:
|
environment:
|
||||||
- MODE=local-ready-check
|
- MODE=local-ready-check
|
||||||
|
|
|
||||||
|
|
@ -60,20 +60,6 @@ Parameters:
|
||||||
AllowedPattern: '^[A-Za-z0-9, =_.\-]*$' # Allows letters, numbers, comma, space, underscore, dot, equals, and hyphen
|
AllowedPattern: '^[A-Za-z0-9, =_.\-]*$' # Allows letters, numbers, comma, space, underscore, dot, equals, and hyphen
|
||||||
ConstraintDescription: Must be a comma-separated list of flags (for example, --flag=value, --bool-flag).
|
ConstraintDescription: Must be a comma-separated list of flags (for example, --flag=value, --bool-flag).
|
||||||
|
|
||||||
TurnDomainName:
|
|
||||||
Description: '(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls'
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
TurnOwnPublicCertificate:
|
|
||||||
Description: "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
TurnOwnPrivateCertificate:
|
|
||||||
Description: "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
Type: String
|
|
||||||
Default: ''
|
|
||||||
|
|
||||||
OpenViduLicense:
|
OpenViduLicense:
|
||||||
Description: "Visit https://openvidu.io/account"
|
Description: "Visit https://openvidu.io/account"
|
||||||
|
|
@ -476,12 +462,6 @@ Metadata:
|
||||||
default: "(Optional) Additional Installer Flags"
|
default: "(Optional) Additional Installer Flags"
|
||||||
Parameters:
|
Parameters:
|
||||||
- AdditionalInstallFlags
|
- AdditionalInstallFlags
|
||||||
- Label:
|
|
||||||
default: (Optional) TURN server configuration with TLS
|
|
||||||
Parameters:
|
|
||||||
- TurnDomainName
|
|
||||||
- TurnOwnPublicCertificate
|
|
||||||
- TurnOwnPrivateCertificate
|
|
||||||
|
|
||||||
Conditions:
|
Conditions:
|
||||||
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ]
|
PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ]
|
||||||
|
|
@ -534,7 +514,6 @@ Resources:
|
||||||
"GRAFANA_URL": "none",
|
"GRAFANA_URL": "none",
|
||||||
"MINIO_URL": "none",
|
"MINIO_URL": "none",
|
||||||
"DOMAIN_NAME": "none",
|
"DOMAIN_NAME": "none",
|
||||||
"LIVEKIT_TURN_DOMAIN_NAME": "none",
|
|
||||||
"OPENVIDU_PRO_LICENSE": "none",
|
"OPENVIDU_PRO_LICENSE": "none",
|
||||||
"OPENVIDU_RTC_ENGINE": "none",
|
"OPENVIDU_RTC_ENGINE": "none",
|
||||||
"REDIS_PASSWORD": "none",
|
"REDIS_PASSWORD": "none",
|
||||||
|
|
@ -639,7 +618,7 @@ Resources:
|
||||||
'/usr/local/bin/install.sh':
|
'/usr/local/bin/install.sh':
|
||||||
content: !Sub |
|
content: !Sub |
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
YQ_VERSION=v4.44.5
|
YQ_VERSION=v4.44.5
|
||||||
|
|
||||||
|
|
@ -665,7 +644,6 @@ Resources:
|
||||||
PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname)
|
PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname)
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io
|
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io"
|
|
||||||
else
|
else
|
||||||
DOMAIN=${DomainName}
|
DOMAIN=${DomainName}
|
||||||
fi
|
fi
|
||||||
|
|
@ -743,18 +721,6 @@ Resources:
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${!TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${!TURN_DOMAIN_NAME_SSLIP_IO}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${TurnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${TurnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${CertificateType}" == "selfsigned" ]]; then
|
if [[ "${CertificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -774,18 +740,6 @@ Resources:
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${TurnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${TurnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${TurnOwnPrivateCertificate}
|
|
||||||
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the final command with all arguments
|
# Construct the final command with all arguments
|
||||||
|
|
@ -882,12 +836,6 @@ Resources:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(echo $SHARED_SECRET | jq -r .LIVEKIT_TURN_DOMAIN_NAME)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${!CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Replace rest of the values
|
# Replace rest of the values
|
||||||
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!CONFIG_DIR}/openvidu.env"
|
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!CONFIG_DIR}/openvidu.env"
|
||||||
sed -i "s/OPENVIDU_PRO_LICENSE=.*/OPENVIDU_PRO_LICENSE=$(echo $SHARED_SECRET | jq -r .OPENVIDU_PRO_LICENSE)/" "${!CONFIG_DIR}/openvidu.env"
|
sed -i "s/OPENVIDU_PRO_LICENSE=.*/OPENVIDU_PRO_LICENSE=$(echo $SHARED_SECRET | jq -r .OPENVIDU_PRO_LICENSE)/" "${!CONFIG_DIR}/openvidu.env"
|
||||||
|
|
@ -948,7 +896,6 @@ Resources:
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_PRO_LICENSE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_PRO_LICENSE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_RTC_ENGINE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_RTC_ENGINE": "'"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"LIVEKIT_TURN_DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_USERNAME": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_USERNAME": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_ADMIN_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_REPLICA_SET_KEY": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"MONGO_REPLICA_SET_KEY": "'"$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "${!CONFIG_DIR}/openvidu.env")"'"}')"
|
||||||
|
|
@ -1144,7 +1091,7 @@ Resources:
|
||||||
BlockDeviceMappings:
|
BlockDeviceMappings:
|
||||||
- DeviceName: /dev/sda1
|
- DeviceName: /dev/sda1
|
||||||
Ebs:
|
Ebs:
|
||||||
VolumeType: gp2
|
VolumeType: gp3
|
||||||
DeleteOnTermination: true
|
DeleteOnTermination: true
|
||||||
VolumeSize: 200
|
VolumeSize: 200
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,15 +33,6 @@ param initialMeetAdminPassword string = ''
|
||||||
@secure()
|
@secure()
|
||||||
param initialMeetApiKey string = ''
|
param initialMeetApiKey string = ''
|
||||||
|
|
||||||
@description('(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls')
|
|
||||||
param turnDomainName string = ''
|
|
||||||
|
|
||||||
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified. Provide in base64 format.')
|
|
||||||
param turnOwnPublicCertificate string = ''
|
|
||||||
|
|
||||||
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified. Provide in base64 format.')
|
|
||||||
param turnOwnPrivateCertificate string = ''
|
|
||||||
|
|
||||||
@description('Visit https://openvidu.io/account')
|
@description('Visit https://openvidu.io/account')
|
||||||
@secure()
|
@secure()
|
||||||
param openviduLicense string
|
param openviduLicense string
|
||||||
|
|
@ -170,12 +161,9 @@ resource openviduSharedInfo 'Microsoft.KeyVault/vaults@2023-07-01' = {
|
||||||
var stringInterpolationParams = {
|
var stringInterpolationParams = {
|
||||||
publicIPId: publicIPId
|
publicIPId: publicIPId
|
||||||
domainName: domainName
|
domainName: domainName
|
||||||
turnDomainName: turnDomainName
|
|
||||||
certificateType: certificateType
|
certificateType: certificateType
|
||||||
ownPublicCertificate: ownPublicCertificate
|
ownPublicCertificate: ownPublicCertificate
|
||||||
ownPrivateCertificate: ownPrivateCertificate
|
ownPrivateCertificate: ownPrivateCertificate
|
||||||
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
||||||
initialMeetAdminPassword: initialMeetAdminPassword
|
initialMeetAdminPassword: initialMeetAdminPassword
|
||||||
initialMeetApiKey: initialMeetApiKey
|
initialMeetApiKey: initialMeetApiKey
|
||||||
keyVaultName: keyVaultName
|
keyVaultName: keyVaultName
|
||||||
|
|
@ -186,7 +174,7 @@ var stringInterpolationParams = {
|
||||||
|
|
||||||
var installScriptTemplate = '''
|
var installScriptTemplate = '''
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
|
|
||||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||||
|
|
@ -208,7 +196,6 @@ if [[ "${domainName}" == '' ]]; then
|
||||||
|
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
DOMAIN="openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo "$PUBLIC_IP" | tr '.' '-').sslip.io"
|
|
||||||
else
|
else
|
||||||
DOMAIN=${domainName}
|
DOMAIN=${domainName}
|
||||||
fi
|
fi
|
||||||
|
|
@ -286,19 +273,6 @@ if [[ "${additionalInstallFlags}" != "" ]]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Turn with TLS
|
|
||||||
if [[ "${turnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${turnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${TURN_DOMAIN_NAME_SSLIP_IO}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${certificateType}" == "selfsigned" ]]; then
|
if [[ "${certificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -318,18 +292,6 @@ else
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${turnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${turnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${turnOwnPrivateCertificate}
|
|
||||||
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Construct the final command with all arguments
|
# Construct the final command with all arguments
|
||||||
|
|
@ -387,12 +349,6 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --query value -o tsv)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the rest of the values
|
# Get the rest of the values
|
||||||
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
||||||
export OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
export OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
||||||
|
|
@ -469,7 +425,6 @@ CONFIG_DIR="${INSTALL_DIR}/config"
|
||||||
# Get current values of the config
|
# Get current values of the config
|
||||||
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${CONFIG_DIR}/openvidu.env")"
|
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${CONFIG_DIR}/openvidu.env")"
|
||||||
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CONFIG_DIR}/openvidu.env")"
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CONFIG_DIR}/openvidu.env")"
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${CONFIG_DIR}/openvidu.env")"
|
|
||||||
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${CONFIG_DIR}/openvidu.env")"
|
||||||
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CONFIG_DIR}/openvidu.env")"
|
||||||
|
|
@ -494,7 +449,6 @@ ENABLED_MODULES="$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES "${CO
|
||||||
# Update shared secret
|
# Update shared secret
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --value $LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --value $OPENVIDU_RTC_ENGINE
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --value $OPENVIDU_RTC_ENGINE
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --value $OPENVIDU_PRO_LICENSE
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --value $OPENVIDU_PRO_LICENSE
|
||||||
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -381,70 +381,6 @@
|
||||||
"visible": true
|
"visible": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "parameters TURN",
|
|
||||||
"label": "(Optional) TURN server configuration with TLS",
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"name": "turnDomainName",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Domain Name",
|
|
||||||
"subLabel": "\n(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": []
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "turnOwnPublicCertificate",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Own Public Certificate",
|
|
||||||
"subLabel": "\n(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format.",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPublicCertificate)), true)]",
|
|
||||||
"message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "turnOwnPrivateCertificate",
|
|
||||||
"type": "Microsoft.Common.TextBox",
|
|
||||||
"label": "Turn Own Private Certificate",
|
|
||||||
"subLabel": "\n(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format.",
|
|
||||||
"defaultValue": "",
|
|
||||||
"toolTip": "",
|
|
||||||
"constraints": {
|
|
||||||
"required": false,
|
|
||||||
"regex": "",
|
|
||||||
"validationMessage": "",
|
|
||||||
"validations": [
|
|
||||||
{
|
|
||||||
"isValid": "[if(and(equals(steps('parameters SSL').certificateType, 'owncert'), not(empty(steps('parameters TURN').turnDomainName))), not(empty(steps('parameters TURN').turnOwnPrivateCertificate)), true)]",
|
|
||||||
"message": "You need to fill this parameter because you've selected owncert certificate type and you've filled Turn Domain Name."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"infoMessages": [],
|
|
||||||
"visible": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -461,9 +397,6 @@
|
||||||
"ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]",
|
"ownPrivateCertificate": "[steps('parameters SSL').ownPrivateCertificate]",
|
||||||
"openviduLicense": "[steps('parameters OPENVIDU').openviduLicense]",
|
"openviduLicense": "[steps('parameters OPENVIDU').openviduLicense]",
|
||||||
"rtcEngine": "[steps('parameters OPENVIDU').rtcEngine]",
|
"rtcEngine": "[steps('parameters OPENVIDU').rtcEngine]",
|
||||||
"turnDomainName": "[steps('parameters TURN').turnDomainName]",
|
|
||||||
"turnOwnPublicCertificate": "[steps('parameters TURN').turnOwnPublicCertificate]",
|
|
||||||
"turnOwnPrivateCertificate": "[steps('parameters TURN').turnOwnPrivateCertificate]",
|
|
||||||
"initialMeetAdminPassword": "[steps('parameters MEET').initialMeetAdminPassword]",
|
"initialMeetAdminPassword": "[steps('parameters MEET').initialMeetAdminPassword]",
|
||||||
"initialMeetApiKey": "[steps('parameters MEET').initialMeetApiKey]",
|
"initialMeetApiKey": "[steps('parameters MEET').initialMeetApiKey]",
|
||||||
"instanceType": "[steps('parameters INSTANCE').instanceType]",
|
"instanceType": "[steps('parameters INSTANCE').instanceType]",
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ resource "google_secret_manager_secret" "openvidu_shared_info" {
|
||||||
for_each = toset([
|
for_each = toset([
|
||||||
"OPENVIDU_URL", "MEET_INITIAL_ADMIN_USER", "MEET_INITIAL_ADMIN_PASSWORD",
|
"OPENVIDU_URL", "MEET_INITIAL_ADMIN_USER", "MEET_INITIAL_ADMIN_PASSWORD",
|
||||||
"MEET_INITIAL_API_KEY", "LIVEKIT_URL", "LIVEKIT_API_KEY", "LIVEKIT_API_SECRET",
|
"MEET_INITIAL_API_KEY", "LIVEKIT_URL", "LIVEKIT_API_KEY", "LIVEKIT_API_SECRET",
|
||||||
"DASHBOARD_URL", "GRAFANA_URL", "MINIO_URL", "DOMAIN_NAME", "LIVEKIT_TURN_DOMAIN_NAME",
|
"DASHBOARD_URL", "GRAFANA_URL", "MINIO_URL", "DOMAIN_NAME",
|
||||||
"OPENVIDU_PRO_LICENSE", "OPENVIDU_RTC_ENGINE", "REDIS_PASSWORD", "MONGO_ADMIN_USERNAME",
|
"OPENVIDU_PRO_LICENSE", "OPENVIDU_RTC_ENGINE", "REDIS_PASSWORD", "MONGO_ADMIN_USERNAME",
|
||||||
"MONGO_ADMIN_PASSWORD", "MONGO_REPLICA_SET_KEY", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY",
|
"MONGO_ADMIN_PASSWORD", "MONGO_REPLICA_SET_KEY", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY",
|
||||||
"DASHBOARD_ADMIN_USERNAME", "DASHBOARD_ADMIN_PASSWORD", "GRAFANA_ADMIN_USERNAME",
|
"DASHBOARD_ADMIN_USERNAME", "DASHBOARD_ADMIN_PASSWORD", "GRAFANA_ADMIN_USERNAME",
|
||||||
|
|
@ -117,9 +117,6 @@ resource "google_compute_instance" "openvidu_server" {
|
||||||
ownPublicCertificate = var.ownPublicCertificate
|
ownPublicCertificate = var.ownPublicCertificate
|
||||||
ownPrivateCertificate = var.ownPrivateCertificate
|
ownPrivateCertificate = var.ownPrivateCertificate
|
||||||
additionalInstallFlags = var.additionalInstallFlags
|
additionalInstallFlags = var.additionalInstallFlags
|
||||||
turnDomainName = var.turnDomainName
|
|
||||||
turnOwnPublicCertificate = var.turnOwnPublicCertificate
|
|
||||||
turnOwnPrivateCertificate = var.turnOwnPrivateCertificate
|
|
||||||
bucketName = local.isEmpty ? google_storage_bucket.bucket[0].name : var.bucketName
|
bucketName = local.isEmpty ? google_storage_bucket.bucket[0].name : var.bucketName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,7 +143,7 @@ locals {
|
||||||
#!/bin/bash -x
|
#!/bin/bash -x
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
OPENVIDU_VERSION=3.5.0
|
OPENVIDU_VERSION=main
|
||||||
DOMAIN=
|
DOMAIN=
|
||||||
YQ_VERSION=v4.44.5
|
YQ_VERSION=v4.44.5
|
||||||
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
echo "DPkg::Lock::Timeout \"-1\";" > /etc/apt/apt.conf.d/99timeout
|
||||||
|
|
@ -178,7 +175,6 @@ if [[ "${var.domainName}" == "" ]]; then
|
||||||
EXTERNAL_IP=$(get_meta "instance/network-interfaces/0/access-configs/0/external-ip")
|
EXTERNAL_IP=$(get_meta "instance/network-interfaces/0/access-configs/0/external-ip")
|
||||||
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)
|
||||||
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
||||||
TURN_DOMAIN_NAME_SSLIP_IO=turn-$RANDOM_DOMAIN_STRING-$(echo $EXTERNAL_IP | tr '.' '-').sslip.io
|
|
||||||
else
|
else
|
||||||
DOMAIN="${var.domainName}"
|
DOMAIN="${var.domainName}"
|
||||||
fi
|
fi
|
||||||
|
|
@ -254,19 +250,6 @@ if [[ "${var.additionalInstallFlags}" != "" ]]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Turn with TLS
|
|
||||||
if [[ "$TURN_DOMAIN_NAME_SSLIP_IO" != "" ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "$TURN_DOMAIN_NAME_SSLIP_IO")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
elif [[ "${var.turnDomainName}" != '' ]]; then
|
|
||||||
LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${var.turnDomainName}")
|
|
||||||
COMMON_ARGS+=(
|
|
||||||
"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Certificate arguments
|
# Certificate arguments
|
||||||
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
||||||
CERT_ARGS=(
|
CERT_ARGS=(
|
||||||
|
|
@ -285,17 +268,6 @@ else
|
||||||
"--owncert-public-key=$OWN_CERT_CRT"
|
"--owncert-public-key=$OWN_CERT_CRT"
|
||||||
"--owncert-private-key=$OWN_CERT_KEY"
|
"--owncert-private-key=$OWN_CERT_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Turn with TLS and own certificate
|
|
||||||
if [[ "${var.turnDomainName}" != '' ]]; then
|
|
||||||
# Use base64 encoded certificates directly
|
|
||||||
OWN_CERT_CRT_TURN=${var.turnOwnPublicCertificate}
|
|
||||||
OWN_CERT_KEY_TURN=${var.turnOwnPrivateCertificate}
|
|
||||||
CERT_ARGS+=(
|
|
||||||
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
||||||
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Final command
|
# Final command
|
||||||
|
|
@ -394,12 +366,6 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
||||||
export LIVEKIT_TURN_DOMAIN_NAME=$(gcloud secrets versions access latest --secret=LIVEKIT_TURN_DOMAIN_NAME)
|
|
||||||
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
||||||
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "$${CONFIG_DIR}/openvidu.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the rest of the values
|
# Get the rest of the values
|
||||||
export REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
export REDIS_PASSWORD=$(gcloud secrets versions access latest --secret=REDIS_PASSWORD)
|
||||||
export OPENVIDU_PRO_LICENSE=$(gcloud secrets versions access latest --secret=OPENVIDU_PRO_LICENSE)
|
export OPENVIDU_PRO_LICENSE=$(gcloud secrets versions access latest --secret=OPENVIDU_PRO_LICENSE)
|
||||||
|
|
@ -476,7 +442,6 @@ REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "$${CON
|
||||||
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "$${CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "$${CONFIG_DIR}/openvidu.env")"
|
||||||
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "$${CONFIG_DIR}/openvidu.env")"
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "$${CONFIG_DIR}/openvidu.env")"
|
||||||
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "$${CONFIG_DIR}/openvidu.env")"
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "$${CONFIG_DIR}/openvidu.env")"
|
||||||
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "$${CONFIG_DIR}/openvidu.env")"
|
|
||||||
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "$${CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "$${CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "$${CONFIG_DIR}/openvidu.env")"
|
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "$${CONFIG_DIR}/openvidu.env")"
|
||||||
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "$${CONFIG_DIR}/openvidu.env")"
|
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "$${CONFIG_DIR}/openvidu.env")"
|
||||||
|
|
@ -500,7 +465,6 @@ echo -n "$REDIS_PASSWORD" | gcloud secrets versions add REDIS_PASSWORD --data-fi
|
||||||
echo -n "$OPENVIDU_PRO_LICENSE" | gcloud secrets versions add OPENVIDU_PRO_LICENSE --data-file=-
|
echo -n "$OPENVIDU_PRO_LICENSE" | gcloud secrets versions add OPENVIDU_PRO_LICENSE --data-file=-
|
||||||
echo -n "$OPENVIDU_RTC_ENGINE" | gcloud secrets versions add OPENVIDU_RTC_ENGINE --data-file=-
|
echo -n "$OPENVIDU_RTC_ENGINE" | gcloud secrets versions add OPENVIDU_RTC_ENGINE --data-file=-
|
||||||
echo -n "$DOMAIN_NAME" | gcloud secrets versions add DOMAIN_NAME --data-file=-
|
echo -n "$DOMAIN_NAME" | gcloud secrets versions add DOMAIN_NAME --data-file=-
|
||||||
echo -n "$LIVEKIT_TURN_DOMAIN_NAME" | gcloud secrets versions add LIVEKIT_TURN_DOMAIN_NAME --data-file=-
|
|
||||||
echo -n "$MONGO_ADMIN_USERNAME" | gcloud secrets versions add MONGO_ADMIN_USERNAME --data-file=-
|
echo -n "$MONGO_ADMIN_USERNAME" | gcloud secrets versions add MONGO_ADMIN_USERNAME --data-file=-
|
||||||
echo -n "$MONGO_ADMIN_PASSWORD" | gcloud secrets versions add MONGO_ADMIN_PASSWORD --data-file=-
|
echo -n "$MONGO_ADMIN_PASSWORD" | gcloud secrets versions add MONGO_ADMIN_PASSWORD --data-file=-
|
||||||
echo -n "$MONGO_REPLICA_SET_KEY" | gcloud secrets versions add MONGO_REPLICA_SET_KEY --data-file=-
|
echo -n "$MONGO_REPLICA_SET_KEY" | gcloud secrets versions add MONGO_REPLICA_SET_KEY --data-file=-
|
||||||
|
|
|
||||||
|
|
@ -122,21 +122,3 @@ variable "additionalInstallFlags" {
|
||||||
error_message = "Must be a comma-separated list of flags (for example, --flag=value, --bool-flag)."
|
error_message = "Must be a comma-separated list of flags (for example, --flag=value, --bool-flag)."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "turnDomainName" {
|
|
||||||
description = "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls"
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "turnOwnPublicCertificate" {
|
|
||||||
description = "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "turnOwnPrivateCertificate" {
|
|
||||||
description = "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set -eu
|
set -eu
|
||||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
||||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
||||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.5.0}"
|
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||||
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
export INSTALLER_IMAGE="${INSTALLER_IMAGE:-docker.io/openvidu/openvidu-installer:${OPENVIDU_VERSION}}"
|
||||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
||||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
||||||
|
|
@ -19,7 +19,7 @@ export OPENVIDU_MEET_SERVER_IMAGE="${OPENVIDU_MEET_SERVER_IMAGE:-docker.io/openv
|
||||||
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing:${OPENVIDU_VERSION}}"
|
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-cloud:${OPENVIDU_VERSION}}"
|
||||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${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 LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ set -eu
|
||||||
export INSTALL_PREFIX="${INSTALL_PREFIX:-/opt/openvidu}"
|
export INSTALL_PREFIX="${INSTALL_PREFIX:-/opt/openvidu}"
|
||||||
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
export DOCKER_VERSION="${DOCKER_VERSION:-29.0.2}"
|
||||||
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
export DOCKER_COMPOSE_VERSION="${DOCKER_COMPOSE_VERSION:-v2.40.3}"
|
||||||
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-3.5.0}"
|
export OPENVIDU_VERSION="${OPENVIDU_VERSION:-main}"
|
||||||
export UPDATER_IMAGE="${UPDATER_IMAGE:-docker.io/openvidu/openvidu-updater:${OPENVIDU_VERSION}}"
|
export UPDATER_IMAGE="${UPDATER_IMAGE:-docker.io/openvidu/openvidu-updater:${OPENVIDU_VERSION}}"
|
||||||
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
export MINIO_SERVER_IMAGE="${MINIO_SERVER_IMAGE:-docker.io/openvidu/minio:2025.9.7-debian-12-r3}"
|
||||||
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
export MINIO_CLIENT_IMAGE="${MINIO_CLIENT_IMAGE:-docker.io/minio/mc:RELEASE.2025-08-13T08-35-41Z}"
|
||||||
|
|
@ -19,7 +19,7 @@ export OPENVIDU_MEET_SERVER_IMAGE="${OPENVIDU_MEET_SERVER_IMAGE:-docker.io/openv
|
||||||
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_PRO_IMAGE="${OPENVIDU_DASHBOARD_PRO_IMAGE:-docker.io/openvidu/openvidu-pro-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
export OPENVIDU_DASHBOARD_IMAGE="${OPENVIDU_DASHBOARD_IMAGE:-docker.io/openvidu/openvidu-dashboard:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
export OPENVIDU_V2COMPATIBILITY_IMAGE="${OPENVIDU_V2COMPATIBILITY_IMAGE:-docker.io/openvidu/openvidu-v2compatibility:${OPENVIDU_VERSION}}"
|
||||||
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing:${OPENVIDU_VERSION}}"
|
export OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE="${OPENVIDU_AGENT_SPEECH_PROCESSING_IMAGE:-docker.io/openvidu/agent-speech-processing-cloud:${OPENVIDU_VERSION}}"
|
||||||
export LIVEKIT_INGRESS_SERVER_IMAGE="${LIVEKIT_INGRESS_SERVER_IMAGE:-docker.io/openvidu/ingress:${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 LIVEKIT_EGRESS_SERVER_IMAGE="${LIVEKIT_EGRESS_SERVER_IMAGE:-docker.io/openvidu/egress:${OPENVIDU_VERSION}}"
|
||||||
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
export PROMETHEUS_IMAGE="${PROMETHEUS_IMAGE:-docker.io/prom/prometheus:v3.7.1}"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue