/* 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
};
/**
* Builder for the {@link module:elements.RecorderEndpoint 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 module:core/abstracts.MediaElement
* MediaElement} is connected to a
* RecorderEndpoint, the media coming from the former will be encapsulated
* 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)://{server-ip}/path/to/file</code></li>
* <li>
* <code>
* http(s)://{username}:{password}@{server-ip}:{server-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 (for current versions of Kurento 6.x): special characters are
* supported in <code>{username}</code> or <code>{password}</code>.
* </strong>
* This means that <code>{username}</code> cannot contain colons
* (<code>:</code>), and <code>{password}</code> cannot contain 'at'
* signs
* (<code>@</code>). This is a limitation of GStreamer 1.8 (the
* underlying
* media framework behind Kurento), and is already fixed in newer
* versions
* (which the upcoming Kurento 7.x will use).
* </li>
* <li>
* <strong>
* NOTE (for upcoming Kurento 7.x): special characters in
* <code>{username}</code> or <code>{password}</code> must be
* url-encoded.
* </strong>
* This means that colons (<code>:</code>) should be replaced with
* '<code>%3A</code>', and 'at' signs (<code>@</code>) should be
* replaced
* with '<code>%40</code>'.
* </li>
* </ul>
* </li>
* <li>
* <strong>Media Profile</strong> ({@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>
* <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>
* The <strong>Media Profile</strong> 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: If your pipeline receives <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>
* <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>
* <strong>
* If your output file is empty, this means that the recorder is waiting
* for
* input media.
* </strong>
* When another endpoint is connected to the recorder, by default both AUDIO
* and
* VIDEO media types are expected, unless specified otherwise when invoking
* the
* <code>connect</code> method. Failing to provide both types, will result in
* RecorderEndpoint buffering the received media: it won't be written to the
* file
* until the recording is stopped. The recorder waits until all types of
* media
* start arriving, in order to synchronize them appropriately.
* </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>MediaFlowInStateChanged</code> and
* <code>MediaFlowOutStateChanged</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>MediaFlowOutStateChanged</code> event.
* </li>
* <li>
* When video packets arrive from the WebRtcEndpoint to the
* RecorderEndpoint,
* the RecorderEndpoint will raise a <code>MediaFlowInStateChanged</code>
* event.
* </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 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 received at the sink pad, media will be transcoded, 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 to 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 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;