aethercall
Version:
A scalable WebRTC video calling API built with Node.js and OpenVidu
185 lines (161 loc) • 6.64 kB
JavaScript
/**
* 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;