obs-websocket-js
Advanced tools
Comparing version 0.2.0 to 0.2.2
@@ -99,2 +99,3 @@ ## Classes | ||
* [.connect(address, [password])](#OBSWebSocket+connect) | ||
* [.disconnect()](#OBSWebSocket+disconnect) | ||
* [.getCurrentScene(callback)](#OBSWebSocket+getCurrentScene) | ||
@@ -158,5 +159,5 @@ * [.setCurrentScene(sceneName)](#OBSWebSocket+setCurrentScene) | ||
| Param | Type | | ||
| --- | --- | | ||
| sceneName | <code>string</code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| sceneName | <code>string</code> | Name of the currently active scene. | | ||
@@ -175,3 +176,3 @@ <a name="OBSWebSocket+onSceneListChanged"></a> | ||
| response.currentScene | <code>string</code> | Name of the currently active scene. | | ||
| response.scenes | <code>[Array.<OBSScene>](#OBSScene)</code> | | | ||
| response.scenes | <code>[Array.<OBSScene>](#OBSScene)</code> | List of all scenes in the current profile. | | ||
@@ -237,3 +238,3 @@ <a name="OBSWebSocket+onStreamStarting"></a> | ||
### obsWebSocket.onStreamStatus(response) | ||
Triggered once per second while streaming. Emits details about the stream status. | ||
Triggered once per second while streaming. Emits details about the stream status. NOTE: This is currently only emit when streaming, it is not emit when only recording. | ||
@@ -243,13 +244,14 @@ **Kind**: instance method of <code>[OBSWebSocket](#OBSWebSocket)</code> | ||
| Param | Type | | ||
| --- | --- | | ||
| response | <code>object</code> | | ||
| response.streaming | <code>bool</code> | | ||
| response.recording | <code>bool</code> | | ||
| response.bytesPerSecond | <code>int</code> | | ||
| response.strain | <code>int</code> | | ||
| response.totalStreamTime | <code>int</code> | | ||
| response.numberOfFrames | <code>int</code> | | ||
| response.numberOfDroppedFrames | <code>int</code> | | ||
| response.fps | <code>double</code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| response | <code>object</code> | | | ||
| response.streaming | <code>bool</code> | Indicates whether OBS is currently streaming. | | ||
| response.recording | <code>bool</code> | Indicates whether OBS is currently recording. | | ||
| data.previewOnly | <code>bool</code> | Always false. | | ||
| response.bytesPerSec | <code>int</code> | Current bitrate of the stream. | | ||
| response.strain | <code>int</code> | Percentage of dropped frames. | | ||
| response.totalStreamTime | <code>int</code> | Total uptime of the stream. | | ||
| response.numTotalFrames | <code>int</code> | Total number of frames since the start of stream. | | ||
| response.numDroppedFrames | <code>int</code> | Total number of dropped frames since the start of stream. | | ||
| response.fps | <code>double</code> | Current Frames per Second of the stream. | | ||
@@ -290,3 +292,3 @@ <a name="OBSWebSocket+onExit"></a> | ||
### obsWebSocket.authenticate([password]) | ||
Attempt to authenticate the OBSWebSocket connection. | ||
Attempt to authenticate the OBSWebSocket connection. Note that this method does not accept a callback. Bind all callbacks to [OBSWebSocket.onAuthenticationSuccess](OBSWebSocket.onAuthenticationSuccess) and [OBSWebSocket.onAuthenticationFailure](OBSWebSocket.onAuthenticationFailure). | ||
@@ -296,5 +298,5 @@ **Kind**: instance method of <code>[OBSWebSocket](#OBSWebSocket)</code> | ||
| Param | Type | | ||
| --- | --- | | ||
| [password] | <code>string</code> | | ||
| Param | Type | Default | Description | | ||
| --- | --- | --- | --- | | ||
| [password] | <code>string</code> | <code>"''"</code> | Defaults to empty. | | ||
@@ -304,3 +306,3 @@ <a name="OBSWebSocket+connect"></a> | ||
### obsWebSocket.connect(address, [password]) | ||
Initialize and authenticate the connection. | ||
Initialize and authenticate the WebSocket connection. | ||
@@ -310,7 +312,14 @@ **Kind**: instance method of <code>[OBSWebSocket](#OBSWebSocket)</code> | ||
| Param | Type | Default | | ||
| --- | --- | --- | | ||
| address | <code>string</code> | <code>"localhost"</code> | | ||
| [password] | <code>string</code> | | | ||
| Param | Type | Default | Description | | ||
| --- | --- | --- | --- | | ||
| address | <code>string</code> | <code>"localhost"</code> | IP Adddress to connect to, with or without port. | | ||
| [password] | <code>string</code> | <code>"''"</code> | Defaults to empty. | | ||
<a name="OBSWebSocket+disconnect"></a> | ||
### obsWebSocket.disconnect() | ||
Close and disconnect the WebSocket connection. | ||
**Kind**: instance method of <code>[OBSWebSocket](#OBSWebSocket)</code> | ||
**Category**: request | ||
<a name="OBSWebSocket+getCurrentScene"></a> | ||
@@ -363,3 +372,3 @@ | ||
| sourceName | <code>string</code> | Name of the source. | | ||
| visible | <code>bool</code> | Whether the source should be visible or not. | | ||
| visible | <code>bool</code> | Indicates whether the source should be visible or not. | | ||
@@ -380,2 +389,6 @@ <a name="OBSWebSocket+toggleStreaming"></a> | ||
**Category**: request | ||
**Todo** | ||
- [ ] Implement. | ||
<a name="OBSWebSocket+stopStreaming"></a> | ||
@@ -388,2 +401,6 @@ | ||
**Category**: request | ||
**Todo** | ||
- [ ] Implement. | ||
<a name="OBSWebSocket+startStopRecording"></a> | ||
@@ -403,2 +420,6 @@ | ||
**Category**: request | ||
**Todo** | ||
- [ ] Implement. | ||
<a name="OBSWebSocket+stopRecording"></a> | ||
@@ -411,2 +432,6 @@ | ||
**Category**: request | ||
**Todo** | ||
- [ ] Implement. | ||
<a name="OBSWebSocket+getStreamStatus"></a> | ||
@@ -456,5 +481,5 @@ | ||
| Param | Type | | ||
| --- | --- | | ||
| transitionName | <code>string</code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| transitionName | <code>string</code> | Name of the transition. | | ||
@@ -468,7 +493,8 @@ <a name="getVersionCb"></a> | ||
| Param | Type | | ||
| --- | --- | | ||
| err | <code>object</code> | | ||
| data | <code>object</code> | | ||
| data.obsVersion | <code>string</code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| err | <code>object</code> | Only populated if an error occurred during the request. | | ||
| data | <code>object</code> | | | ||
| data.obsWebSocketVersion | <code>string</code> | Current OBS WebSocket plugin version. | | ||
| data.version | <code>double</code> | Hardcoded for OBS Remote backwards compatibility. | | ||
@@ -482,9 +508,9 @@ <a name="getAuthRequiredCb"></a> | ||
| Param | Type | | ||
| --- | --- | | ||
| err | | | ||
| data | | | ||
| data.authRequired | <code>bool</code> | | ||
| [data.salt] | <code>string</code> | | ||
| [data.challenge] | <code>string</code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| err | <code>object</code> | Only populated if an error occurred during the request. | | ||
| data | <code>object</code> | | | ||
| data.authRequired | <code>bool</code> | Indicates whether authentication is required. | | ||
| [data.salt] | <code>string</code> | Authentication Salt. Only populated if authentication is required. | | ||
| [data.challenge] | <code>string</code> | Authentication Challenge. Only populated if authentication is required. | | ||
@@ -498,6 +524,6 @@ <a name="getCurrentSceneCb"></a> | ||
| Param | Type | | ||
| --- | --- | | ||
| err | | | ||
| data | <code>[OBSScene](#OBSScene)</code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| err | <code>object</code> | Only populated if an error occurred during the request. | | ||
| data | <code>[OBSScene](#OBSScene)</code> | Currently active scene. | | ||
@@ -513,4 +539,4 @@ <a name="getSceneListCb"></a> | ||
| --- | --- | --- | | ||
| err | | | | ||
| data | | | | ||
| err | <code>object</code> | Only populated if an error occurred during the request. | | ||
| data | <code>object</code> | | | ||
| data.currentScene | <code>string</code> | Name of the currently active scene. | | ||
@@ -528,13 +554,13 @@ | data.scenes | <code>[Array.<OBSScene>](#OBSScene)</code> | Array of [OBSScene](#OBSScene)s. | | ||
| --- | --- | --- | | ||
| err | | | | ||
| data | | | | ||
| data.streaming | <code>bool</code> | | | ||
| data.recording | <code>bool</code> | | | ||
| err | <code>object</code> | Only populated if an error occurred during the request. | | ||
| data | <code>object</code> | | | ||
| data.streaming | <code>bool</code> | Indicates whether OBS is currently streaming. | | ||
| data.recording | <code>bool</code> | Indicates whether OBS is currently recording. | | ||
| data.previewOnly | <code>bool</code> | Always false. | | ||
| [data.bytesPerSec] | <code>int</code> | | | ||
| [data.strain] | <code>double</code> | | | ||
| [data.totalStreamTime] | <code>int</code> | | | ||
| [data.numTotalFrames] | <code>int</code> | | | ||
| [data.numDroppedFrames] | <code>int</code> | | | ||
| [data.fps] | <code>double</code> | | | ||
| [data.bytesPerSec] | <code>int</code> | Current bitrate of the stream. | | ||
| [data.strain] | <code>double</code> | Percentage of dropped frames. | | ||
| [data.totalStreamTime] | <code>int</code> | Total uptime of the stream. | | ||
| [data.numTotalFrames] | <code>int</code> | Total number of frames since the start of stream. | | ||
| [data.numDroppedFrames] | <code>int</code> | Total number of dropped frames since the start of stream. | | ||
| [data.fps] | <code>double</code> | Current Frames per Second of the stream. | | ||
@@ -548,8 +574,8 @@ <a name="getTransitionListCb"></a> | ||
| Param | Type | | ||
| --- | --- | | ||
| err | | | ||
| data | | | ||
| data.currentTransition | <code>string</code> | | ||
| data.transitions | <code>Array.<string></code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| err | <code>object</code> | Only populated if an error occurred during the request. | | ||
| data | <code>object</code> | | | ||
| data.currentTransition | <code>string</code> | Name of the currently active transition. | | ||
| data.transitions | <code>Array.<string></code> | Array of available transitions by name. | | ||
@@ -563,7 +589,7 @@ <a name="getCurrentTransitionCb"></a> | ||
| Param | Type | | ||
| --- | --- | | ||
| err | | | ||
| data | | | ||
| data.name | <code>string</code> | | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| err | <code>object</code> | Only populated if an error occurred during the request. | | ||
| data | <code>object</code> | | | ||
| data.name | <code>string</code> | Name of the currently active transition. | | ||
@@ -1,10 +0,74 @@ | ||
(function(){ | ||
/* | ||
* OBS WebSocket Javascript API (obs-websocket-js) v0.1.1 | ||
* Author: Brendan Hagan (haganbmj) | ||
* Repo: git+https://github.com/haganbmj/obs-websocket-js.git | ||
*/ | ||
var OBSWebSocket = | ||
/******/ (function(modules) { // webpackBootstrap | ||
/******/ // The module cache | ||
/******/ var installedModules = {}; | ||
'use strict'; | ||
/******/ // The require function | ||
/******/ function __webpack_require__(moduleId) { | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) | ||
/******/ return installedModules[moduleId].exports; | ||
/******/ // Create a new module (and put it into the cache) | ||
/******/ var module = installedModules[moduleId] = { | ||
/******/ i: moduleId, | ||
/******/ l: false, | ||
/******/ exports: {} | ||
/******/ }; | ||
/******/ // Execute the module function | ||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | ||
/******/ // Flag the module as loaded | ||
/******/ module.l = true; | ||
/******/ // Return the exports of the module | ||
/******/ return module.exports; | ||
/******/ } | ||
/******/ // expose the modules object (__webpack_modules__) | ||
/******/ __webpack_require__.m = modules; | ||
/******/ // expose the module cache | ||
/******/ __webpack_require__.c = installedModules; | ||
/******/ // identity function for calling harmony imports with the correct context | ||
/******/ __webpack_require__.i = function(value) { return value; }; | ||
/******/ // define getter function for harmony exports | ||
/******/ __webpack_require__.d = function(exports, name, getter) { | ||
/******/ if(!__webpack_require__.o(exports, name)) { | ||
/******/ Object.defineProperty(exports, name, { | ||
/******/ configurable: false, | ||
/******/ enumerable: true, | ||
/******/ get: getter | ||
/******/ }); | ||
/******/ } | ||
/******/ }; | ||
/******/ // getDefaultExport function for compatibility with non-harmony modules | ||
/******/ __webpack_require__.n = function(module) { | ||
/******/ var getter = module && module.__esModule ? | ||
/******/ function getDefault() { return module['default']; } : | ||
/******/ function getModuleExports() { return module; }; | ||
/******/ __webpack_require__.d(getter, 'a', getter); | ||
/******/ return getter; | ||
/******/ }; | ||
/******/ // Object.prototype.hasOwnProperty.call | ||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; | ||
/******/ // __webpack_public_path__ | ||
/******/ __webpack_require__.p = ""; | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(__webpack_require__.s = 4); | ||
/******/ }) | ||
/************************************************************************/ | ||
/******/ ([ | ||
/* 0 */ | ||
/***/ (function(module, exports) { | ||
/** | ||
@@ -21,4 +85,3 @@ * @class OBSSource | ||
*/ | ||
(function() { | ||
function OBSSource(name, type, x, y, boundsX, boundsY, volume, visible) { | ||
module.exports = function(name, type, x, y, boundsX, boundsY, volume, visible) { | ||
this.name = (typeof name === 'undefined') ? '' : name; | ||
@@ -32,71 +95,22 @@ this.type = (typeof type === 'undefined') ? '' : type; | ||
this.visible = visible || false; | ||
} | ||
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { | ||
module.exports.OBSSource = OBSSource; | ||
} else { | ||
window.OBSSource = OBSSource; | ||
} | ||
})(); | ||
this.marshal = function(source) { | ||
return this(source.name, source.type, source.x, source.y, source.cx, source.cy, source.volume, source.render); | ||
}; | ||
}; | ||
function marshalOBSSource(source) { // jshint ignore:line | ||
return new OBSSource(source.name, source.type, source.x, source.y, source.cx, source.cy, source.volume, source.render); | ||
} | ||
/** | ||
* @class OBSScene | ||
* @param name {string} - Source name. | ||
* @param sources {Array.<OBSSource>} - Array of {@link OBSSource}s. | ||
*/ | ||
(function() { | ||
function OBSScene(name, sources) { | ||
this.name = (typeof name === 'undefined') ? '' : name; | ||
sources = (typeof sources === 'undefined') ? [] : sources; | ||
/***/ }), | ||
/* 1 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
var self = this; | ||
var OBSScene = __webpack_require__(2); | ||
var OBSSource = __webpack_require__(0); | ||
var WebSocket = __webpack_require__(3); | ||
if (sources.length > 0 && !(sources[0] instanceof OBSSource)) { | ||
this.sources = []; | ||
sources.forEach(function(source) { | ||
self.sources.push(marshalOBSSource(source)); | ||
}); | ||
} | ||
} | ||
var OBSWebSocket = function() { | ||
this.DEFAULT_PORT = 4444; | ||
this.CONSOLE_NAME = '[OBSWebSocket]'; | ||
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { | ||
module.exports.OBSScene = OBSScene; | ||
} else { | ||
window.OBSScene = OBSScene; | ||
} | ||
})(); | ||
function marshalOBSScene(scene) { // jshint ignore:line | ||
return new OBSScene(scene.name, scene.sources); | ||
} | ||
function isModule() { | ||
return typeof module !== 'undefined' && typeof module.exports !== 'undefined'; | ||
} | ||
var OBSSource = {}; | ||
var OBSScene = {}; | ||
if (isModule()) { | ||
OBSSource = module.exports.OBSSource; | ||
OBSScene = module.exports.OBSScene; | ||
} else { | ||
OBSSource = window.OBSSource; | ||
OBSScene = window.OBSScene; | ||
} | ||
/** | ||
* @class OBSWebSocket | ||
* @example | ||
* var ws = new OBSWebSocket(); | ||
* ws.connect('url', 'password'); | ||
*/ | ||
function OBSWebSocket() { | ||
OBSWebSocket.DEFAULT_PORT = 4444; | ||
OBSWebSocket.CONSOLE_NAME = '[OBSWebSocket]'; | ||
this._debug = false; | ||
this._connected = false; | ||
@@ -106,730 +120,203 @@ this._socket = undefined; | ||
this._responseCallbacks = {}; | ||
this._auth = { salt: '', challenge: '' }; | ||
} | ||
var WebSocket = {}; | ||
if (isModule()) { | ||
WebSocket = require('ws'); | ||
} else { | ||
WebSocket = window.WebSocket; | ||
} | ||
OBSWebSocket.prototype._generateMessageId = function() { | ||
this._requestCounter++; | ||
return this._requestCounter + ''; | ||
this._auth = { | ||
salt: '', | ||
challenge: '' | ||
}; | ||
}; | ||
OBSWebSocket.prototype._sendRequest = function(requestType, args, callback) { | ||
if (this._connected) { | ||
args = args || {}; | ||
callback = callback || function() {}; | ||
args['message-id'] = this._generateMessageId(); | ||
args['request-type'] = requestType; | ||
this._responseCallbacks[args['message-id']] = { | ||
'requestType': requestType, | ||
'callbackFunction': callback | ||
}; | ||
this._socket.send(JSON.stringify(args)); | ||
} else { | ||
console.warn(OBSWebSocket.CONSOLE_NAME, "Not connected."); | ||
var latestVersion = '0.3.2'; | ||
var version = { | ||
'0.3.2': { | ||
'core': { | ||
'params': { | ||
'messageId': 'message-id', | ||
'requestType': 'request-type' | ||
} | ||
}, | ||
'getVersion': { | ||
'name': 'GetVersion', | ||
'params': {}, | ||
'response': { | ||
'version': 'version', | ||
'websocketVersion': 'obs-websocket-version', | ||
'obsStudioVersion': 'obs-studio-version' | ||
} | ||
}, | ||
'getAuthenticationRequired': { | ||
'name': 'GetAuthRequired', | ||
'params': {}, | ||
'response': { | ||
'challenge': 'challenge', | ||
'salt': 'salt' | ||
} | ||
}, | ||
'authenticate': { | ||
'name': 'Authenticate', | ||
'params': {}, | ||
'response': {} | ||
}, | ||
'setCurrentScene': { | ||
'name': 'SetCurrentScene', | ||
'params': { | ||
'sceneName': 'scene-name' | ||
}, | ||
'response': {} | ||
}, | ||
'getCurrentScene': { | ||
'name': 'GetCurrentScene', | ||
'params': {}, | ||
'response': {} | ||
}, | ||
'getSceneList': { | ||
'name': 'GetSceneList', | ||
'params': {}, | ||
'response': {} | ||
}, | ||
'getStreamStatus': { | ||
'name': 'GetStreamingStatus', | ||
'params': {}, | ||
'response': {} | ||
}, | ||
'startStopStreaming': { | ||
'name': 'StartStopStreaming', | ||
'params': {}, | ||
'response': {} | ||
}, | ||
'startStopRecording': { | ||
'name': 'StartStopRecording', | ||
'params': {}, | ||
'response': {} | ||
}, | ||
'setCurrentTransition': { | ||
'name': 'SetCurrentTransition', | ||
'params': { | ||
'transitionName': 'transition-name' | ||
}, | ||
'response': {} | ||
}, | ||
'getCurrentTransition': { | ||
'name': 'GetCurrentTransition', | ||
'params': {}, | ||
'response': {} | ||
}, | ||
'getTransitionList': { | ||
'name': 'GetTransitionList', | ||
'params': {}, | ||
'response': {} | ||
} | ||
} | ||
}; | ||
OBSWebSocket.prototype._onMessage = function(msg) { | ||
var message = JSON.parse(msg.data); | ||
var err = null; | ||
function apiLookup(requestType, params, callback) { | ||
args = args || {}; | ||
callback = callback || function() {}; | ||
if (!message) | ||
return; | ||
var updateType = message['update-type']; | ||
var messageId = message['message-id']; | ||
if (message.status === 'error') { | ||
console.error(OBSWebSocket.CONSOLE_NAME, 'Error:', message.error); | ||
err = message.error; | ||
message = null; | ||
// Determine the API Version. | ||
var api = version[OBSWebSocket.apiVersion]; | ||
if (!api) { | ||
console.info('API Version was not recognized. Defaulting to latest (' + latestVersion + ') for all future requests.'); | ||
OBSWebSocket.apiVersion = latestVersion; | ||
api = version[latestVersion]; | ||
} | ||
if (updateType) { | ||
if (message) { | ||
this._buildEventCallback(updateType, message); | ||
} | ||
} else { | ||
var callback = this._responseCallbacks[messageId].callbackFunction; | ||
// Determine the Function. | ||
var func = api[requestType]; | ||
if (!func) { | ||
var err = { | ||
'error': 'Unsupported', | ||
'message': 'API Version ' + api.key + ' does not support ' + requestType + '.', | ||
'api': api.key, | ||
'requestType': requestType | ||
}; | ||
if (callback) { | ||
callback(err, message); | ||
} | ||
if (OBSWebSocket._debug) | ||
console.error(err.message); | ||
delete this._responseCallbacks[messageId]; | ||
callback(err, null); | ||
return; | ||
} | ||
}; | ||
OBSWebSocket.prototype._buildEventCallback = function(updateType, message) { | ||
var self = this; | ||
switch(updateType) { | ||
case 'SwitchScenes': | ||
this.onSceneSwitch(message['scene-name']); | ||
return; | ||
case 'ScenesChanged': | ||
this.getSceneList(function(sceneList) { | ||
self.onSceneListChanged(sceneList); | ||
}); | ||
return; | ||
case 'StreamStarting': | ||
this.onStreamStarting(); | ||
return; | ||
case 'StreamStarted': | ||
this.onStreamStarted(); | ||
return; | ||
case 'StreamStopping': | ||
this.onStreamStopping(); | ||
return; | ||
case 'StreamStopped': | ||
this.onStreamStopped(); | ||
return; | ||
case 'RecordingStarting': | ||
this.onRecordingStarting(); | ||
return; | ||
case 'RecordingStarted': | ||
this.onRecordingStarted(); | ||
return; | ||
case 'RecordingStopping': | ||
this.onRecordingStopping(); | ||
return; | ||
case 'RecordingStopped': | ||
this.onRecordingStopped(); | ||
return; | ||
case 'StreamStatus': | ||
message['bytesPerSecond'] = message['bytes-per-sec']; | ||
message['totalStreamTime'] = message['total-stream-time']; | ||
message['numberOfFrames'] = message['num-total-frames']; | ||
message['numberOfDroppedFrames'] = message['num-dropped-frames']; | ||
this.onStreamStatus(message); | ||
return; | ||
case 'Exiting': | ||
this.onExit(); | ||
return; | ||
default: | ||
console.warn(OBSWebSocket.CONSOLE_NAME, 'Unknown UpdateType:', updateType, message); | ||
// Populate the Request Params based on the available mapped API params. | ||
var args = {}; | ||
for (var key in func.params) { | ||
if (func.hasOwnProperty(key)) { | ||
args[key.value] = params[key]; | ||
} | ||
} | ||
}; | ||
if (isModule()) { | ||
module.exports.OBSWebSocket = OBSWebSocket; | ||
} else { | ||
window.OBSWebSocket = OBSWebSocket; | ||
} | ||
// Append core generated Request Params. | ||
var messageId = args[api.core.params.messageId || 'message-id'] = OBSWebSocket._generateMessageId(); | ||
var req = args[api.core.params.requestType || 'request-type'] = func.name; | ||
OBSWebSocket.prototype._webCryptoHash = function(pass, callback) { | ||
var self = this; | ||
// Bind the response callback for future use. | ||
OBSWebSocket._responseCallbacks[messageId] = { | ||
'requestType': req, | ||
'api': api.key, | ||
'callbackFunction': callback, | ||
'timestamp': Date.now() | ||
}; | ||
var utf8Pass = _encodeStringAsUTF8(pass); | ||
var utf8Salt = _encodeStringAsUTF8(this._auth.salt); | ||
var ab1 = _stringToArrayBuffer(utf8Pass + utf8Salt); | ||
crypto.subtle.digest('SHA-256', ab1) | ||
.then(function(authHash) { | ||
var utf8AuthHash = _encodeStringAsUTF8(_arrayBufferToBase64(authHash)); | ||
var utf8Challenge = _encodeStringAsUTF8(self._auth.challenge); | ||
var ab2 = _stringToArrayBuffer(utf8AuthHash + utf8Challenge); | ||
crypto.subtle.digest('SHA-256', ab2) | ||
.then(function(authResp) { | ||
var authRespB64 = _arrayBufferToBase64(authResp); | ||
callback(authRespB64); | ||
}); | ||
}); | ||
}; | ||
OBSWebSocket.prototype._cryptoJSHash = function(pass, callback) { | ||
var utf8Pass = _encodeStringAsUTF8(pass); | ||
var utf8Salt = _encodeStringAsUTF8(this._auth.salt); | ||
var authHash = CryptoJS.SHA256(utf8Pass + utf8Salt).toString(CryptoJS.enc.Base64); | ||
var utf8AuthHash = _encodeStringAsUTF8(authHash); | ||
var utf8Challenge = _encodeStringAsUTF8(this._auth.challenge); | ||
var authResp = CryptoJS.SHA256(utf8AuthHash + utf8Challenge).toString(CryptoJS.enc.Base64); | ||
callback(authResp); | ||
}; | ||
OBSWebSocket.prototype._nodeCryptoHash = function(pass, callback) { | ||
var authHasher = crypto.createHash('sha256'); | ||
var utf8Pass = _encodeStringAsUTF8(pass); | ||
var utf8Salt = _encodeStringAsUTF8(this._auth.salt); | ||
authHasher.update(utf8Pass + utf8Salt); | ||
var authHash = authHasher.digest('base64'); | ||
var respHasher = crypto.createHash('sha256'); | ||
var utf8AuthHash = _encodeStringAsUTF8(authHash); | ||
var utf8Challenge = _encodeStringAsUTF8(this._auth.challenge); | ||
respHasher.update(utf8AuthHash + utf8Challenge); | ||
var respHash = respHasher.digest('base64'); | ||
callback(respHash); | ||
}; | ||
function _encodeStringAsUTF8(string) { | ||
return unescape(encodeURIComponent(string)); | ||
// Send the request to the websocket. | ||
sendRequest(args); | ||
} | ||
function _stringToArrayBuffer(string) { | ||
var ret = new Uint8Array(string.length); | ||
for (var i = 0; i < string.length; i++) { | ||
ret[i] = string.charCodeAt(i); | ||
} | ||
function sendRequest(args) { | ||
if (OBSWebSocket._debug) | ||
console.log(OBSWebSocket.CONSOLE_NAME, '[sendRequest]', args); | ||
return ret.buffer; | ||
OBSWebSocket._socket.send(JSON.stringify(args)); | ||
} | ||
function _arrayBufferToBase64(arrayBuffer) { | ||
var binary = ''; | ||
var bytes = new Uint8Array(arrayBuffer); | ||
module.exports = OBSWebSocket; | ||
var length = bytes.byteLength; | ||
for (var i = 0; i < length; i++) { | ||
binary += String.fromCharCode(bytes[i]); | ||
} | ||
console.log(new OBSSource()); | ||
var s = new OBSSource(); | ||
console.log(new OBSScene("name", [s])); | ||
return btoa(binary); | ||
} | ||
var crypto = {}; | ||
/***/ }), | ||
/* 2 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
if (isModule()) { | ||
crypto = require('crypto'); | ||
OBSWebSocket.prototype._authHash = OBSWebSocket.prototype._nodeCryptoHash; | ||
} else { | ||
crypto = window.crypto || window.msCrypto || {}; | ||
OBSWebSocket.prototype._authHash = OBSWebSocket.prototype._webCryptoHash; | ||
var OBSSource = __webpack_require__(0); | ||
if (typeof crypto.subtle === 'undefined') { | ||
if (typeof crypto.webkitSubtle === 'undefined') { | ||
if (typeof CryptoJS === 'undefined') { | ||
throw new Error('OBS WebSocket requires CryptoJS when native crypto is unavailable.'); | ||
} | ||
OBSWebSocket.prototype._authHash = OBSWebSocket.prototype._cryptoJSHash; | ||
} else { | ||
crypto.subtle = crypto.webkitSubtle; | ||
} | ||
} | ||
} | ||
/** | ||
* Triggered on socket open. | ||
* | ||
* @function | ||
* @category listener | ||
* @class OBSScene | ||
* @param name {string} - Source name. | ||
* @param sources {Array.<OBSSource>} - Array of {@link OBSSource}s. | ||
*/ | ||
OBSWebSocket.prototype.onConnectionOpened = function() {}; | ||
module.exports = function(name, sources) { | ||
this.name = (typeof name === 'undefined') ? '' : name; | ||
sources = (typeof sources === 'undefined') ? [] : sources; | ||
/** | ||
* Triggered on socket close. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onConnectionClosed = function() {}; | ||
this.sources = sources; | ||
var self = this; | ||
/** | ||
* Triggered on socket failure. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onConnectionFailed = function() {}; | ||
/** | ||
* Triggered on {@link OBSWebSocket.authenticate} success. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onAuthenticationSuccess = function() {}; | ||
/** | ||
* Triggered on {@link OBSWebSocket.authenticate} failure. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onAuthenticationFailure = function() {}; | ||
/** | ||
* Triggered on Scene Change. | ||
* | ||
* @function | ||
* @category listener | ||
* @param sceneName {string} | ||
*/ | ||
OBSWebSocket.prototype.onSceneSwitch = function(sceneName) {}; // jshint ignore:line | ||
/** | ||
* Triggered when the scene list is modified (a scene has been created, removed, or renamed). | ||
* @function | ||
* @category listener | ||
* @param response {object} | ||
* @param response.currentScene {string} - Name of the currently active scene. | ||
* @param response.scenes {Array.<OBSScene>} | ||
*/ | ||
OBSWebSocket.prototype.onSceneListChanged = function(response) {}; // jshint ignore:line | ||
/** | ||
* Triggered when a request to start streaming has been issued. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onStreamStarting = function() {}; | ||
/** | ||
* Triggered when the stream has successfully started. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onStreamStarted = function() {}; | ||
/** | ||
* Triggered when a request to stop streaming has been issued. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onStreamStopping = function() {}; | ||
/** | ||
* Triggered when the stream has successfully stopped. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onStreamStopped = function() {}; | ||
/** | ||
* Triggered when a request to start recording has been issued. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onRecordingStarting = function() {}; | ||
/** | ||
* Triggered when the recording has successfully started. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onRecordingStarted = function() {}; | ||
/** | ||
* Triggered when a request to stop streaming has been issued. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onRecordingStopping = function() {}; | ||
/** | ||
* Triggered when the recording has successfully stopped. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onRecordingStopped = function() {}; | ||
/** | ||
* Triggered once per second while streaming. Emits details about the stream status. | ||
* | ||
* @function | ||
* @category listener | ||
* @param response {object} | ||
* @param response.streaming {bool} | ||
* @param response.recording {bool} | ||
* @param response.bytesPerSecond {int} | ||
* @param response.strain {int} | ||
* @param response.totalStreamTime {int} | ||
* @param response.numberOfFrames {int} | ||
* @param response.numberOfDroppedFrames {int} | ||
* @param response.fps {double} | ||
*/ | ||
OBSWebSocket.prototype.onStreamStatus = function(response) {}; // jshint ignore:line | ||
/** | ||
* Triggered when OBS has been closed. | ||
* | ||
* @function | ||
* @category listener | ||
*/ | ||
OBSWebSocket.prototype.onExit = function() {}; | ||
/** | ||
* Callback for GetVersion. | ||
* @callback getVersionCb | ||
* @param err {object} | ||
* @param data {object} | ||
* @param data.obsVersion {string} | ||
*/ | ||
/** | ||
* Retrieve OBSWebSocket version information. | ||
* | ||
* @function | ||
* @category request | ||
* @param callback {getVersionCb} | ||
*/ | ||
OBSWebSocket.prototype.getVersion = function(callback) { | ||
function nestedCallback(err, data) { | ||
if (data) { | ||
data['obsStudioVersion'] = data['obs-studio-version']; | ||
data['obsWebSocketVersion'] = data['obs-websocket-version']; | ||
if (sources.length > 0 && !(sources[0] instanceof OBSSource)) { | ||
this.sources = []; | ||
sources.forEach(function(source) { | ||
self.sources.push(new OBSScene().marshal(source)); | ||
}); | ||
} | ||
callback(err, data); | ||
} | ||
this._sendRequest('GetVersion', {}, nestedCallback); | ||
}; | ||
/** | ||
* Callback for getAuthRequired. | ||
* @callback getAuthRequiredCb | ||
* @param err | ||
* @param data | ||
* @param data.authRequired {bool} | ||
* @param data.salt {string=} | ||
* @param data.challenge {string=} | ||
*/ | ||
/** | ||
* Retrieve information about the OBSWebSocket authentication requirements. | ||
* | ||
* @function | ||
* @category request | ||
* @param callback {getAuthRequiredCb} | ||
*/ | ||
OBSWebSocket.prototype.getAuthRequired = function(callback) { | ||
this._sendRequest('GetAuthRequired', {}, callback); | ||
}; | ||
/** | ||
* Attempt to authenticate the OBSWebSocket connection. | ||
* | ||
* @function | ||
* @category request | ||
* @param password {string=} | ||
*/ | ||
OBSWebSocket.prototype.authenticate = function(password) { | ||
password = password || ''; | ||
var self = this; | ||
this._authHash(password, function(authResp) { | ||
self._sendRequest('Authenticate', { 'auth' : authResp }, function(err, data) { | ||
if (err) { | ||
console.error(OBSWebSocket.CONSOLE_NAME, "Authentication Failure.", err); | ||
self.onAuthenticationFailure(); | ||
return; | ||
} | ||
console.info(OBSWebSocket.CONSOLE_NAME, "Authentication Success."); | ||
self.onAuthenticationSuccess(); | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Initialize and authenticate the connection. | ||
* | ||
* @function | ||
* @category request | ||
* @param address=localhost {string} | ||
* @param password {string=} | ||
*/ | ||
OBSWebSocket.prototype.connect = function(address, password) { | ||
address = address || 'localhost'; | ||
password = password || ''; | ||
address += address.indexOf(':') > 0 ? '' : ':' + OBSWebSocket.DEFAULT_PORT; | ||
var self = this; | ||
if (this._connected) { | ||
this._socket.close(); | ||
this._connected = false; | ||
} | ||
this._socket = new WebSocket('ws://' + address); | ||
this._socket.onopen = function() { | ||
self._connected = true; | ||
self.onConnectionOpened(); | ||
self.getAuthRequired(function(err, data) { | ||
if (err) { return; } | ||
if (data['authRequired']) { | ||
self._auth.salt = data['salt']; | ||
self._auth.challenge = data['challenge']; | ||
self.authenticate(password); | ||
} | ||
}); | ||
this.marshal = function(scene) { | ||
return this(scene.name, scene.sources); | ||
}; | ||
}; | ||
this._socket.onclose = function() { | ||
if (self._connected) { | ||
self.onConnectionClosed(); | ||
} | ||
self._connected = false; | ||
}; | ||
this._socket.onerror = function(evt) { | ||
self.onConnectionFailed(evt); | ||
self._connected = false; | ||
}; | ||
/***/ }), | ||
/* 3 */ | ||
/***/ (function(module, exports) { | ||
this._socket.onmessage = function(msg) { | ||
// console.log(OBSWebSocket.CONSOLE_NAME, msg); | ||
self._onMessage(msg); | ||
}; | ||
}; | ||
module.exports = WebSocket; | ||
/** | ||
* Callback for getCurrentScene. | ||
* @callback getCurrentSceneCb | ||
* @param err | ||
* @param data {OBSScene} | ||
*/ | ||
/** | ||
* Retrieve the currently active scene. | ||
* | ||
* @function | ||
* @category request | ||
* @param callback {getCurrentSceneCb} | ||
*/ | ||
OBSWebSocket.prototype.getCurrentScene = function(callback) { | ||
function nestedCallback(err, data) { | ||
if (data) { | ||
data = marshalOBSScene(data); | ||
} | ||
/***/ }), | ||
/* 4 */ | ||
/***/ (function(module, exports, __webpack_require__) { | ||
callback(err, data); | ||
} | ||
module.exports = __webpack_require__(1); | ||
this._sendRequest('GetCurrentScene', {}, nestedCallback); | ||
}; | ||
/** | ||
* Set the currently active scene. | ||
* | ||
* @function | ||
* @category request | ||
* @param sceneName {string} - Scene name. | ||
*/ | ||
OBSWebSocket.prototype.setCurrentScene = function(sceneName) { | ||
this._sendRequest('SetCurrentScene', | ||
{ 'scene-name' : sceneName }); | ||
}; | ||
/** | ||
* Callback for getSceneList. | ||
* @callback getSceneListCb | ||
* @param err | ||
* @param data | ||
* @param data.currentScene {string} - Name of the currently active scene. | ||
* @param data.scenes {Array.<OBSScene>} - Array of {@link OBSScene}s. | ||
*/ | ||
/** | ||
* Retrieve the list of available scenes. | ||
* | ||
* @function | ||
* @category request | ||
* @param callback {getSceneListCb} | ||
*/ | ||
OBSWebSocket.prototype.getSceneList = function(callback) { | ||
function nestedCallback(err, data) { | ||
if (data) { | ||
data['currentScene'] = data['current-scene']; | ||
data['scenes'] = Object.keys(data['scenes']).map(function(key) { return marshalOBSScene(data['scenes'][key]); }); | ||
} | ||
callback(err, data); | ||
} | ||
this._sendRequest('GetSceneList', {}, nestedCallback); | ||
}; | ||
/** | ||
* Set the visibility of a selected source. | ||
* | ||
* @function | ||
* @category request | ||
* @param sourceName {string} - Name of the source. | ||
* @param visible {bool} - Whether the source should be visible or not. | ||
*/ | ||
OBSWebSocket.prototype.setSourceVisbility = function(sourceName, visible) { | ||
this._sendRequest('SetSourceVisibility', | ||
{ 'source' : sourceName, 'render' : visible }); | ||
}; | ||
/** | ||
* Toggle streaming state. | ||
* | ||
* @function | ||
* @category request | ||
*/ | ||
OBSWebSocket.prototype.toggleStreaming = function() { | ||
this._sendRequest('StartStopStreaming'); | ||
}; | ||
/** | ||
* Start streaming. | ||
* | ||
* @function | ||
* @category request | ||
*/ | ||
OBSWebSocket.prototype.startStreaming = function() { | ||
// TODO: | ||
}; | ||
/** | ||
* Stop streaming. | ||
* | ||
* @function | ||
* @category request | ||
*/ | ||
OBSWebSocket.prototype.stopStreaming = function() { | ||
// TODO; | ||
}; | ||
/** | ||
* Toggle recording state. | ||
* | ||
* @function | ||
* @category request | ||
*/ | ||
OBSWebSocket.prototype.startStopRecording = function() { | ||
this._sendRequest('StartStopRecording'); | ||
}; | ||
/** | ||
* Start recording. | ||
* | ||
* @function | ||
* @category request | ||
*/ | ||
OBSWebSocket.prototype.startRecording = function() { | ||
// TODO: | ||
}; | ||
/** | ||
* Stop recording. | ||
* | ||
* @function | ||
* @category request | ||
*/ | ||
OBSWebSocket.prototype.stopRecording = function() { | ||
// TODO; | ||
}; | ||
/** | ||
* Callback for getStreamStatus. | ||
* @callback getStreamStatusCb | ||
* @param err | ||
* @param data | ||
* @param data.streaming {bool} | ||
* @param data.recording {bool} | ||
* @param data.previewOnly {bool} - Always false. | ||
* @param data.bytesPerSec {int=} | ||
* @param data.strain {double=} | ||
* @param data.totalStreamTime {int=} | ||
* @param data.numTotalFrames {int=} | ||
* @param data.numDroppedFrames {int=} | ||
* @param data.fps {double=} | ||
*/ | ||
/** | ||
* Retrieve details about the stream status. | ||
* | ||
* @function | ||
* @category request | ||
* @param callback {getStreamStatusCb} | ||
*/ | ||
OBSWebSocket.prototype.getStreamStatus = function(callback) { | ||
function nestedCallback(err, data) { | ||
if (data) { | ||
data['previewOnly'] = data['preview-only']; | ||
data['bytesPerSec'] = data['bytes-per-sec']; | ||
data['totalStreamTime'] = data['total-stream-time']; | ||
data['numTotalFrames'] = data['num-total-frames']; | ||
data['numDroppedFrames'] = data['num-dropped-frames']; | ||
} | ||
callback(err, data); | ||
} | ||
this._sendRequest('GetStreamingStatus', {}, nestedCallback); | ||
}; | ||
/** | ||
* Callback for getTransitionList. | ||
* @callback getTransitionListCb | ||
* @param err | ||
* @param data | ||
* @param data.currentTransition {string} | ||
* @param data.transitions {Array.<string>} | ||
*/ | ||
/** | ||
* Retrieve the list of available transitions. | ||
* | ||
* @function | ||
* @category request | ||
* @param callback {getTransitionListCb} | ||
*/ | ||
OBSWebSocket.prototype.getTransitionList = function(callback) { | ||
function nestedCallback(err, data) { | ||
if (data) { | ||
data['currentTransition'] = data['current-transition']; | ||
} | ||
callback(err, data); | ||
} | ||
this._sendRequest('GetTransitionList', {}, nestedCallback); | ||
}; | ||
/** | ||
* Callback for getCurrentTransition. | ||
* @callback getCurrentTransitionCb | ||
* @param err | ||
* @param data | ||
* @param data.name {string} | ||
*/ | ||
/** | ||
* Retrieve the currently selected transition. | ||
* | ||
* @function | ||
* @category request | ||
* @param callback {getCurrentTransitionCb} | ||
*/ | ||
OBSWebSocket.prototype.getCurrentTransition = function(callback) { | ||
this._sendRequest('GetCurrentTransition', {}, callback); | ||
}; | ||
/** | ||
* Set the currently selected transition. | ||
* | ||
* @function | ||
* @category request | ||
* @param transitionName {string} | ||
*/ | ||
OBSWebSocket.prototype.setCurrentTransition = function(transitionName) { | ||
this._sendRequest('SetCurrentTransition', | ||
{ 'transition-name' : transitionName }); | ||
}; | ||
})(); | ||
/***/ }) | ||
/******/ ]); |
@@ -1,1 +0,1 @@ | ||
module.exports = require('./dist/obs-websocket.js'); | ||
module.exports = require('./src/obs-websocket-api.js'); |
@@ -0,0 +0,0 @@ |
{ | ||
"name": "obs-websocket-js", | ||
"version": "0.2.0", | ||
"version": "0.2.2", | ||
"description": "OBS Websocket API in Javascript", | ||
"main": "index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/haganbmj/obs-websocket-js.git" | ||
}, | ||
"repository": "haganbmj/obs-websocket-js", | ||
"scripts": { | ||
@@ -41,3 +38,8 @@ "test": "echo \"Error: no test specified\" && exit 1", | ||
"load-grunt-tasks": "^3.5.2" | ||
} | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/haganbmj/obs-websocket-js/issues" | ||
}, | ||
"homepage": "https://github.com/haganbmj/obs-websocket-js#readme", | ||
"sha": "abc" | ||
} |
# obs-websocket-js | ||
OBSWebSocket.JS allows Javascript-based connections to [obs-websocket](https://github.com/Palakis/obs-websocket). | ||
Based heavily on [obs-remote](https://github.com/nodecg/obs-remote-js), which is built for the older, obs-classic compatible plugin. | ||
# [API Documentation](dist/DOCUMENTATION.md) | ||
[![Build Status][badge-build-status]](https://travis-ci.org/haganbmj/obs-websocket-js) [![Latest release][badge-release]][Releases] [![Latest Tag][badge-tag]][Tags] | ||
**OBSWebSocket.JS allows Javascript-based connections to [obs-websocket](https://github.com/Palakis/obs-websocket). | ||
Based heavily on [obs-remote](https://github.com/nodecg/obs-remote-js), which is built for the older, obs-classic compatible plugin.** | ||
# [API Documentation](https://github.com/haganbmj/obs-websocket-js/blob/gh-pages/DOCUMENTATION.md) | ||
# [Distributable](https://haganbmj.github.io/obs-websocket-js/obs-websocket.js) | ||
## Usage | ||
@@ -66,1 +70,9 @@ | ||
- 2 spaces rather than tabs. | ||
[Releases]: https://github.com/haganbmj/obs-websocket-js/releases "obs-websocket-js Releases" | ||
[Tags]: https://github.com/haganbmj/obs-websocket-js/tags "obs-websocket-js Tags" | ||
[badge-build-status]: https://img.shields.io/travis/haganbmj/obs-websocket-js/master.svg?style=flat "Travis Status" | ||
[badge-tag]: https://img.shields.io/github/tag/haganbmj/obs-websocket-js.svg?style=flat "Latest Tag" | ||
[badge-release]: https://img.shields.io/github/release/haganbmj/obs-websocket-js.svg?style=flat "Latest Release" |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
7
0
2
78
33849
269
1
1