Updated openvidu-ionic
This commit is contained in:
parent
757fec766e
commit
981b85ce61
9
openvidu-ionic/Caddyfile
Normal file
9
openvidu-ionic/Caddyfile
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
{$IP_ADDRESS}:5001 {
|
||||
reverse_proxy http://localhost:5000
|
||||
@ws {
|
||||
header Connection *Upgrade*
|
||||
header Upgrade websocket
|
||||
}
|
||||
reverse_proxy @ws http://localhost:7880
|
||||
}
|
||||
@ -5,34 +5,16 @@ const config: CapacitorConfig = {
|
||||
appId: 'io.ionic.starter',
|
||||
appName: 'openvidu-ionic',
|
||||
webDir: 'www',
|
||||
server: {
|
||||
androidScheme: 'http',
|
||||
iosScheme: 'http'
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
if (environment.externalIp) {
|
||||
config.server = config.server || {};
|
||||
config.server.hostname = 'localhost';
|
||||
config.server.cleartext = true;
|
||||
// config.includePlugins = config.includePlugins || [];
|
||||
// '@jcesarmobile/ssl-skip' plugin is needed to allow serve the app over HTTPS
|
||||
// with a self-signed certificate without installing the certificate in the device
|
||||
// config.includePlugins.push('@jcesarmobile/ssl-skip', 'cordova-plugin-android-permissions');
|
||||
|
||||
// Android configuration
|
||||
config.android = config.android || {};
|
||||
config.android.allowMixedContent = true;
|
||||
config.android.includePlugins = config.android.includePlugins || [];
|
||||
config.android.includePlugins.push('@jcesarmobile/ssl-skip', 'cordova-plugin-android-permissions');
|
||||
|
||||
|
||||
// iOS configuration
|
||||
// config.ios = config.ios || {};
|
||||
// config.ios.includePlugins = config.ios.includePlugins || [];
|
||||
// config.ios.includePlugins.push('@jcesarmobile/ssl-skip');
|
||||
|
||||
}
|
||||
|
||||
export default config;
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
platforms:
|
||||
android:
|
||||
versionName: 1.0.0
|
||||
manifest:
|
||||
- file: AndroidManifest.xml
|
||||
target: manifest
|
||||
merge: |
|
||||
<manifest>
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
</manifest>
|
||||
- file: AndroidManifest.xml
|
||||
target: manifest/application/activity
|
||||
attrs:
|
||||
android:exported: true
|
||||
android:networkSecurityConfig: "@xml/network_security_config"
|
||||
res:
|
||||
- path: xml
|
||||
file: network_security_config.xml
|
||||
text: |
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config>
|
||||
<trust-anchors>
|
||||
<certificates src="system"/>
|
||||
<certificates src="user"/>
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
ios:
|
||||
version: 1.0.0
|
||||
@ -1,52 +0,0 @@
|
||||
events {
|
||||
worker_connections 512;
|
||||
}
|
||||
http {
|
||||
upstream openvidu-deployment {
|
||||
server host.docker.internal:4443;
|
||||
}
|
||||
upstream server-application {
|
||||
server host.docker.internal:5000;
|
||||
}
|
||||
upstream client-application {
|
||||
server host.docker.internal:8100;
|
||||
}
|
||||
server {
|
||||
listen 443 ssl;
|
||||
ssl_certificate /etc/nginx/certs/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/key.pem;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_headers_hash_bucket_size 512;
|
||||
proxy_redirect off;
|
||||
|
||||
# Websockets
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# OpenVidu deployment API
|
||||
location /openvidu/api {
|
||||
proxy_pass http://openvidu-deployment;
|
||||
}
|
||||
|
||||
# OpenVidu WebSocket
|
||||
location ~ /openvidu$ {
|
||||
proxy_pass http://openvidu-deployment;
|
||||
}
|
||||
|
||||
# Server application requests
|
||||
location /api/ {
|
||||
proxy_pass http://server-application;
|
||||
}
|
||||
|
||||
# Client application requests
|
||||
location / {
|
||||
proxy_pass http://client-application;
|
||||
}
|
||||
}
|
||||
}
|
||||
1092
openvidu-ionic/package-lock.json
generated
1092
openvidu-ionic/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,14 +4,13 @@
|
||||
"author": "Ionic Framework",
|
||||
"homepage": "https://ionicframework.com/",
|
||||
"scripts": {
|
||||
"start": "ionic serve",
|
||||
"build": "ng build",
|
||||
"start": "npx ionic serve",
|
||||
"build": "npx ionic build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"android": "./scripts/mobile_run.sh androidd",
|
||||
"android": "./scripts/mobile_run.sh android",
|
||||
"ios": "./scripts/mobile_run.sh ios",
|
||||
"sync": "npx ionic capacitor sync",
|
||||
"build:full": "npm run trapeze && npx ionic capacitor sync",
|
||||
"build:android": "npm run build:full && npx ionic capacitor build android --no-open && cd android && ./gradlew assembleDebug && ./gradlew assembleRelease",
|
||||
"build:android": "npx ionic capacitor build android --no-open && cd android && ./gradlew assembleDebug && ./gradlew assembleRelease",
|
||||
"copy:android": "cp ./android/app/build/outputs/apk/debug/app-debug.apk /opt/openvidu/android/openvidu-ionic.apk"
|
||||
},
|
||||
"private": true,
|
||||
|
||||
@ -17,18 +17,7 @@ case "$os_name" in
|
||||
"Linux")
|
||||
# Commands for Linux
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
|
||||
|
||||
|
||||
if [ -z "$LOCAL_IP" ]; then
|
||||
echo "Cannot get your local IP address."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sed -i "s/\(externalIp:\s*'\)[^']*/\1$LOCAL_IP/" src/environments/environment.ts
|
||||
echo "Your local ip is $LOCAL_IP"
|
||||
echo "Setting up your movile environment for developing OpenVidu..."
|
||||
npx ionic cap run $PLATFORM -l --external --disable-host-check --public-host=$LOCAL_IP --ssl
|
||||
|
||||
sed -i "s/\(externalIp:\s*'\)[^']*/\1$LOCAL_IP/" $ENV_FILE
|
||||
;;
|
||||
"Darwin")
|
||||
# Commands for macOS
|
||||
@ -39,21 +28,37 @@ case "$os_name" in
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$LOCAL_IP" ]; then
|
||||
echo "Cannot get your local IP address."
|
||||
exit 1
|
||||
fi
|
||||
echo "Your local ip is $LOCAL_IP"
|
||||
echo "Setting up your movile environment for developing OpenVidu..."
|
||||
sed -i '' "s/externalIp: .*/externalIp: '$LOCAL_IP'/g" $ENV_FILE
|
||||
npx ionic capacitor run ios -c development
|
||||
;;
|
||||
*)
|
||||
# Unsupported/Unknown OS
|
||||
echo "Unsupported operating system: $os_name"
|
||||
exit 1
|
||||
# Windows OS
|
||||
echo "Recognized $os_name as operating system. The ip must be set manually."
|
||||
read -p "Insert your local ip " ip_address
|
||||
LOCAL_IP=$ip_address
|
||||
# Requesting the user to set the ip manually and wait for the user to press enter
|
||||
echo "Please set your local ip in $ENV_FILE"
|
||||
echo "Example:"
|
||||
echo ""
|
||||
echo "export const environment = {"
|
||||
echo " production: false,"
|
||||
echo " externalIp: 'XXX.XXX.X.XX' <--- SET YOUR IP HERE"
|
||||
echo "};"
|
||||
read -p "Press Enter to continue..."
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$LOCAL_IP" ]; then
|
||||
echo "Cannot get your local IP address."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(docker ps -q -f ancestor=caddy)" ]; then
|
||||
echo "Container caddy is running."
|
||||
else
|
||||
echo "Container caddy is not running. Launching it..."
|
||||
docker run -d --network=host -v $PWD/Caddyfile:/etc/caddy/Caddyfile -e IP_ADDRESS=$LOCAL_IP caddy
|
||||
fi
|
||||
echo "Your local ip is $LOCAL_IP"
|
||||
echo "Setting up your mobile environment for developing OpenVidu..."
|
||||
npm run build
|
||||
npx ionic cap run $PLATFORM -c development --external --disable-host-check --public-host=$LOCAL_IP --ssl
|
||||
|
||||
@ -6,7 +6,6 @@ import {
|
||||
RemoteTrackPublication,
|
||||
Room,
|
||||
RoomEvent,
|
||||
TrackPublishOptions,
|
||||
} from 'livekit-client';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { AlertController, Platform } from '@ionic/angular';
|
||||
@ -21,24 +20,20 @@ import { environment } from 'src/environments/environment';
|
||||
})
|
||||
export class HomePage {
|
||||
APPLICATION_SERVER_URL = 'http://localhost:5000/';
|
||||
WS_LIVEKIT_URL = 'ws://localhost:7880/';
|
||||
private IS_DEVICE_DEV_MODE = false;
|
||||
|
||||
// OpenVidu objects
|
||||
room: Room | undefined = undefined;
|
||||
|
||||
localPublication: LocalTrackPublication | undefined = undefined;
|
||||
remotePublications: RemoteTrackPublication[] = [];
|
||||
|
||||
// Join form
|
||||
myRoomName!: string;
|
||||
myParticipantName!: string;
|
||||
|
||||
cameraIcon = 'videocam';
|
||||
microphoneIcon = 'mic';
|
||||
|
||||
private cameras: MediaDeviceInfo[] = [];
|
||||
private cameraSelected!: MediaDeviceInfo;
|
||||
private isFrontCamera: boolean = false;
|
||||
|
||||
ANDROID_PERMISSIONS = [
|
||||
this.androidPermissions.PERMISSION.CAMERA,
|
||||
this.androidPermissions.PERMISSION.RECORD_AUDIO,
|
||||
@ -52,19 +47,6 @@ export class HomePage {
|
||||
private androidPermissions: AndroidPermissions
|
||||
) {
|
||||
this.generateParticipantInfo();
|
||||
|
||||
// WARNING!! To make the mobile development easier, this code allows
|
||||
// using your local IP address for communicating with the backend.
|
||||
// For production uses, the server should be accessible from the Internet
|
||||
if (this.platform.is('hybrid')) {
|
||||
if (environment.externalIp) {
|
||||
console.warn('Your local IP address: ', environment.externalIp);
|
||||
this.APPLICATION_SERVER_URL = this.APPLICATION_SERVER_URL.replace(
|
||||
'localhost',
|
||||
environment.externalIp
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('window:beforeunload')
|
||||
@ -73,6 +55,23 @@ export class HomePage {
|
||||
this.leaveRoom();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
/**
|
||||
* WARNING!! To make the mobile development easier, this code allows
|
||||
* using your local IP address for communicating with the backend.
|
||||
* For production uses, the server should be accessible from the Internet
|
||||
* and the code below should be removed.
|
||||
*/
|
||||
if (this.platform.is('hybrid') && environment.externalIp) {
|
||||
this.IS_DEVICE_DEV_MODE = true;
|
||||
this.prepareForDeviceDevelopment();
|
||||
}
|
||||
|
||||
console.log('IS_DEVICE_DEV_MODE: ', this.IS_DEVICE_DEV_MODE);
|
||||
console.log('APPLICATION_SERVER_URL: ', this.APPLICATION_SERVER_URL);
|
||||
console.log('WS_LIVEKIT_URL: ', this.WS_LIVEKIT_URL);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
// On component destroyed leave room
|
||||
this.leaveRoom();
|
||||
@ -114,28 +113,20 @@ export class HomePage {
|
||||
this.myParticipantName
|
||||
);
|
||||
|
||||
let livekitUrl = this.getLivekitUrlFromMetadata(token);
|
||||
|
||||
if (environment.externalIp) {
|
||||
// WARNING!! To make the mobile development easier, this code allows
|
||||
// using your local IP address for communicating with the backend.
|
||||
// For production uses, the server should be accessible from the Internet
|
||||
livekitUrl = livekitUrl.replace('localhost', environment.externalIp);
|
||||
if (!this.IS_DEVICE_DEV_MODE) {
|
||||
// Get the Livekit WebSocket URL from the token metadata if not in device dev mode
|
||||
this.WS_LIVEKIT_URL = this.getLivekitUrlFromMetadata(token);
|
||||
}
|
||||
|
||||
// First param is the LiveKit server URL. Second param is the access token
|
||||
|
||||
await this.room.connect(livekitUrl, token);
|
||||
await this.room.connect(this.WS_LIVEKIT_URL, token);
|
||||
|
||||
// --- 5) Requesting and Checking Android Permissions
|
||||
if (this.platform.is('hybrid') && this.platform.is('android')) {
|
||||
await this.checkAndroidPermissions();
|
||||
}
|
||||
|
||||
const publishOptions: TrackPublishOptions = {
|
||||
stream: 'test',
|
||||
};
|
||||
|
||||
const [audioPublication, videoPublication] = await Promise.all([
|
||||
this.room.localParticipant.setMicrophoneEnabled(true),
|
||||
this.room.localParticipant.setCameraEnabled(true),
|
||||
@ -143,7 +134,10 @@ export class HomePage {
|
||||
|
||||
// Set the main video in the page to display our webcam and store our localPublication
|
||||
this.localPublication = videoPublication;
|
||||
this.refreshVideos();
|
||||
videoPublication?.track?.on('elementAttached', (track) => {
|
||||
this.refreshVideos();
|
||||
});
|
||||
|
||||
await this.initDevices();
|
||||
} catch (error: any) {
|
||||
console.log(
|
||||
@ -154,11 +148,11 @@ export class HomePage {
|
||||
}
|
||||
}
|
||||
|
||||
leaveRoom() {
|
||||
async leaveRoom() {
|
||||
// --- 7) Leave the room by calling 'disconnect' method over the Session object ---
|
||||
|
||||
if (this.room) {
|
||||
this.room.disconnect();
|
||||
await this.room.disconnect();
|
||||
}
|
||||
|
||||
// Empty all properties...
|
||||
@ -166,6 +160,8 @@ export class HomePage {
|
||||
this.localPublication = undefined;
|
||||
this.room = undefined;
|
||||
this.generateParticipantInfo();
|
||||
this.cameraIcon = 'videocam';
|
||||
this.microphoneIcon = 'mic';
|
||||
}
|
||||
|
||||
// Others methods...
|
||||
@ -208,11 +204,6 @@ export class HomePage {
|
||||
async toggleCamera() {
|
||||
if (this.room) {
|
||||
const enabled = !this.room.localParticipant.isCameraEnabled;
|
||||
// const options: VideoCaptureOptions = {};
|
||||
// const publishOptions: TrackPublishOptions = {
|
||||
// stream: 'test',
|
||||
// };
|
||||
|
||||
await this.room.localParticipant.setCameraEnabled(enabled);
|
||||
this.refreshVideos();
|
||||
this.cameraIcon = enabled ? 'videocam' : 'eye-off';
|
||||
@ -222,14 +213,7 @@ export class HomePage {
|
||||
async toggleMicrophone() {
|
||||
if (this.room) {
|
||||
const enabled = !this.room.localParticipant.isMicrophoneEnabled;
|
||||
const publishOptions: TrackPublishOptions = {
|
||||
stream: 'test',
|
||||
};
|
||||
await this.room.localParticipant.setMicrophoneEnabled(
|
||||
enabled,
|
||||
undefined,
|
||||
publishOptions
|
||||
);
|
||||
await this.room.localParticipant.setMicrophoneEnabled(enabled);
|
||||
this.microphoneIcon = enabled ? 'mic' : 'mic-off';
|
||||
}
|
||||
}
|
||||
@ -251,6 +235,10 @@ export class HomePage {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows to change the LiveKit websocket URL and the application server URL
|
||||
* from the application itself. This is useful for development purposes.
|
||||
*/
|
||||
async presentSettingsAlert() {
|
||||
const alert = await this.alertController.create({
|
||||
header: 'Application server',
|
||||
@ -262,6 +250,13 @@ export class HomePage {
|
||||
placeholder: 'URL',
|
||||
id: 'url-input',
|
||||
},
|
||||
{
|
||||
name: 'websocket',
|
||||
type: 'text',
|
||||
value: this.WS_LIVEKIT_URL,
|
||||
placeholder: 'WS URL',
|
||||
id: 'ws-input',
|
||||
},
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
@ -275,6 +270,7 @@ export class HomePage {
|
||||
id: 'ok-btn',
|
||||
handler: (data) => {
|
||||
this.APPLICATION_SERVER_URL = data.url;
|
||||
this.WS_LIVEKIT_URL = data.websocket;
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -284,17 +280,21 @@ export class HomePage {
|
||||
}
|
||||
|
||||
private refreshVideos() {
|
||||
// setTimeout(() => {
|
||||
// console.warn('track restarted: UPDATED DOM');
|
||||
// const refreshedElement = document.getElementById('refreshed-workaround');
|
||||
// if (refreshedElement) {
|
||||
// refreshedElement.remove();
|
||||
// } else {
|
||||
// const p = document.createElement('p');
|
||||
// p.id = 'refreshed-workaround';
|
||||
// document.getElementById('room')?.appendChild(p);
|
||||
// }
|
||||
// }, 200);
|
||||
if (this.platform.is('hybrid') && this.platform.is('android')) {
|
||||
// Workaround for Android devices
|
||||
setTimeout(() => {
|
||||
const refreshedElement = document.getElementById(
|
||||
'refreshed-workaround'
|
||||
);
|
||||
if (refreshedElement) {
|
||||
refreshedElement.remove();
|
||||
} else {
|
||||
const p = document.createElement('p');
|
||||
p.id = 'refreshed-workaround';
|
||||
document.getElementById('room')?.appendChild(p);
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
|
||||
private async checkAndroidPermissions(): Promise<void> {
|
||||
@ -353,6 +353,19 @@ export class HomePage {
|
||||
}
|
||||
}
|
||||
|
||||
private prepareForDeviceDevelopment() {
|
||||
/**
|
||||
* WARNING!! To make the mobile development easier, this code allows
|
||||
* using your local IP address for communicating with the backend.
|
||||
* For production uses, the server should be accessible from the Internet
|
||||
* and the code below should be removed.
|
||||
*/
|
||||
console.warn('Your local IP address: ', environment.externalIp);
|
||||
// Pointing to our proxy server through https/wss and our local IP address
|
||||
this.APPLICATION_SERVER_URL = `https://${environment.externalIp}:5001/`;
|
||||
this.WS_LIVEKIT_URL = `wss://${environment.externalIp}:5001/`;
|
||||
}
|
||||
|
||||
/**
|
||||
* --------------------------------------------
|
||||
* GETTING A TOKEN FROM YOUR APPLICATION SERVER
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user