var Janus = require('../externals/janus.nojquery'); var Promise = require('bluebird/js/release/bluebird'); /** * VideoMail usecase * @class * @classdesc VideoMail usecase * @param {object} onEvents Event handlers: onRecording, onStopped * @param {object} domElements DOM elements: videomail * @param {object} options Available options: stream * @return {Promise} VideoMail methods: startRecording, stopRecording, toggleAudio, toggleVideo * @example * var onEvents = { * onRecording: function() { * // Recording * }, * onStopped: function() { * // Stopped * } * }; * * var domElements = { * videomail: document.getElementById('videomail') * }; * * var options = { * stream: { * audioEnabled: true, * videoEnabled: true, * aDeviceId: null, * vDeviceId: null * } * }; * * usecases.videoMail(onEvents, domElements, options) * .then(function(action) { * // Use Case has been atacched succesfully * ... * }) * .catch(function(cause) { * // Error attaching the Use Case * console.log("Error Attach " + cause ); * }) */ var videoMail = function(onEvents, domElements, options) { var videomailHandle = null; var recordingId = null; var bandwidth = 1024 * 1024; // Stream options var streamOptions = (options && options.stream) ? options.stream : {}; if(!streamOptions.audioEnabled) streamOptions.audioEnabled = false; if(!streamOptions.videoEnabled) streamOptions.videoEnabled = false; if(!streamOptions.aDeviceId) streamOptions.aDeviceId = undefined; if(!streamOptions.vDeviceId) streamOptions.vDeviceId = undefined; /** * Close the current UseCase. It's recommended combine with disconnect method * @return {nothing} * @example * action.closeUsecase(); * myVideoApp.disconnect(); // Recommended */ var closeUsecase = function() { if(domElements) { for (var element in domElements) { if (!domElements.hasOwnProperty(element)) continue; var obj = domElements[element]; if(obj && obj.innerHTML) obj.innerHTML = ''; } } }; /** * The User sends a request to start recording a Video message * @param {string} recordPrefix Prefix record * @param {string} name File name * @return {nothing} * @example * action.startRecording('__default__', 'MyRecordMobile'); */ var startRecording = function(recordPrefix, name) { var fullname = recordPrefix + "VideoMail-" + name + "-" + Date.now(); // bitrate and keyframe interval can be set at any time: // before, after, during recording videomailHandle.send({ 'message': { 'request': 'configure', 'video-bitrate-max': bandwidth, // a quarter megabit 'video-keyframe-interval': 15000 // 15 seconds } }); videomailHandle.createOffer( { media: { // Publishers are sendonly audioRecv: false, audioSend: streamOptions.audioEnabled || false, videoRecv: false, videoSend: streamOptions.videoEnabled || false, data: false, audio: { deviceId: { exact: streamOptions.aDeviceId } }, video: { deviceId: { exact: streamOptions.vDeviceId } } }, // By default, it's sendrecv for audio and video... success: function(jsep) { Janus.debug("Got SDP!"); Janus.debug(jsep); var body = { "request": "record", "name": fullname }; videomailHandle.send({"message": body, "jsep": jsep}); }, error: function(error) { Janus.error("WebRTC error...", error); videomailHandle.hangup(); } }); }; /** * The User sends a request to stop recording the current Video message * @return {nothing} * @example * action.stopRecording(); */ var stopRecording = function() { var request = { "request": "stop" }; videomailHandle.send({"message": request}); videomailHandle.hangup(); }; /** * Toggle Audio stream (Mute/Unmute) * @return {boolean} Is audio muted? * @example * action.toggleAudio(); // true or false */ var toggleAudio = function() { if (videomailHandle.isAudioMuted()) videomailHandle.unmuteAudio(); else videomailHandle.muteAudio(); return videomailHandle.isAudioMuted(); }; /** * Toggle Video stream (Mute/Unmute) * @return {boolean} Is video muted? * @example * action.toggleVideo(); // true or false */ var toggleVideo = function() { if (videomailHandle.isVideoMuted()) videomailHandle.unmuteVideo(); else videomailHandle.muteVideo(); return videomailHandle.isVideoMuted(); }; return new Promise(function (resolve, reject) { window.VideoRTC.connection.handle.attach({ plugin: "janus.plugin.recordplay", success: function(pluginHandle) { videomailHandle = pluginHandle; resolve({ closeUsecase: closeUsecase, startRecording: startRecording, stopRecording: stopRecording, toggleAudio: toggleAudio, toggleVideo: toggleVideo }); }, error: function(cause) { Janus.error(" -- Error attaching plugin...", cause); reject(cause); }, consentDialog: function(on) { // Nothing }, onmessage: function(msg, jsep) { var result = msg["result"]; if(result !== null && result !== undefined) { if(result["status"] !== undefined && result["status"] !== null) { var event = result["status"]; if(event === 'recording') { // Got an ANSWER to our recording OFFER if(jsep !== null && jsep !== undefined) videomailHandle.handleRemoteJsep({jsep: jsep}); var id = result["id"]; if(id !== null && id !== undefined) { Janus.log("The ID of the current recording is " + id); recordingId = id; } if(onEvents && onEvents.onRecording) onEvents.onRecording(); } else if(event === 'slow_link') { var uplink = result["uplink"]; if(uplink !== 0) { // Janus detected issues when receiving our media, let's slow down bandwidth = parseInt(bandwidth / 1.5); videomailHandle.send({ 'message': { 'request': 'configure', 'video-bitrate-max': bandwidth, // Reduce the bitrate 'video-keyframe-interval': 15000 // Keep the 15 seconds key frame interval } }); } } else if(event === 'stopped') { Janus.log("Session has stopped!"); var id = result["id"]; if(recordingId !== null && recordingId !== undefined) { if(recordingId !== id) { Janus.warn("Not a stop to our recording?"); return; } } var container = domElements.videomail; container.innerHTML = ''; videomailHandle.hangup(); if(recordingId !== null && onEvents && onEvents.onStopped) onEvents.onStopped(); recordingId = null; } } } }, onlocalstream: function(stream) { Janus.debug(" ::: Got a local stream :::"); var container = domElements.videomail; container.innerHTML = '<video autoplay poster="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" id="vmail"></video>'; var videoElem = document.getElementById('vmail'); Janus.attachMediaStream(videoElem, stream); videoElem.muted = true; var videoTracks = stream.getVideoTracks(); if(videoTracks === null || videoTracks === undefined || videoTracks.length === 0) { // No remote video var nodeNoCamera = document.createElement('div'); nodeNoCamera.innerHTML = 'No camera available'; nodeNoCamera.style.position = "relative"; nodeNoCamera.style.height = "100%"; nodeNoCamera.style.width = "100%"; nodeNoCamera.style.top = "100%"; nodeNoCamera.style.left = "50%"; nodeNoCamera.style.transform = "translate(-50%,-50%)"; nodeNoCamera.className = "no-camera-available"; container.insertBefore(nodeNoCamera, container.firstChild); } }, onremotestream: function(stream) { // Nothing }, oncleanup: function() { var container = domElements.videomail; container.innerHTML = ''; }, detached: function() { // Nothing } }); }); }; exports.videoMail = videoMail;