/* Autogenerated with Kurento Idl */
/*
* (C) Copyright 2013-2015 Kurento (https://kurento.openvidu.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var inherits = require('inherits');
var kurentoClient = require('kurento-client');
var disguise = kurentoClient.disguise;
var checkType = kurentoClient.checkType;
var ChecktypeError = checkType.ChecktypeError;
var Transaction = kurentoClient.TransactionsManager.Transaction;
var UriEndpoint = require('kurento-client-core').abstracts.UriEndpoint;
function noop(error, result) {
if (error) console.trace(error);
return result
};
/**
* Builder for the {@link RecorderEndpoint}
*
* @classdesc
* Provides functionality to store media contents.
* <p>
* RecorderEndpoint can store media into local files or send it to a remote
* network storage. When another {@link MediaElement} is connected to a
* RecorderEndpoint, the media coming from the former will be muxed into the
* selected recording format and stored in the designated location.
* </p>
* <p>
* These parameters must be provided to create a RecorderEndpoint, and they
* cannot be changed afterwards:
* </p>
* <ul>
* <li>
* <strong>Destination URI</strong>, where media will be stored. These
* formats
* are supported:
* <ul>
* <li>
* File: A file path that will be written into the local file system.
* Example:
* <ul>
* <li><code>file:///path/to/file</code></li>
* </ul>
* </li>
* <li>
* HTTP: A POST request will be used against a remote server. The
* server
* must support using the <i>chunked</i> encoding mode (HTTP header
* <code>Transfer-Encoding: chunked</code>). Examples:
* <ul>
* <li><code>http(s)://host/path/to/file</code></li>
* <li>
* <code>
* http(s)://username:password@host:port/path/to/file
* </code>
* </li>
* </ul>
* </li>
* <li>
* Relative URIs (with no schema) are supported. They are completed by
* prepending a default URI defined by property <i>defaultPath</i>.
* This
* property is defined in the configuration file
* <i>/etc/kurento/modules/kurento/UriEndpoint.conf.ini</i>, and the
* default value is <code>file:///var/lib/kurento/</code>
* </li>
* <li>
* <strong>
* NOTE: Special characters must be
* <a href='https://en.wikipedia.org/wiki/Query_string#URL_encoding'>
* URL-encoded
* </a>
* in <code>username</code> and <code>password</code> fields.
* </strong>
* </li>
* </ul>
* </li>
* <li>
* <strong>Media Profile</strong> ({@link MediaProfileSpecType}), which
* determines the video and audio encoding. See below for more details.
* </li>
* <li>
* <strong>EndOfStream</strong> (optional), a parameter that dictates if
* the
* recording should be automatically stopped once the EOS event is
* detected.
* </li>
* </ul>
* <p>
* Note that
* <strong>
* RecorderEndpoint requires write permissions to the destination
* </strong>
* ; otherwise, the media server won't be able to store any information, and
* an
* {@link ErrorEvent} will be fired. Make sure your application subscribes to
* event, otherwise troubleshooting issues will be difficult.
* </p>
* <ul>
* <li>
* To write local files (if you use <code>file://</code>), the system user
* that
* is owner of the media server process needs to have write permissions for
* requested path. By default, this user is named '<code>kurento</code>'.
* </li>
* <li>
* To record through HTTP, the remote server must be accessible through the
* network, and also have the correct write permissions for the destination
* path.
* </li>
* </ul>
* <p>
* Recording will start as soon as the user invokes the
* <code>record()</code> method. The recorder will then store, in the
* location
* indicated, the media that the source is sending to the endpoint. If no
* media
* is being received, or no endpoint has been connected, then the destination
* will be empty. The recorder starts storing information into the file as
* soon
* as it gets it.
* </p>
* <p>
* <strong>Recording must be stopped</strong> when no more data should be
* stored.
* This is done with the <code>stopAndWait()</code> method, which blocks and
* returns only after all the information was stored correctly.
* </p>
* <p>
* The source endpoint can be hot-swapped while the recording is taking
* place.
* The recorded file will then contain different feeds. When switching video
* sources, if the new video has different size, the recorder will retain the
* size of the previous source. If the source is disconnected, the last frame
* recorded will be shown for the duration of the disconnection, or until the
* recording is stopped.
* </p>
* <p>
* <strong>
* NOTE: It is recommended to start recording only after media arrives.
* </strong>
* For this, you may use the <code>MediaFlowInStateChanged</code> and
* <code>MediaFlowOutStateChanged</code>
* events of your endpoints, and synchronize the recording with the moment
* media
* comes into the Recorder.
* </p>
* <p>
* <strong>
* WARNING: All connected media types must be flowing to the
* RecorderEndpoint.
* </strong>
* If you used the default <code>connect()</code> method, it will assume both
* AUDIO and VIDEO. Failing to provide both kinds of media will result in the
* RecorderEndpoint creating an empty file and buffering indefinitely; the
* recorder waits until all kinds of media start arriving, in order to
* synchronize them appropriately.<br />
* For audio-only or video-only recordings, make sure to use the correct,
* media-specific variant of the <code>connect()</code> method.
* </p>
* <p>For example:</p>
* <ol>
* <li>
* When a web browser's video arrives to Kurento via WebRTC, your
* WebRtcEndpoint will emit a <code>MediaFlowOutStateChanged</code> event.
* </li>
* <li>
* When video starts flowing from the WebRtcEndpoint to the
* RecorderEndpoint,
* the RecorderEndpoint will emit a <code>MediaFlowInStateChanged</code>
* event.
* You should start recording at this point.
* </li>
* <li>
* You should only start recording when RecorderEndpoint has notified a
* <code>MediaFlowInStateChanged</code> for ALL streams. So, if you record
* AUDIO+VIDEO, your application must receive a
* <code>MediaFlowInStateChanged</code> event for audio, and another
* <code>MediaFlowInStateChanged</code> event for video.
* </li>
* </ol>
*
* @extends module:core/abstracts.UriEndpoint
*
* @constructor module:elements.RecorderEndpoint
*
* @fires {@link module:elements#event:Paused Paused}
* @fires {@link module:elements#event:Recording Recording}
* @fires {@link module:elements#event:Stopped Stopped}
*/
function RecorderEndpoint(){
RecorderEndpoint.super_.call(this);
};
inherits(RecorderEndpoint, UriEndpoint);
//
// Public methods
//
/**
* Starts storing media received through the sink pad.
*
* @alias module:elements.RecorderEndpoint.record
*
* @param {module:elements.RecorderEndpoint~recordCallback} [callback]
*
* @return {external:Promise}
*/
RecorderEndpoint.prototype.record = function(callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
var usePromise = false;
if (callback == undefined) {
usePromise = true;
}
if(!arguments.length) callback = undefined;
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'record', callback), this)
};
/**
* @callback module:elements.RecorderEndpoint~recordCallback
* @param {external:Error} error
*/
/**
* Stops recording and does not return until all the content has been written to
*
* @alias module:elements.RecorderEndpoint.stopAndWait
*
* @param {module:elements.RecorderEndpoint~stopAndWaitCallback} [callback]
*
* @return {external:Promise}
*/
RecorderEndpoint.prototype.stopAndWait = function(callback){
var transaction = (arguments[0] instanceof Transaction)
? Array.prototype.shift.apply(arguments)
: undefined;
var usePromise = false;
if (callback == undefined) {
usePromise = true;
}
if(!arguments.length) callback = undefined;
callback = (callback || noop).bind(this)
return disguise(this._invoke(transaction, 'stopAndWait', callback), this)
};
/**
* @callback module:elements.RecorderEndpoint~stopAndWaitCallback
* @param {external:Error} error
*/
/**
* @alias module:elements.RecorderEndpoint.constructorParams
*
* @property {module:core.MediaPipeline} mediaPipeline
* the {@link MediaPipeline} to which the endpoint belongs
*
* @property {module:elements/complexTypes.MediaProfileSpecType} [mediaProfile]
* Selects the media format used for recording.
* <p>
* The media profile allows you to specify which codecs and media container
* will
* be used for the recordings. This is currently the only way available to
* tell
* Kurento about which codecs should be used.
* </p>
* <p>
* Watch out for these important remarks:
* </p>
* <ul>
* <li>
* If the format of incoming media differs from the recording profile,
* media
* will need to be transcoded. Transcoding always incurs in noticeable CPU
* load, so it is always good trying to avoid it. For instance, if a
* VP8-encoded video (from WebRTC) is recorded with an MP4 recording
* profile
* (which means H.264 encoding), the video needs to be transcoded from VP8
* to
* H.264. On the other hand, recording with the WEBM profile would allow to
* store the video as-is with its VP8 encoding.
* </li>
* <li>
* If you intend to record audio-only or video-only media, select the
* appropriate <code>_AUDIO_ONLY</code> or <code>_VIDEO_ONLY</code>
* profile.
* For example, to record a WebRTC screen capture (as obtained from a web
* browser's call to <code>MediaDevices.getDisplayMedia()</code>), choose
* <code>WEBM_VIDEO_ONLY</code> instead of just <code>WEBM</code>.
* </li>
* </ul>
*
* @property {external:Boolean} [stopOnEndOfStream]
* Forces the recorder endpoint to finish processing data when an End Of Stream
*
* @property {external:String} uri
* URI where the recording will be stored. It must be accessible from the media
* <ul>
* <li>Local server resources: The user running the Kurento
* Media Server must have write permission over the file.</li>
* <li>Network resources: Must be accessible from the network
* where the media server is running.</li>
* </ul>
*/
RecorderEndpoint.constructorParams = {
mediaPipeline: {
type: 'kurento.MediaPipeline',
required: true
},
mediaProfile: {
type: 'kurento.MediaProfileSpecType' },
stopOnEndOfStream: {
type: 'boolean' },
uri: {
type: 'String',
required: true
}
};
/**
* @alias module:elements.RecorderEndpoint.events
*
* @extends module:core/abstracts.UriEndpoint.events
*/
RecorderEndpoint.events = UriEndpoint.events.concat(['Paused', 'Recording', 'Stopped']);
/**
* Checker for {@link module:elements.RecorderEndpoint}
*
* @memberof module:elements
*
* @param {external:String} key
* @param {module:elements.RecorderEndpoint} value
*/
function checkRecorderEndpoint(key, value)
{
if(!(value instanceof RecorderEndpoint))
throw ChecktypeError(key, RecorderEndpoint, value);
};
module.exports = RecorderEndpoint;
RecorderEndpoint.check = checkRecorderEndpoint;