/* Autogenerated with Kurento Idl */
/*
* (C) Copyright 2013-2015 Kurento (http://kurento.org/)
*
* 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
};
/**
*
* @classdesc
* Provides functionality to store media contents.
* <p>
* The RecorderEndpoint can store media in local files or in a network
* resource.
* It receives a media stream from another {@link
* module:core/abstracts.MediaElement MediaElement} (i.e. the
* source), and stores it in the designated location.
* </p>
* <p>
* The following information has to be provided in order to create a
* RecorderEndpoint, and 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 exists in the local file system.
* <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>).
* <ul>
* <li><code>http(s)://{server-ip}/path/to/file</code></li>
* <li>
* <code>
* http(s)://{username}:{password}@{server-ip}/path/to/file
* </code>
* </li>
* </ul>
* </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>
* The <stron>Media Profile</stron> ({@link
* module:elements.RecorderEndpoint#MediaProfileSpecType}) used for
* storage. This will determine the video and audio encoding. See below for
* more details about Media Profile.
* </li>
* <li>
* Optionally, the user can select if the endpoint will stop processing
* once
* the <strong>EndOfStream</strong> event is detected.
* </li>
* </ul>
* <p>
* <strong>
* RecorderEndpoint requires access to the resource where stream is going
* to be
* recorded
* </strong>
* . Otherwise, the media server won't be able to store any information, and
* an
* {@link ErrorEvent} will be fired. Please note that if you haven't
* subscribed to
* that type of event, you can be left wondering why your media is not being
* saved, while the error message was ignored.
* </p>
* <ul>
* <li>
* To write local files (if you use <code>file://</code>), the user running
* media server (by default, user <code>kurento</code>) needs to have write
* permissions for the requested path.
* </li>
* <li>
* To save into an HTTP server, the server must be accessible through the
* network, and also have the correct access rights to the destination
* path.
* </li>
* </ul>
* <p>
* The media profile is quite an important parameter, as it will determine
* whether the server needs to perform on-the-fly transcoding of the media.
* If
* the input stream codec if not compatible with the selected media profile,
* the
* media will be transcoded into a suitable format. This will result in a
* higher
* CPU load and will impact overall performance of the media server.
* </p>
* <p>
* For example: Say that your pipeline will receive <b>VP8</b>-encoded video
* from
* WebRTC, and sends it to a RecorderEndpoint; depending on the format
* selected...
* </p>
* <ul>
* <li>
* WEBM: The input codec is the same as the recording format, so no
* transcoding
* will take place.
* </li>
* <li>
* MP4: The media server will have to transcode from <b>VP8</b> to
* <b>H264</b>.
* This will raise the CPU load in the system.
* </li>
* <li>
* MKV: Again, video must be transcoded from <b>VP8</b> to <b>H264</b>,
* which
* means more CPU load.
* </li>
* </ul>
* <p>
* From this you can see how selecting the correct format for your
* application is
* a very important decision.
* </p>
* <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>
* Stopping the recording process is done through the
* <code>stopAndWait</code> method, which will return only after all the
* information was stored correctly. If the file is empty, this means that no
* media arrived at the recorder.
* </p>
* <p>
* When another endpoint is connected to the recorder, by default both AUDIO
* and
* VIDEO media types are expected, unless specified otherwise when invoking
* the
* connect method. Failing to provide both types, will result in teh
* recording
* buffering the received media: it won't be written to the file until the
* recording is stopped. This is due to the recorder waiting for the other
* type
* of media to arrive, so they are synchronized.
* </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>
* It is recommended to start recording only after media arrives
* </strong>
* . For this, you may use the <code>MediaFlowInStateChange</code> and
* <code>MediaFlowOutStateChange</code>
* events of your endpoints, and synchronize the recording with the moment
* media
* comes into the Recorder. For example:
* </p>
* <ol>
* <li>
* When the remote video arrives to KMS, your WebRtcEndpoint will start
* generating packets into the Kurento Pipeline, and it will trigger a
* <code>MediaFlowOutStateChange</code> event.
* </li>
* <li>
* When video packets arrive from the WebRtcEndpoint to the
* RecorderEndpoint,
* the RecorderEndpoint will raise a <code>MediaFlowInStateChange</code>
* event.
* </li>
* <li>
* You should only start recording when RecorderEndpoint has notified a
* <code>MediaFlowInStateChange</code> for ALL streams (so, if you record
* AUDIO+VIDEO, your application must receive a
* <code>MediaFlowInStateChange</code> event for audio, and another
* <code>MediaFlowInStateChange</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 module:core.MediaPipeline MediaPipeline} to which the endpoint
* belongs
*
* @property {module:elements/complexTypes.MediaProfileSpecType} [mediaProfile]
* Sets the media profile used for recording. If the profile is different than
* the one being recieved at the sink pad, media will be trnascoded, resulting
* in a higher CPU load. For instance, when recording a VP8 encoded video from
* a WebRTC endpoint in MP4, the load is higher that when recording in WEBM.
*
* @property {external:Boolean} [stopOnEndOfStream]
* Forces the recorder endpoint to finish processing data when an <a
* href="http://www.kurento.org/docs/current/glossary.html#term-eos">EOS</a> is
*
* @property {external:String} uri
* URI where the recording will be stored. It has to be accessible to the KMS
* process.
* <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 server
* 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;