UNPKG

onvif

Version:

Client to ONVIF NVT devices Profile S: cameras

626 lines (579 loc) 23.4 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: media.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: media.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/** * @namespace cam * @description Media section for Cam class * @author Andrew D.Laptev &lt;a.d.laptev@gmail.com> * @licence MIT */ const Cam = require('./cam').Cam , linerase = require('./utils').linerase ; /** * @typedef {object} Cam~VideoSource * @property {string} $.token Video source token * @property {number} framerate * @property {number} resolution.width * @property {number} resolution.height */ /** * @callback Cam~GetVideoSourcesCallback * @property {?Error} error * @property {Cam~VideoSource|Array.&lt;Cam~VideoSource>} videoSources * @property {string} xml Raw SOAP response */ /** * Receive video sources * @param {Cam~GetVideoSourcesCallback} [callback] */ Cam.prototype.getVideoSources = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetVideoSources xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { /** * Video sources * @name Cam#videoSources * @type {Cam~VideoSource|Array.&lt;Cam~VideoSource>} */ this.videoSources = linerase(data).getVideoSourcesResponse.videoSources; } if (callback) { callback.call(this, err, this.videoSources, xml); } }.bind(this)); }; /** * @typedef {object} Cam~VideoSourceConfiguration * @property {string} token Token that uniquely refernces this configuration * @property {string} sourceToken Reference to the physical input * @property {string} name User readable name * @property {number} useCount Number of internal references currently using this configuration * @property {object} bounds * @property {number} bounds.height * @property {number} bounds.width * @property {number} bounds.x * @property {number} bounds.y */ /** * @callback Cam~GetVideoSourceConfigurationsCallback * @property {?Error} error * @property {Array.&lt;Cam~VideoSourceConfiguration>} videoSourceConfigurations * @property {string} xml Raw SOAP response */ /** * Receive video sources * @param {Cam~GetVideoSourceConfigurationsCallback} [callback] */ Cam.prototype.getVideoSourceConfigurations = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetVideoSourceConfigurations xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { this.videoSourceConfigurations = data[0].getVideoSourceConfigurationsResponse[0].configurations.map(function(data) { var obj = linerase(data); return { token: obj.$.token , name: obj.name , useCount: obj.useCount , sourceToken: obj.sourceToken , bounds: { height: obj.bounds.$.height , width: obj.bounds.$.width , x: obj.bounds.$.x , y: obj.bounds.$.y } }; }); } if (callback) { callback.call(this, err, this.videoSourceConfigurations, xml); } }.bind(this)); }; /** * @typedef {object} Cam~VideoEncoderConfiguration * @property {string} $.token Token that uniquely refernces this configuration * @property {string} name User readable name. * @property {string} useCount Number of internal references currently using this configuration * @property {string} encoding Used video codec ('JPEG' | 'MPEG4' | 'H264' ) * @property {object} resolution Configured video resolution * @property {number} resolution.width * @property {number} resolution.height * @property {number} quality Relative value for the video quantizers and the quality of the video. A high value within supported quality range means higher quality * @property {object} [rateControl] Optional element to configure rate control related parameters * @property {number} rateControl.frameRateLimit * @property {number} rateControl.encodingInterval * @property {number} rateControl.bitrateLimit * @property {object} [H264] Optional element to configure H.264 related parameters * @property {number} H264.govLength Group of Video frames length * @property {string} H264.H264profile the H.264 profile * @property {object} [MPEG4] Optional element to configure Mpeg4 related parameters * @property {number} MPEG4.govLength Determines the interval in which the I-Frames will be coded. * @property {string} MPEG4.MPEG4profile the Mpeg4 profile * @property {object} multicast * @property {string} multicast.address.type * @property {string} [multicast.address.IPv4Address] * @property {string} [multicast.address.IPv6Address] * @property {number} multicast.port * @property {number} multicast.TTL * @property {boolean} multicast.autoStart * @property {string} sessionTimeout The rtsp session timeout for the related video stream */ /** * @callback Cam~VideoEncoderConfigurationCallback * @property {?Error} error * @property {Cam~VideoEncoderConfiguration} videoEncoderConfiguration * @property {string} xml Raw SOAP response */ /** * @callback Cam~VideoEncoderConfigurationsCallback * @property {?Error} error * @property {Array.&lt;Cam~VideoEncoderConfiguration>} videoEncoderConfigurations * @property {string} xml Raw SOAP response */ /** * Get existing video encoder configuration by its token * If token is omitted tries first from #videoEncoderConfigurations array * @param {string} [token] Token of the requested video encoder configuration * @param {Cam~VideoEncoderConfigurationCallback} callback */ Cam.prototype.getVideoEncoderConfiguration = function(token, callback) { if (callback === undefined) { callback = token; if (this.videoEncoderConfigurations &amp;&amp; this.videoEncoderConfigurations[0]) { token = this.videoEncoderConfigurations[0].$.token; } else { return callback(new Error('No video encoder configuration token is present!')); } } this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetVideoEncoderConfiguration xmlns="http://www.onvif.org/ver10/media/wsdl">' + '&lt;ConfigurationToken>' + token + '&lt;/ConfigurationToken>' + '&lt;/GetVideoEncoderConfiguration>' + this._envelopeFooter() }, function(err, data, xml) { if (callback) { callback.call(this, err, err ? null : linerase(data[0].getVideoEncoderConfigurationResponse[0].configuration), xml); } }.bind(this)); }; /** * Get all existing video encoder configurations of a device * @param {Cam~VideoEncoderConfigurationsCallback} callback */ Cam.prototype.getVideoEncoderConfigurations = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetVideoEncoderConfigurations xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { this.videoEncoderConfigurations = data[0].getVideoEncoderConfigurationsResponse[0].configurations.map(function(config) { return linerase(config); }); } if (callback) { callback.call(this, err, this.videoEncoderConfigurations, xml); } }.bind(this)); }; /** * Set the device video encoder configuration * @param {object} options * @param {string} [options.token] Token that uniquely references this configuration. * @param {string} [$.token] Token that uniquely references this configuration. * @param {string} [options.name] User readable name. * @param {number} [options.useCount] Number of internal references (read-only) * @param {string} [options.encoding] ( JPEG | H264 | MPEG4 ) * @param {object} [options.resolution] Configured video resolution * @param {number} options.resolution.width Number of the columns of the Video image * @param {number} options.resolution.height Number of the lines of the Video image * @param {number} options.quality Relative value for the video quantizers and the quality of the video * @param {object} [options.rateControl] Optional element to configure rate control related parameters * @param {number} options.rateControl.frameRateLimit Maximum output framerate in fps * @param {number} options.rateControl.encodingInterval Interval at which images are encoded and transmitted (A value of 1 means that every frame is encoded, a value of 2 means that every 2nd frame is encoded ...) * @param {number} options.rateControl.bitrateLimit the maximum output bitrate in kbps * @param {object} [options.MPEG4] * @param {number} options.MPEG4.govLength Determines the interval in which the I-Frames will be coded * @param {string} options.MPEG4.profile the Mpeg4 profile ( SP | ASP ) * @param {object} [options.H264] * @param {number} options.H264.govLength Group of Video frames length * @param {string} options.H264.profile the H.264 profile ( Baseline | Main | Extended | High ) * @param {object} [options.multicast] * @param {object|number} [options.multicast.address] The multicast address (if this address is set to 0 no multicast streaming is enaled) * @param {string} options.multicast.address.type Indicates if the address is an IPv4 or IPv6 address ( IPv4 | IPv6) * @param {string} [options.multicast.address.IPv4Address] * @param {string} [options.multicast.address.IPv6Address] * @param {number} [options.multicast.port] The RTP mutlicast destination port * @param {number} [options.multicast.TTL] * @param {boolean} [options.multicast.autoStart] * @param {string} options.sessionTimeout * @param {Cam~VideoEncoderConfigurationCallback} callback */ Cam.prototype.setVideoEncoderConfiguration = function(options, callback) { if (!options.token &amp;&amp; !(options.$ &amp;&amp; options.$.token)) { return callback(new Error('No video encoder configuration token is present!')); } this._request({ service: 'media', body: this._envelopeHeader() + '&lt;SetVideoEncoderConfiguration xmlns="http://www.onvif.org/ver10/media/wsdl">' + '&lt;Configuration token = "' + (options.token || options.$.token) + '">' + ( options.name ? '&lt;Name xmlns="http://www.onvif.org/ver10/schema">' + options.name + '&lt;/Name>' : '' ) + ( options.useCount ? '&lt;UseCount xmlns="http://www.onvif.org/ver10/schema">' + options.useCount + '&lt;/UseCount>' : '' ) + ( options.encoding ? '&lt;Encoding xmlns="http://www.onvif.org/ver10/schema">' + options.encoding + '&lt;/Encoding>' : '' ) + ( options.resolution ? '&lt;Resolution xmlns="http://www.onvif.org/ver10/schema">' + ( options.resolution.width ? '&lt;Width>' + options.resolution.width + '&lt;/Width>' : '') + ( options.resolution.height ? '&lt;Height>' + options.resolution.height + '&lt;/Height>' : '') + '&lt;/Resolution>' : '') + ( options.quality ? '&lt;Quality xmlns="http://www.onvif.org/ver10/schema">' + options.quality + '&lt;/Quality>' : '' ) + ( options.rateControl ? '&lt;RateControl xmlns="http://www.onvif.org/ver10/schema">' + ( options.rateControl.frameRateLimit ? '&lt;FrameRateLimit>' + options.rateControl.frameRateLimit + '&lt;/FrameRateLimit>' : '' ) + ( options.rateControl.encodingInterval ? '&lt;EncodingInterval>' + options.rateControl.encodingInterval + '&lt;/EncodingInterval>' : '' ) + ( options.rateControl.bitrateLimit ? '&lt;BitrateLimit>' + options.rateControl.bitrateLimit + '&lt;/BitrateLimit>' : '' ) + '&lt;/RateControl>' : '' ) + ( options.MPEG4 ? '&lt;MPEG4 xmlns="http://www.onvif.org/ver10/schema">' + ( options.MPEG4.govLength ? '&lt;GovLength>' + options.MPEG4.govLength + '&lt;/GovLength>' : '' ) + ( options.MPEG4.profile ? '&lt;MPEG4Profile>' + options.MPEG4.profile + '&lt;/MPEG4Profile>' : '') + '&lt;/MPEG4>' : '') + ( options.H264 ? '&lt;H264 xmlns="http://www.onvif.org/ver10/schema">' + ( options.H264.govLength ? '&lt;GovLength>' + options.H264.govLength + '&lt;/GovLength>' : '' ) + ( options.H264.profile ? '&lt;H264Profile>' + options.H264.profile + '&lt;/H264Profile>' : '' ) + '&lt;/H264>' : '') + ( options.multicast ? '&lt;Multicast xmlns="http://www.onvif.org/ver10/schema">' + ( options.multicast.address ? '&lt;Address>' + ( options.multicast.address === 0 ? '0' : ( options.multicast.address.type ? '&lt;Type>' + options.multicast.address.type + '&lt;/Type>' : '' ) + ( options.multicast.address.IPv4Address ? '&lt;IPv4Address>' + options.multicast.address.IPv4Address + '&lt;/IPv4Address>' : '') + ( options.multicast.address.IPv6Address ? '&lt;IPv6Address>' + options.multicast.address.IPv6Address + '&lt;/IPv6Address>' : '') ) + '&lt;/Address>' : '') + ( options.multicast.port !== undefined ? '&lt;Port>' + options.multicast.port + '&lt;/Port>' : '' ) + ( options.multicast.TTL !== undefined ? '&lt;TTL>' + options.multicast.TTL + '&lt;/TTL>' : '') + ( options.multicast.autoStart !== undefined ? '&lt;AutoStart>' + options.multicast.autoStart + '&lt;/AutoStart>' : '') + '&lt;/Multicast>' : '' ) + ( options.sessionTimeout ? '&lt;SessionTimeout xmlns="http://www.onvif.org/ver10/schema">' + options.sessionTimeout + '&lt;/SessionTimeout>' : '' ) + '&lt;/Configuration>' + '&lt;ForcePersistence>true&lt;/ForcePersistence>' + '&lt;/SetVideoEncoderConfiguration>' + this._envelopeFooter() }, function(err, data, xml) { if (err || linerase(data).setVideoEncoderConfigurationResponse !== '') { return callback.call(this, linerase(data).setVideoEncoderConfigurationResponse !== '' ? new Error('Wrong `SetVideoEncoderConfiguration` response') : err, data, xml); } //get new encoding settings from device this.getVideoEncoderConfiguration(options.token, callback); }.bind(this)); }; /** * Get all available physical audio iutputs of a device * @param callback */ Cam.prototype.getAudioSources = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetAudioSources xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { this.audioSources = data[0].getAudioSourcesResponse[0].audioSources.map(function(config) { return linerase(config); }); } if (callback) { callback.call(this, err, this.audioSources, xml); } }.bind(this)); }; /** * Get all available audio encoder configurations of a device * @param callback */ Cam.prototype.getAudioEncoderConfigurations = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetAudioEncoderConfigurations xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { this.audioEncoderConfigurations = data[0].getAudioEncoderConfigurationsResponse[0].configurations.map(function(config) { return linerase(config); }); } if (callback) { callback.call(this, err, this.audioEncoderConfigurations, xml); } }.bind(this)); }; /** * Get all existing audio source configurations of a device * @param callback */ Cam.prototype.getAudioSourceConfigurations = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetAudioSourceConfigurations xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { this.audioSourceConfigurations = data[0].getAudioSourceConfigurationsResponse[0].configurations.map(function(config) { return linerase(config); }); } if (callback) { callback.call(this, err, this.audioSourceConfigurations, xml); } }.bind(this)); }; /** * Get all available audio outputs of a device * @param callback */ Cam.prototype.getAudioOutputs = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetAudioOutputs xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { this.audioOutputs = data[0].getAudioOutputsResponse[0].audioOutputs.map(function(config) { return linerase(config); }); } if (callback) { callback.call(this, err, this.audioOutputs, xml); } }.bind(this)); }; /** * Get all existing audio output configurations of a device * @param callback */ Cam.prototype.getAudioOutputConfigurations = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetAudioOutputConfigurations xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { this.audioOutputConfigurations = data[0].getAudioOutputConfigurationsResponse[0].configurations.map(function(config) { return linerase(config); }); } if (callback) { callback.call(this, err, this.audioOutputConfigurations, xml); } }.bind(this)); }; // TODO AddVideoEncoderConfiguration /* Cam.prototype.getVideoEncoderConfigurationOptions = function(options, callback) { if (callback === undefined) {callback = options; options = {};} this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetVideoEncoderConfigurationOptions xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { } if (callback) { callback.call(this, err, this.videoEncoderConfigurations, xml); } }.bind(this)); }; */ /** * @typedef {object} Cam~Profile * @property {object} $ * @property {string} $.token profile token * @property {boolean} $.fixed is this a system or a user profile * @property {object} videoSourceConfiguration * @property {string} videoSourceConfiguration.$.token video source token * @property {object} videoEncoderConfiguration * @property {object} PTZConfiguration * @property {string} PTZConfiguration.$.token PTZ token * @property {string} PTZConfiguration.name PTZ configuration name */ /** * @callback Cam~GetProfilesCallback * @property {?Error} error * @property {Array.&lt;Cam~Profile>} profiles Array of device's profiles * @property {string} xml Raw XML response */ /** * /Media/ Receive profiles * @param {Cam~GetProfilesCallback} [callback] */ Cam.prototype.getProfiles = function(callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetProfiles xmlns="http://www.onvif.org/ver10/media/wsdl"/>' + this._envelopeFooter() }, function(err, data, xml) { if (!err) { /** * Array of all device profiles * @name Cam#profiles * @type {Array&lt;Cam~Profile>} */ this.profiles = data[0]['getProfilesResponse'][0]['profiles'].map(function(profile) { return linerase(profile); }); } if (callback) { callback.call(this, err, this.profiles, xml); } }.bind(this)); }; /** * Create an empty new deletable media profile * @param options * @param {string} options.name Profile name * @param {string} [options.token] Profile token * @param {Cam~MessageCallback} callback */ Cam.prototype.createProfile = function(options, callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;CreateProfile xmlns="http://www.onvif.org/ver10/media/wsdl">' + '&lt;Name>' + options.name + '&lt;/Name>' + ( options.token ? '&lt;Token>' + options.token + '&lt;/Token>' : '' ) + '&lt;/CreateProfile>' + this._envelopeFooter() }, function(err, data, xml) { if (callback) { callback.call(this, err, err ? null : linerase(data).createProfileResponse.profile, xml); } }.bind(this)); }; /** * Delete a profile * @param {string} token * @param {Cam~MessageCallback} callback */ Cam.prototype.deleteProfile = function(token, callback) { this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;DeleteProfile xmlns="http://www.onvif.org/ver10/media/wsdl">' + '&lt;ProfileToken>' + token + '&lt;/ProfileToken>' + '&lt;/DeleteProfile>' + this._envelopeFooter() }, function(err, data, xml) { if (callback) { callback.call(this, err, err ? null : linerase(data).deleteProfileResponse, xml); } }.bind(this)); }; /** * @callback Cam~ResponseUriCallback * @property {string} uri */ /** * Receive stream URI * @param {Object} [options] * @param {string} [options.stream] * @param {string} [options.protocol] * @param {Cam~ResponseUriCallback} [callback] */ Cam.prototype.getStreamUri = function(options, callback) { if (callback === undefined) { callback = options; options = {}; } this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetStreamUri xmlns="http://www.onvif.org/ver10/media/wsdl">' + '&lt;StreamSetup>' + '&lt;Stream xmlns="http://www.onvif.org/ver10/schema">' + (options.stream || 'RTP-Unicast') +'&lt;/Stream>' + '&lt;Transport xmlns="http://www.onvif.org/ver10/schema">' + '&lt;Protocol>' + (options.protocol || 'RTSP') +'&lt;/Protocol>' + '&lt;/Transport>' + '&lt;/StreamSetup>' + '&lt;ProfileToken>' + (options.profileToken || this.activeSource.profileToken) +'&lt;/ProfileToken>' + '&lt;/GetStreamUri>' + this._envelopeFooter() }, function(err, data, xml) { if (callback) { callback.call(this, err, err ? null : linerase(data).getStreamUriResponse.mediaUri, xml); } }.bind(this)); }; /** * Receive snapshot URI * @param {Object} [options] * @param {string} [options.profileToken] * @param {Cam~ResponseUriCallback} [callback] */ Cam.prototype.getSnapshotUri = function(options, callback) { if (callback === undefined) { callback = options; options = {}; } this._request({ service: 'media' , body: this._envelopeHeader() + '&lt;GetSnapshotUri xmlns="http://www.onvif.org/ver10/media/wsdl">' + '&lt;ProfileToken>' + (options.profileToken || this.activeSource.profileToken) +'&lt;/ProfileToken>' + '&lt;/GetSnapshotUri>' + this._envelopeFooter() }, function(err, data, xml) { if (callback) { callback.call(this, err, err ? null : linerase(data).getSnapshotUriResponse.mediaUri, xml); } }.bind(this)); }; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Cam_.html">Cam</a></li><li><a href="Discovery_.html">Discovery</a></li></ul><h3>Events</h3><ul><li><a href="Cam_.html#event:event">event</a></li><li><a href="Cam_.html#event:rawResponse">rawResponse</a></li><li><a href="Discovery_.html#event:device">device</a></li><li><a href="Discovery_.html#event:error">error</a></li></ul><h3>Namespaces</h3><ul><li><a href="cam.html">cam</a></li><li><a href="discovery.html">discovery</a></li><li><a href="utils.html">utils</a></li></ul><h3>Global</h3><ul><li><a href="global.html#guid">guid</a></li><li><a href="global.html#linerase">linerase</a></li><li><a href="global.html#parseSOAPString">parseSOAPString</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Mon Jun 20 2016 15:42:17 GMT+0300 (MSK) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>