UNPKG

aethercall

Version:

A scalable WebRTC video calling API built with Node.js and OpenVidu

185 lines (161 loc) 6.64 kB
/** * OpenVidu REST API Client * Pure HTTP calls to OpenVidu server for session management */ const https = require('https'); const http = require('http'); class OpenViduAPI { constructor(openviduUrl, openviduSecret) { this.openviduUrl = openviduUrl; this.openviduSecret = openviduSecret; this.baseHeaders = { 'Authorization': `Basic ${Buffer.from(`OPENVIDUAPP:${openviduSecret}`).toString('base64')}`, 'Content-Type': 'application/json' }; } /** * Create a new OpenVidu session * @param {Object} sessionOptions - Session configuration * @returns {Promise<Object>} Session details */ async createSession(sessionOptions = {}) { const sessionData = { mediaMode: sessionOptions.mediaMode || 'ROUTED', recordingMode: sessionOptions.recordingMode || 'MANUAL', customSessionId: sessionOptions.customSessionId || null, defaultRecordingProperties: sessionOptions.defaultRecordingProperties || {}, ...sessionOptions }; return this._makeRequest('POST', '/openvidu/api/sessions', sessionData); } /** * Get session information * @param {string} sessionId - Session ID * @returns {Promise<Object>} Session details */ async getSession(sessionId) { return this._makeRequest('GET', `/openvidu/api/sessions/${sessionId}`); } /** * Generate connection token for a session * @param {string} sessionId - Session ID * @param {Object} connectionOptions - Connection configuration * @returns {Promise<Object>} Connection token and details */ async createConnection(sessionId, connectionOptions = {}) { const connectionData = { type: connectionOptions.type || 'WEBRTC', role: connectionOptions.role || 'PUBLISHER', data: connectionOptions.data || '', record: connectionOptions.record || true, kurentoOptions: connectionOptions.kurentoOptions || {}, ...connectionOptions }; return this._makeRequest('POST', `/openvidu/api/sessions/${sessionId}/connection`, connectionData); } /** * Start recording a session * @param {string} sessionId - Session ID * @param {Object} recordingOptions - Recording configuration * @returns {Promise<Object>} Recording details */ async startRecording(sessionId, recordingOptions = {}) { const recordingData = { session: sessionId, name: recordingOptions.name || `recording-${Date.now()}`, outputMode: recordingOptions.outputMode || 'COMPOSED', recordingLayout: recordingOptions.recordingLayout || 'BEST_FIT', hasAudio: recordingOptions.hasAudio !== false, hasVideo: recordingOptions.hasVideo !== false, ...recordingOptions }; return this._makeRequest('POST', '/openvidu/api/recordings/start', recordingData); } /** * Stop recording a session * @param {string} recordingId - Recording ID * @returns {Promise<Object>} Recording details */ async stopRecording(recordingId) { return this._makeRequest('POST', `/openvidu/api/recordings/stop/${recordingId}`); } /** * Get recording information * @param {string} recordingId - Recording ID * @returns {Promise<Object>} Recording details */ async getRecording(recordingId) { return this._makeRequest('GET', `/openvidu/api/recordings/${recordingId}`); } /** * Delete a recording * @param {string} recordingId - Recording ID * @returns {Promise<Object>} Deletion confirmation */ async deleteRecording(recordingId) { return this._makeRequest('DELETE', `/openvidu/api/recordings/${recordingId}`); } /** * Close a session * @param {string} sessionId - Session ID * @returns {Promise<Object>} Closure confirmation */ async closeSession(sessionId) { return this._makeRequest('DELETE', `/openvidu/api/sessions/${sessionId}`); } /** * Get all active sessions * @returns {Promise<Object>} List of active sessions */ async getActiveSessions() { return this._makeRequest('GET', '/openvidu/api/sessions'); } /** * Private method to make HTTP requests to OpenVidu * @param {string} method - HTTP method * @param {string} path - API endpoint path * @param {Object} data - Request body data * @returns {Promise<Object>} Response data */ async _makeRequest(method, path, data = null) { return new Promise((resolve, reject) => { const url = new URL(this.openviduUrl + path); const options = { hostname: url.hostname, port: url.port, path: url.pathname + url.search, method: method, headers: this.baseHeaders, // Allow self-signed certificates in development rejectUnauthorized: false }; const httpModule = url.protocol === 'https:' ? https : http; const req = httpModule.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => { responseData += chunk; }); res.on('end', () => { try { const parsedData = responseData ? JSON.parse(responseData) : {}; if (res.statusCode >= 200 && res.statusCode < 300) { resolve(parsedData); } else { reject(new Error(`OpenVidu API error: ${res.statusCode} - ${parsedData.message || responseData}`)); } } catch (error) { reject(new Error(`Failed to parse OpenVidu response: ${error.message}`)); } }); }); req.on('error', (error) => { reject(new Error(`OpenVidu request failed: ${error.message}`)); }); if (data && (method === 'POST' || method === 'PUT' || method === 'PATCH')) { req.write(JSON.stringify(data)); } req.end(); }); } } module.exports = OpenViduAPI;