'use strict'; /** * ============================================== * MiroTalk SFU - Configuration File * ============================================== * * This file contains all configurable settings for the MiroTalk SFU application. * Environment variables can override most settings (see each section for details). * * Structure: * 1. Core System Configuration * 2. Server Settings * 3. Media Handling * 4. Security & Authentication * 5. API Configuration * 6. Third-Party Integrations * 7. UI/UX Customization * 8. Feature Flags * 9. Mediasoup (WebRTC) Settings */ const dotenv = require('dotenv').config(); const packageJson = require('../../package.json'); const os = require('os'); const fs = require('fs'); const splitChar = ','; // ============================================== // 1. Environment Detection & System Configuration // ============================================== const PLATFORM = os.platform(); const IS_DOCKER = fs.existsSync('/.dockerenv'); const ENVIRONMENT = process.env.NODE_ENV || 'development'; const ANNOUNCED_IP = process.env.SFU_ANNOUNCED_IP || ''; const LISTEN_IP = process.env.SFU_LISTEN_IP || '0.0.0.0'; const IPv4 = getIPv4(); // ============================================== // 2. WebRTC Port Configuration // ============================================== const RTC_MIN_PORT = parseInt(process.env.SFU_MIN_PORT) || 40000; const RTC_MAX_PORT = parseInt(process.env.SFU_MAX_PORT) || 40100; const NUM_CPUS = os.cpus().length; const NUM_WORKERS = Math.min(process.env.SFU_NUM_WORKERS || NUM_CPUS, NUM_CPUS); // ============================================== // 3. FFmpeg Path Configuration // ============================================== const RTMP_FFMPEG_PATH = process.env.RTMP_FFMPEG_PATH || getFFmpegPath(PLATFORM); // ============================================== // Main Configuration Export // ============================================== module.exports = { // ============================================== // 1. Core System Configuration // ============================================== system: { /** * System Information * ------------------ * - Hardware/OS details collected automatically * - Used for diagnostics and optimization */ info: { environment: ENVIRONMENT, os: { type: os.type(), release: os.release(), arch: os.arch(), }, cpu: { cores: NUM_CPUS, model: os.cpus()[0].model, }, memory: { total: (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB', }, isDocker: IS_DOCKER, }, /** * Console Configuration * --------------------- * - timeZone: IANA timezone (e.g., 'Europe/Rome') * - debug: Enable debug logging in non-production * - colors: Colorized console output * - json: Log output in JSON format * - json_pretty: Pretty-print JSON logs */ console: { timeZone: 'UTC', debug: ENVIRONMENT !== 'production', json: process.env.LOGS_JSON === 'true', json_pretty: process.env.LOGS_JSON_PRETTY === 'true', colors: process.env.LOGS_JSON === 'true' ? false : true, }, /** * External Services Configuration * ------------------------------- * - ip: Services to detect public IP address */ services: { ip: ['http://api.ipify.org', 'http://ipinfo.io/ip', 'http://ifconfig.me/ip'], }, }, // ============================================== // 2. Server Configuration // ============================================== server: { /** * Host Configuration * ------------------ * - hostUrl: Public URL (e.g., 'https://yourdomain.com') * - listen: IP and port to bind to */ hostUrl: process.env.SERVER_HOST_URL || 'https://localhost:3010', listen: { ip: process.env.SERVER_LISTEN_IP || '0.0.0.0', port: process.env.SERVER_LISTEN_PORT || 3010, }, /** * Security Settings * ----------------- * - trustProxy: Trust X-Forwarded-* headers * - ssl: SSL certificate paths * - cors: Cross-origin resource sharing */ trustProxy: process.env.TRUST_PROXY === 'true', ssl: { cert: process.env.SERVER_SSL_CERT || '../ssl/cert.pem', key: process.env.SERVER_SSL_KEY || '../ssl/key.pem', }, cors: { origin: process.env.CORS_ORIGIN || '*', methods: ['GET', 'POST'], }, }, // ============================================== // 3. Media Handling Configuration // ============================================== media: { /** * Recording Configuration * ======================= * Server side recording functionality. * * Core Settings: * ------------------------ * - enabled : Enable recording functionality * - uploadToS3 : Upload recording to AWS S3 bucket [true/false] * - endpoint : Leave empty ('') to store recordings locally OR * - Set to a valid URL (e.g., 'http://localhost:8080/') to: * - Push recordings to a remote server * - Store in cloud storage services * - Send to processing pipelines * - dir : Storage directory for recordings * - maxFileSize : Maximum recording size (1GB default) * * Docker Note: * ------------ * - When running in Docker, ensure the recording directory exists and is properly mounted: * 1. Create the directory (e.g., 'app/rec') * 2. Configure as volume in docker-compose.yml * 3. Set appropriate permissions * 4. Restart container after changes */ recording: { enabled: process.env.RECORDING_ENABLED === 'true', uploadToS3: process.env.RECORDING_UPLOAD_TO_S3 === 'true', endpoint: process.env.RECORDING_ENDPOINT || '', dir: 'rec', maxFileSize: 1 * 1024 * 1024 * 1024, // 1GB }, /** * RTMP Configuration * ================= * Configures Real-Time Messaging Protocol (RTMP) for audio/video/data streaming. * * Core Settings * ------------ * - enabled : Enable/disable RTMP streaming (default: false) * - fromFile : Enable local file streaming (default: true) * - fromUrl : Enable URL streaming (default: true) * - fromStream : Enable live stream input (default: true) * - maxStreams : Maximum simultaneous streams (default: 1) * - useNodeMediaServer : Use NodeMediaServer instead of nginx-rtmp (default: true) * - server : RTMP server URL (default: 'rtmp://localhost:1935') * - appName : Application name (default: 'live') * - streamKey : Optional authentication key (auto-generated UUID if empty) * - secret : Must match NodeMediaServer's config.js (default: 'mirotalkRtmpSecret') * - apiSecret : WebRTC→RTMP API secret (default: 'mirotalkRtmpApiSecret') * - expirationHours : Stream URL expiry in hours (default: 4) * - dir : Video storage directory (default: 'app/rtmp') * - ffmpegPath : FFmpeg binary path (auto-detected) * - platform : Current OS platform (auto-detected) * * Server Management * ---------------- * NodeMediaServer (mirotalk/nms:latest): * - Start: npm run nms-start * - Stop: npm run nms-stop * - Logs: npm run nms-logs * * NGINX-RTMP (mirotalk/rtmp:latest): * - Start: npm run rtmp-start * - Stop: npm run rtmp-stop * - Logs: npm run rtmp-logs * * Implementation Notes: * -------------------- * 1. For NodeMediaServer: * - Mandatory values: appName (falls back to 'live'), streamKey (auto-generated) * - URL format: rtmp://host:port/appName/streamKey?sign=expiration-token * * 2. Default Behavior: * - If server URL is empty, uses localhost:1935 * - If no streamKey provided, generates UUIDv4 * - When useNodeMediaServer=true, generates signed URLs with expiration * * Requirements: * ------------- * - RTMP server must be running * - Port 1935 must be accessible * - FFmpeg must be installed * * Documentation: * -------------- * - https://docs.mirotalk.com/mirotalk-sfu/rtmp/ */ rtmp: { enabled: process.env.RTMP_ENABLED === 'true', fromFile: process.env.RTMP_FROM_FILE !== 'false', fromUrl: process.env.RTMP_FROM_URL !== 'false', fromStream: process.env.RTMP_FROM_STREAM !== 'false', maxStreams: parseInt(process.env.RTMP_MAX_STREAMS) || 1, useNodeMediaServer: process.env.RTMP_USE_NODE_MEDIA_SERVER !== 'false', server: process.env.RTMP_SERVER || 'rtmp://localhost:1935', appName: process.env.RTMP_APP_NAME || 'live', streamKey: process.env.RTMP_STREAM_KEY || '', secret: process.env.RTMP_SECRET || 'mirotalkRtmpSecret', apiSecret: process.env.RTMP_API_SECRET || 'mirotalkRtmpApiSecret', expirationHours: parseInt(process.env.RTMP_EXPIRATION_HOURS) || 4, dir: 'rtmp', ffmpegPath: RTMP_FFMPEG_PATH, platform: PLATFORM, }, }, // ============================================== // 4. Security & Authentication // ============================================== security: { /** * IP Whitelisting * ------------------------ * - enabled: Restrict access to specified IPs * - allowedIPs: Array of permitted IP addresses */ middleware: { IpWhitelist: { enabled: process.env.IP_WHITELIST_ENABLED === 'true', allowedIPs: process.env.IP_WHITELIST_ALLOWED ? process.env.IP_WHITELIST_ALLOWED.split(splitChar) .map((ip) => ip.trim()) .filter((ip) => ip !== '') : ['127.0.0.1', '::1'], }, }, /** * JWT Configuration * ------------------------ * - key: Secret for JWT signing * - exp: Token expiration time */ jwt: { key: process.env.JWT_SECRET || 'mirotalksfu_jwt_secret', exp: process.env.JWT_EXPIRATION || '1h', }, /** * OpenID Connect (OIDC) Authentication Configuration * ================================================= * Configures authentication using OpenID Connect (OIDC), allowing integration with * identity providers like Auth0, Okta, Keycloak, etc. * * Structure: * - enabled : Master switch for OIDC authentication * - baseURLDynamic : Whether to dynamically resolve base URL * allow_rooms_creation_for_auth_users : Allow all authenticated users via OIDC to create their own rooms * - peer_name : Controls which user attributes to enforce/request * - config : Core OIDC provider settings * * Core Settings: * - issuerBaseURL : Provider's discovery endpoint (e.g., https://your-tenant.auth0.com) * - baseURL : Your application's base URL * - clientID : Client identifier issued by provider * - clientSecret : Client secret issued by provider * - secret : Application session secret * - authRequired : Whether all routes require authentication * - auth0Logout : Whether to use provider's logout endpoint * - authorizationParams: OAuth/OIDC flow parameters including: * - response_type : OAuth response type ('code' for Authorization Code Flow) * - scope : Requested claims (openid, profile, email) * - routes : Endpoint path configuration for: * - callback : OAuth callback handler path * - login : Custom login path (false to disable) * - logout : Custom logout path * */ oidc: { enabled: process.env.OIDC_ENABLED === 'true', baseURLDynamic: false, // Set true if your app has dynamic base URLs // ================================================================================================== allow_rooms_creation_for_auth_users: process.env.OIDC_ALLOW_ROOMS_CREATION_FOR_AUTH_USERS !== 'false', // ================================================================================================== // User identity requirements peer_name: { force: process.env.OIDC_USERNAME_FORCE !== 'false', // Forces the username to match the OIDC email or name. If true, the user won't be able to change their name when joining a room email: process.env.OIDC_USERNAME_AS_EMAIL !== 'false', // Uses the OIDC email as the username. name: process.env.OIDC_USERNAME_AS_NAME === 'true', // Uses the OIDC name as the username }, // Provider configuration config: { // Required provider settings issuerBaseURL: process.env.OIDC_ISSUER || 'https://server.example.com', baseURL: process.env.OIDC_BASE_URL || `http://localhost:${process.env.PORT || 3010}`, clientID: process.env.OIDC_CLIENT_ID || 'clientID', clientSecret: process.env.OIDC_CLIENT_SECRET || 'clientSecret', // Session configuration secret: process.env.OIDC_SECRET || 'mirotalksfu-oidc-secret', authRequired: process.env.OIDC_AUTH_REQUIRED === 'true', // Whether all routes require authentication auth0Logout: process.env.OIDC_AUTH_LOGOUT !== 'false', // Use provider's logout endpoint // OAuth/OIDC flow parameters authorizationParams: { response_type: 'code', // Use authorization code flow scope: 'openid profile email', // Request standard claims }, // Route customization routes: { callback: '/auth/callback', // OAuth callback path login: false, // Disable default login route logout: '/logout', // Custom logout path }, }, }, /** * Host Protection Configuration * ============================ * Controls access to host-level functionality and room management. * * Authentication Methods: * ---------------------- * - Local users (defined in config or via HOST_USERS env variable) * - API/database validation (users_from_db=true) * * Core Settings: * -------------- * - protected : Enable/disable host protection globally * - user_auth : Require user authentication for host access * - users_from_db : Fetch users from API/database instead of local config * * API Integration: * --------------- * - users_api_secret_key : Secret key for API authentication * - users_api_endpoint : Endpoint to validate user credentials * - users_api_room_allowed : Endpoint to check if user can access a room * - users_api_rooms_allowed : Endpoint to get allowed rooms for a user * - api_room_exists : Endpoint to verify if a room exists * * Local User Configuration: * ------------------------ * - users: Array of authorized users (used if users_from_db=false) * - Define via HOST_USERS env variable: * HOST_USERS=username:password:displayname:room1,room2|username2:password2:displayname2:* * (Each user separated by '|', fields by ':', allowed_rooms comma-separated or '*' for all) * - If HOST_USERS is not set, falls back to DEFAULT_USERNAME, DEFAULT_PASSWORD, etc. * - Fields: * - username : Login username * - password : Login password * - displayname : User's display name * - allowed_rooms : List of rooms user can access ('*' for all) * * Presenter Management: * -------------------- * - list : Array of usernames who can be presenters * - join_first : First joiner becomes presenter (default: true) * * Documentation: * ------------- * https://docs.mirotalk.com/mirotalk-sfu/host-protection/ */ host: { protected: process.env.HOST_PROTECTED === 'true', user_auth: process.env.HOST_USER_AUTH === 'true', users_from_db: process.env.HOST_USERS_FROM_DB === 'true', users_api_secret_key: process.env.USERS_API_SECRET || 'mirotalkweb_default_secret', users_api_endpoint: process.env.USERS_API_ENDPOINT || 'http://localhost:9000/api/v1/user/isAuth', // 'https://webrtc.mirotalk.com/api/v1/user/isAuth' users_api_room_allowed: process.env.USERS_ROOM_ALLOWED_ENDPOINT || 'http://localhost:9000/api/v1/user/isRoomAllowed', // 'https://webrtc.mirotalk.com/api/v1/user/isRoomAllowed' users_api_rooms_allowed: process.env.USERS_ROOMS_ALLOWED_ENDPOINT || 'http://localhost:9000/api/v1/user/roomsAllowed', // 'https://webrtc.mirotalk.com/api/v1/user/roomsAllowed' api_room_exists: process.env.ROOM_EXISTS_ENDPOINT || 'http://localhost:9000/api/v1/room/exists', // 'https://webrtc.mirotalk.com//api/v1/room/exists' users: process.env.HOST_USERS ? process.env.HOST_USERS.split('|').map((userStr) => { const [username, password, displayname, allowedRoomsStr] = userStr.split(':'); return { username: username || '', password: password || '', displayname: displayname || '', allowed_rooms: allowedRoomsStr ? allowedRoomsStr .split(',') .map((room) => room.trim()) .filter((room) => room !== '') : ['*'], }; }) : [ { username: 'username', password: 'password', displayname: 'username displayname', allowed_rooms: ['*'], }, { username: 'username2', password: 'password2', displayname: 'username2 displayname', allowed_rooms: ['room1', 'room2'], }, { username: 'username3', password: 'password3', displayname: 'username3 displayname', }, //... ], presenters: { list: process.env.PRESENTERS ? process.env.PRESENTERS.split(splitChar) .map((presenter) => presenter.trim()) .filter((presenter) => presenter !== '') : ['Miroslav Pejic', 'miroslav.pejic.85@gmail.com'], join_first: process.env.PRESENTER_JOIN_FIRST !== 'false', }, }, }, // ============================================== // 5. API Configuration // ============================================== /** * API Security & Endpoint Configuration * ==================================== * Controls access to the SFU's API endpoints and integration settings. * * Security Settings: * ----------------- * - keySecret : Authentication secret for API requests * (Always override default in production) * * Endpoint Control: * ----------------- * - stats : Enable/disable system statistics endpoint [true/false] (default: true) * - meetings : Enable/disable meetings list endpoint [true/false] (default: true) * - meeting : Enable/disable single meeting operations [true/false] (default: true) * - join : Enable/disable meeting join endpoint [true/false] (default: true) * - token : Enable/disable token generation endpoint [true/false] (default: false) * - slack : Enable/disable Slack webhook integration [true/false] (default: true) * - mattermost : Enable/disable Mattermost webhook integration [true/false] (default: true) * * API Documentation: * ------------------ * - Complete API reference: https://docs.mirotalk.com/mirotalk-sfu/api/ * - Webhook setup: See integration guides for Slack/Mattermost */ api: { keySecret: process.env.API_KEY_SECRET || 'mirotalksfu_default_secret', allowed: { stats: process.env.API_ALLOW_STATS !== 'false', meetings: process.env.API_ALLOW_MEETINGS === 'true', meeting: process.env.API_ALLOW_MEETING !== 'false', join: process.env.API_ALLOW_JOIN !== 'false', token: process.env.API_ALLOW_TOKEN === 'true', slack: process.env.API_ALLOW_SLACK !== 'false', mattermost: process.env.API_ALLOW_MATTERMOST !== 'false', }, }, // ============================================== // 6. Third-Party Integrations // ============================================== integrations: { /** * ChatGPT Integration Configuration * ================================ * OpenAI API integration for AI-powered chat functionality * * Setup Instructions: * ------------------ * 1. Go to https://platform.openai.com/ * 2. Create your OpenAI account * 3. Generate your API key at https://platform.openai.com/account/api-keys * * Core Settings: * ------------- * - enabled : Enable/disable ChatGPT integration [true/false] (default: false) * - basePath : OpenAI API endpoint (default: 'https://api.openai.com/v1/') * - apiKey : OpenAI API secret key (ALWAYS store in .env) * - model : GPT model version (default: 'gpt-3.5-turbo') * * Advanced Settings: * ----------------- * - max_tokens: Maximum response length (default: 1024 tokens) * - temperature: Creativity control (0=strict, 1=creative) (default: 0) * * Usage Example: * ------------- * 1. Supported Models: * - gpt-3.5-turbo (recommended) * - gpt-4 * - gpt-4-turbo * - ... * * 2. Temperature Guide: * - 0.0: Factual responses * - 0.7: Balanced * - 1.0: Maximum creativity */ chatGPT: { enabled: process.env.CHATGPT_ENABLED === 'true', basePath: process.env.CHATGPT_BASE_PATH || 'https://api.openai.com/v1/', apiKey: process.env.CHATGPT_API_KEY || '', model: process.env.CHATGPT_MODEL || 'gpt-3.5-turbo', max_tokens: parseInt(process.env.CHATGPT_MAX_TOKENS) || 1024, temperature: parseInt(process.env.CHATGPT_TEMPERATURE) || 0.7, }, /** * DeepDeek Integration Configuration * ================================ * DeepDeek API integration for AI-powered chat functionality * * Setup Instructions: * ------------------ * 1. Go to https://deepseek.com/ * 2. Create your DeepDeek account * 3. Generate your API key at https://deepseek.com/account/api-keys * * Core Settings: * ------------- * - enabled : Enable/disable DeepDeek integration [true/false] (default: false) * - basePath : DeepDeek API endpoint (default: 'https://api.deepseek.com/v1/') * - apiKey : DeepDeek API secret key (ALWAYS store in .env) * - model : DeepDeek model version (default: 'deepdeek-chat') * * Advanced Settings: * ----------------- * - max_tokens: Maximum response length (default: 1024 tokens) * - temperature: Creativity control (0=strict, 1=creative) (default: 0) * * Usage Example: * ------------- * 1. Supported Models: * - deepseek-chat (recommended) * - deepseek-coder * - deepseek-math * - deepseek-llm * - ... * * 2. Temperature Guide: * - 0.0: Factual responses * - 0.7: Balanced * - 1.0: Maximum creativity * */ deepSeek: { enabled: process.env.DEEP_SEEK_ENABLED === 'true', basePath: process.env.DEEP_SEEK_BASE_PATH || 'https://api.deepseek.com/v1/', apiKey: process.env.DEEP_SEEK_API_KEY || '', model: process.env.DEEP_SEEK_MODEL || 'deepseek-chat', max_tokens: parseInt(process.env.DEEP_SEEK_MAX_TOKENS) || 1024, temperature: parseInt(process.env.DEEP_SEEK_TEMPERATURE) || 0.7, }, /** * HeyGen Video AI Configuration * ============================ * AI-powered avatar streaming integration * * Setup Instructions: * ------------------ * 1. Go to https://app.heygen.com * 2. Create your HeyGen account * 3. Generate your API key at https://app.heygen.com/settings?nav=API * * Core Settings: * ------------- * - enabled : Enable/disable Video AI [true/false] (default: false) * - basePath : HeyGen API endpoint (default: 'https://api.heygen.com') * - apiKey : From HeyGen account (ALWAYS store in .env) * * AI Behavior: * ----------- * - systemLimit: Personality/behavior instructions for the AI avatar * (default: Streaming avatar instructions for MiroTalk SFU) */ videoAI: { enabled: process.env.VIDEOAI_ENABLED === 'true', basePath: 'https://api.heygen.com', apiKey: process.env.VIDEOAI_API_KEY || '', systemLimit: process.env.VIDEOAI_SYSTEM_LIMIT || 'You are a streaming avatar from MiroTalk SFU...', }, /** * Email Notification Configuration * =============================== * SMTP settings for system alerts and notifications * * Core Settings: * ------------- * - alert : Enable/disable email alerts [true/false] (default: false) * - notify : Enable/disable room email notifications [true/false] (default: false) * - host : SMTP server address (default: 'smtp.gmail.com') * - port : SMTP port (default: 587 for TLS) * - username : SMTP auth username * - password : SMTP auth password (store ONLY in .env) * - from : Sender email address (default: same as username) * - sendTo : Recipient email for alerts * * Common Providers: * ---------------- * Gmail: * - host: smtp.gmail.com * - port: 587 * * Office365: * - host: smtp.office365.com * - port: 587 * * SendGrid: * - host: smtp.sendgrid.net * - port: 587 */ email: { alert: process.env.EMAIL_ALERTS_ENABLED === 'true', notify: process.env.EMAIL_NOTIFICATIONS === 'true', host: process.env.EMAIL_HOST || 'smtp.gmail.com', port: parseInt(process.env.EMAIL_PORT) || 587, username: process.env.EMAIL_USERNAME || 'your_username', password: process.env.EMAIL_PASSWORD || 'your_password', from: process.env.EMAIL_FROM || process.env.EMAIL_USERNAME, sendTo: process.env.EMAIL_SEND_TO || 'sfu.mirotalk@gmail.com', }, /** * Slack Integration Configuration * ============================== * Settings for Slack slash commands and interactivity * * Setup Instructions: * ------------------ * 1. Create a Slack app at https://api.slack.com/apps * 2. Under "Basic Information" → "App Credentials": * - Copy the Signing Secret * 3. Enable "Interactivity & Shortcuts" and "Slash Commands" * 4. Set Request URL to: https://your-domain.com/slack/commands * * Core Settings: * ------------- * - enabled : Enable/disable Slack integration [true/false] (default: false) * - signingSecret : From Slack app credentials (store ONLY in .env) * */ slack: { enabled: process.env.SLACK_ENABLED === 'true', signingSecret: process.env.SLACK_SIGNING_SECRET || '', }, /** * Mattermost Integration Configuration * =================================== * Settings for Mattermost slash commands and bot integration * * Setup Instructions: * ------------------ * 1. Go to Mattermost System Console → Integrations → Bot Accounts * 2. Create a new bot account and copy: * - Server URL (e.g., 'https://chat.yourdomain.com') * - Access Token * 3. For slash commands: * - Navigate to Integrations → Slash Commands * - Set Command: '/sfu' * - Set Request URL: 'https://your-sfu-server.com/mattermost/commands' * * Core Settings: * ------------- * - enabled : Enable/disable integration [true/false] (default: false) * - serverUrl : Mattermost server URL (include protocol) * - token : Bot account access token (most secure option) * - OR * - username : Legacy auth username (less secure) * - password : Legacy auth password (deprecated) * * Command Configuration: * --------------------- * - commands : Slash command definitions: * - name : Command trigger (e.g., '/sfu') * - message : Default response template * */ mattermost: { enabled: process.env.MATTERMOST_ENABLED === 'true', serverUrl: process.env.MATTERMOST_SERVER_URL || '', username: process.env.MATTERMOST_USERNAME || '', password: process.env.MATTERMOST_PASSWORD || '', token: process.env.MATTERMOST_TOKEN || '', commands: [ { name: process.env.MATTERMOST_COMMAND_NAME || '/sfu', message: process.env.MATTERMOST_DEFAULT_MESSAGE || 'Here is your meeting room:', }, ], texts: [ { name: process.env.MATTERMOST_COMMAND_NAME || '/sfu', message: process.env.MATTERMOST_DEFAULT_MESSAGE || 'Here is your meeting room:', }, ], }, /** * Discord Integration Configuration * ================================ * Settings for Discord bot and slash commands integration * * Setup Instructions: * ------------------ * 1. Create a Discord application at https://discord.com/developers/applications * 2. Navigate to "Bot" section and: * - Click "Add Bot" * - Copy the bot token (DISCORD_TOKEN) * 3. Under "OAuth2 → URL Generator": * - Select "bot" and "applications.commands" scopes * - Select required permissions (see below) * 4. Invite bot to your server using generated URL * * Core Settings: * ------------- * - enabled : Enable/disable Discord bot [true/false] (default: false) * - token : Bot token from Discord Developer Portal (store in .env) * * Command Configuration: * --------------------- * - commands : Slash command definitions: * - name : Command trigger (e.g., '/sfu') * - message : Response template * - baseUrl : Meeting room base URL * */ discord: { enabled: process.env.DISCORD_ENABLED === 'true', token: process.env.DISCORD_TOKEN || '', commands: [ { name: process.env.DISCORD_COMMAND_NAME || '/sfu', message: process.env.DISCORD_DEFAULT_MESSAGE || 'Here is your SFU meeting room:', baseUrl: process.env.DISCORD_BASE_URL || 'https://sfu.mirotalk.com/join/', }, ], }, /** * Ngrok Tunnel Configuration * ========================= * Secure tunneling for local development and testing * * Setup Instructions: * ------------------ * 1. Sign up at https://dashboard.ngrok.com/signup * 2. Get your auth token from: * https://dashboard.ngrok.com/get-started/your-authtoken * 3. For reserved domains/subdomains: * - Upgrade to paid plan if needed * - Reserve at https://dashboard.ngrok.com/cloud-edge/domains * * Core Settings: * ------------- * - enabled : Enable/disable Ngrok tunneling [true/false] (default: false) * - authToken : Your Ngrok authentication token (from dashboard) */ ngrok: { enabled: process.env.NGROK_ENABLED === 'true', authToken: process.env.NGROK_AUTH_TOKEN || '', }, /** * Sentry Error Tracking Configuration * ================================== * Real-time error monitoring and performance tracking * * Setup Instructions: * ------------------ * 1. Create a project at https://sentry.io/signup/ * 2. Get your DSN from: * Project Settings → Client Keys (DSN) * 3. Configure alert rules and integrations as needed * * Core Settings: * ------------- * enabled : Enable/disable Sentry [true/false] (default: false) * logLevels : Array of log levels to capture (default: ['error']) * DSN : Data Source Name (from Sentry dashboard) * tracesSampleRate : Percentage of transactions to capture (0.0-1.0) * * Performance Tuning: * ------------------ * - Production : 0.1-0.2 (10-20% of transactions) * - Staging : 0.5-1.0 * - Development : 0.0 (disable performance tracking) * */ sentry: { enabled: process.env.SENTRY_ENABLED === 'true', logLevels: process.env.SENTRY_LOG_LEVELS ? process.env.SENTRY_LOG_LEVELS.split(splitChar).map((level) => level.trim()) : ['error'], DSN: process.env.SENTRY_DSN || '', tracesSampleRate: Math.min(Math.max(parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE) || 0.5, 0), 1), }, /** * Webhook Configuration Settings * ============================= * Controls the webhook notification system for sending event data to external services. * * Core Settings: * --------------------- * - enabled: Turns webhook notifications on/off * - url: The endpoint URL where webhook payloads will be sent in JSON format * * Implementation Guide: * -------------------- * - For complete implementation examples, refer to: * - Project demo: /mirotalksfu/webhook/ folder */ webhook: { enabled: process.env.WEBHOOK_ENABLED === 'true', url: process.env.WEBHOOK_URL || 'https://your-site.com/webhook-endpoint', }, /** * IP Geolocation Service Configuration * =================================== * Enables lookup of geographical information based on IP addresses using the GeoJS.io API. * * Core Settings: * --------------------- * - enabled: Enable/disable the IP lookup functionality [true/false] default false * * Service Details: * -------------- * - Uses GeoJS.io free API service (https://www.geojs.io/) * - Returns JSON data containing: * - Country, region, city * - Latitude/longitude * - Timezone and organization * - Rate limits: 60 requests/minute (free tier) */ IPLookup: { enabled: process.env.IP_LOOKUP_ENABLED === 'true', getEndpoint(ip) { return `https://get.geojs.io/v1/ip/geo/${ip}.json`; }, }, /** * AWS S3 Storage Configuration * =========================== * Enables cloud file storage using Amazon Simple Storage Service (S3). * * Core Settings: * -------------- * - enabled: Enable/disable AWS S3 integration [true/false] * * Service Setup: * ------------- * 1. Create an S3 Bucket: * - Sign in to AWS Management Console * - Navigate to S3 service * - Click "Create bucket" * - Choose unique name (e.g., 'mirotalk') * - Select region (must match AWS_REGION in config) * - Enable desired settings (versioning, logging, etc.) * * 2. Get Security Credentials: * - Create IAM user with programmatic access * - Attach 'AmazonS3FullAccess' policy (or custom minimal policy) * - Save Access Key ID and Secret Access Key * * 3. Configure CORS (for direct uploads): * [ * { * "AllowedHeaders": ["*"], * "AllowedMethods": ["PUT", "POST"], * "AllowedOrigins": ["*"], * "ExposeHeaders": [] * } * ] * * Technical Details: * ----------------- * - Default region: us-east-2 (Ohio) * - Direct upload uses presigned URLs (expire after 1 hour by default) * - Recommended permissions for direct upload: * - s3:PutObject * - s3:GetObject * - s3:DeleteObject */ aws: { enabled: process.env.AWS_S3_ENABLED === 'true', accessKeyId: process.env.AWS_ACCESS_KEY_ID || 'your-access-key-id', secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || 'your-secret-access-key', region: process.env.AWS_REGION || 'us-east-2', bucket: process.env.AWS_S3_BUCKET || 'mirotalk', }, }, // ============================================== // 7. UI/UX Customization // ============================================== ui: { /** * Branding & Appearance Configuration * ----------------------------------- * Controls all aspects of the application's visual identity, content, and metadata. * Supports environment variable overrides for deployment-specific customization. * * ============================================== * LICENSE REQUIRED: * ============================================== * - https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 */ rooms: { /** * Room Display Settings * --------------------- * - showActive: Show active rooms in the UI (default: false) * https://sfu.mirotalk.com/activeRooms */ showActive: process.env.SHOW_ACTIVE_ROOMS === 'true', }, brand: { /** * Application Branding * -------------------- * Core application identity and user interface text elements. * * Note: * Set BRAND_HTML_INJECTION to 'false' to disable HTML injection. * This allows for static branding in the public/views folder, without dynamic content injection. */ htmlInjection: process.env.BRAND_HTML_INJECTION !== 'false', app: { language: process.env.UI_LANGUAGE || 'en', name: process.env.APP_NAME || 'MiroTalk SFU', title: process.env.APP_TITLE || '