{"version":3,"sources":["webpack://VideojsRecord/webpack/universalModuleDefinition","webpack://VideojsRecord/webpack/bootstrap","webpack://VideojsRecord/./src/js/engine/record-mode.js","webpack://VideojsRecord/./src/js/engine/record-engine.js","webpack://VideojsRecord/./src/js/utils/detect-browser.js","webpack://VideojsRecord/external \"videojs\"","webpack://VideojsRecord/./src/js/engine/record-rtc.js","webpack://VideojsRecord/(webpack)/buildin/global.js","webpack://VideojsRecord/./node_modules/global/window.js","webpack://VideojsRecord/./src/js/utils/browser-shim.js","webpack://VideojsRecord/./src/js/utils/format-time.js","webpack://VideojsRecord/./src/js/defaults.js","webpack://VideojsRecord/./src/js/controls/record-indicator.js","webpack://VideojsRecord/./src/js/controls/record-toggle.js","webpack://VideojsRecord/./src/js/controls/camera-button.js","webpack://VideojsRecord/./src/js/controls/device-button.js","webpack://VideojsRecord/./src/js/controls/record-canvas.js","webpack://VideojsRecord/./src/js/controls/animation-display.js","webpack://VideojsRecord/./src/js/videojs.record.js"],"names":["root","factory","exports","module","require","define","amd","window","__WEBPACK_EXTERNAL_MODULE__5__","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","r","value","n","__esModule","object","property","prototype","hasOwnProperty","p","s","isModeEnabled","mode","getRecorderMode","image","audio","video","animation","IMAGE_ONLY","AUDIO_ONLY","VIDEO_ONLY","AUDIO_VIDEO","ANIMATION","Component","videojs","getComponent","RecordEngine","player","options","_classCallCheck","this","evented","_possibleConstructorReturn","__proto__","getPrototypeOf","undefined","recordedData","URL","revokeObjectURL","fileObj","Blob","File","now","Date","lastModified","getTime","lastModifiedDate","e","TypeError","fileExtension","type","split","indexOf","data","addFileInfo","dispose","trigger","fileName","keys","navigator","msSaveOrOpenBlob","msSaveBlob","hyperlink","document","createElement","href","createObjectURL","download","style","body","documentElement","appendChild","click","target","dispatchEvent","MouseEvent","view","bubbles","cancelable","registerComponent","RECORDRTC","LIBVORBISJS","RECORDERJS","LAMEJS","OPUSRECORDER","detectBrowser","result","_window2","default","browser","mozGetUserMedia","version","extractVersion","userAgent","minVersion","webkitGetUserMedia","mediaDevices","match","RTCPeerConnection","uastring","expr","pos","length","parseInt","isEdge","isOpera","opera","isChrome","isSafari","_recordEngine","_detectBrowser","_recordMode","RecordRTCEngine","stream","mediaType","debug","inputStream","engine","RecordRTC","MRecordRTC","disableLogs","mimeType","bufferSize","sampleRate","numberOfAudioChannels","audioChannels","canvas","quality","frameRate","onTimeStamp","timeSlice","addStream","_get","destroy","startRecording","stopRecording","onStopRecording","bind","pauseRecording","resumeRecording","save","audioVideoURL","_this2","mediaURL","recordType","record","getRecordType","getBlob","recording","mtype","gif","g","Function","eval","global","win","self","setSrcObject","element","ignoreCreateObjectURL","src","srcObject","mozSrcObject","console","log","seconds","guide","msDisplayMax","Math","floor","h","gm","gh","ms","isNaN","Infinity","maxLength","frameWidth","frameHeight","videoMimeType","videoRecorderType","audioEngine","audioRecorderType","audioMimeType","audioBufferSize","audioSampleRate","audioBitRate","audioWorkerURL","animationFrameRate","animationQuality","RecordIndicator","_this","enable","className","dir","on","player_","show","hide","off","Button","RecordToggle","onStart","onStop","event","recorder","isRecording","stop","start","removeClass","addClass","controlText","controlText_","CameraButton","isProcessing","retrySnapshot","DeviceButton","getDevice","RecordCanvas","innerHTML","AnimationDisplay","Plugin","_video2","getPlugin","play","retval","techGet_","then","Record","loadOptions","resetState","deviceIcon","_deviceButton2","buildCSSClass","deviceButton","addChild","recordIndicator","_recordIndicator2","recordCanvas","_recordCanvas2","animationDisplay","_animationDisplay2","cameraButton","_cameraButton2","recordToggle","_recordToggle2","one","setupUI","recordOptions","mergeOptions","_defaults2","options_","plugins","recordImage","recordAudio","recordVideo","recordAnimation","recordTimeSlice","videoFrameWidth","videoFrameHeight","controlBar","el","insertBefore","firstChild","remainingTimeDisplay","display","liveDisplay","loop","surfer","wavesurfer","bigPlayButton","setDuration","usingNativeControls_","tech_","el_","controls","removeTechControlsListeners_","progressControl","userActive","playToggle","_recording","_processing","children","deviceReadyCallback","onDeviceReady","deviceErrorCallback","onDeviceError","engineStopCallback","onRecordComplete","microphone","un","setupPlaybackEvents","liveMode","paused","getUserMedia","catch","_this3","_deviceActive","setCurrentTime","playbackTimeUpdate","Error","EngineClass","LibVorbisEngine","RecorderjsEngine","LamejsEngine","OpusRecorderEngine","err","error","bitRate","width","height","setup","currentTimeDisplay","timeDivider","durationDisplay","forEach","disable","mediaElement","muted","displayVolumeControl","load","code","deviceErrorCode","_this4","startVideoPreview","captureFrame","createSnapshot","pauseTime","pausedTime","startTime","countDown","setInterval","onCountDown","clearInterval","stopStream","stopDevice","getTracks","pause","resume","_this5","loadingSpinner","once","streamDuration","showAnimation","hideAnimation","duration","currentTime","streamCurrentTime","getCurrentTime","min","formattedTime_","contentEl","lastChild","textContent","_formatTime2","url","_browserShim2","saveAs","_this6","reset","empty","devices","_this7","toDataURL","_this8","detected","Promise","resolve","reject","ImageCapture","_typeof","track","getVideoTracks","grabFrame","imageBitmap","drawCanvas","getContext","drawImage","current","all","internal","currentTimestamp","allTimestamps","audioRecorder","gifRecorder","videoRecorder","getInternalRecorder","MediaStreamRecorder","getArrayOfBlobs","_this9","enumerateDevices","enumerateErrorCode","device","push","deviceId","_this10","errorMessage","setSinkId","sinkId","volumePanel","VERSION","registerPlugin"],"mappings":"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","file":"videojs.record.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"videojs\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"VideojsRecord\", [\"videojs\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"VideojsRecord\"] = factory(require(\"videojs\"));\n\telse\n\t\troot[\"VideojsRecord\"] = factory(root[\"videojs\"]);\n})(window, function(__WEBPACK_EXTERNAL_MODULE__5__) {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 19);\n","/**\n * @file record-mode.js\n * @since 2.0.0\n */\n\n// recorder modes\nconst IMAGE_ONLY = 'image_only';\nconst AUDIO_ONLY = 'audio_only';\nconst VIDEO_ONLY = 'video_only';\nconst AUDIO_VIDEO = 'audio_video';\nconst ANIMATION = 'animation';\n\n\nconst getRecorderMode = function(image, audio, video, animation) {\n if (isModeEnabled(image)) {\n return IMAGE_ONLY;\n\n } else if (isModeEnabled(animation)) {\n return ANIMATION;\n\n } else if (isModeEnabled(audio) && !isModeEnabled(video)) {\n return AUDIO_ONLY;\n\n } else if (isModeEnabled(audio) && isModeEnabled(video)) {\n return AUDIO_VIDEO;\n\n } else if (!isModeEnabled(audio) && isModeEnabled(video)) {\n return VIDEO_ONLY;\n }\n};\n\n/**\n * Return boolean indicating whether mode is enabled or not.\n *\n * @private\n */\nconst isModeEnabled = function(mode) {\n return mode === Object(mode) || mode === true;\n};\n\nexport {\n getRecorderMode,\n IMAGE_ONLY, AUDIO_ONLY, VIDEO_ONLY, AUDIO_VIDEO, ANIMATION\n};\n","/**\n * @file record-engine.js\n * @since 2.0.0\n */\n\nconst Component = videojs.getComponent('Component');\n\n// supported recorder plugin engines\nconst RECORDRTC = 'recordrtc';\nconst LIBVORBISJS = 'libvorbis.js';\nconst RECORDERJS = 'recorder.js';\nconst LAMEJS = 'lamejs';\nconst OPUSRECORDER = 'opus-recorder';\n\n/**\n * Base class for recorder backends.\n * @class\n * @augments videojs.Component\n */\nclass RecordEngine extends Component {\n /**\n * Creates an instance of this class.\n *\n * @param {Player} player\n * The `Player` that this class should be attached to.\n *\n * @param {Object} [options]\n * The key/value store of player options.\n */\n constructor(player, options) {\n\n // auto mixin the evented mixin (required since video.js v6.6.0)\n options.evented = true;\n\n super(player, options);\n }\n\n /**\n * Remove any temporary data and references to streams.\n * @private\n */\n dispose() {\n // dispose previous recording\n if (this.recordedData !== undefined) {\n URL.revokeObjectURL(this.recordedData);\n }\n }\n\n /**\n * Add filename and timestamp to recorded file object.\n *\n * @param {(blob|file)} fileObj - Blob or File object.\n */\n addFileInfo(fileObj) {\n if (fileObj instanceof Blob || fileObj instanceof File) {\n // set modification date\n let now = new Date();\n try {\n fileObj.lastModified = now.getTime();\n fileObj.lastModifiedDate = now;\n } catch (e) {\n if (e instanceof TypeError) {\n // ignore: setting getter-only property \"lastModifiedDate\"\n } else {\n // re-raise error\n throw e;\n }\n }\n // guess extension name from mime type, e.g. audio/ogg, but\n // any extension is valid here. Chrome also accepts extended\n // mime types like video/webm;codecs=h264,vp9,opus\n let fileExtension = '.' + fileObj.type.split('/')[1];\n if (fileExtension.indexOf(';') > -1) {\n fileExtension = fileExtension.split(';')[0];\n }\n\n // use timestamp in filename, e.g. 1451180941326.ogg\n try {\n fileObj.name = now.getTime() + fileExtension;\n } catch (e) {\n if (e instanceof TypeError) {\n // ignore: setting getter-only property \"name\"\n } else {\n // re-raise error\n throw e;\n }\n }\n }\n }\n\n /**\n * Invoked when recording is stopped and resulting stream is available.\n *\n * @param {blob} data - Reference to the recorded Blob.\n */\n onStopRecording(data) {\n this.recordedData = data;\n\n // add filename and timestamp to recorded file object\n this.addFileInfo(this.recordedData);\n\n // remove reference to recorded stream\n this.dispose();\n\n // notify listeners\n this.trigger('recordComplete');\n }\n\n /**\n * Show save as dialog in browser so the user can store the recorded media\n * locally.\n *\n * @param {object} name - Object with names for the particular blob(s)\n * you want to save. File extensions are added automatically. For\n * example: {'video': 'name-of-video-file'}. Supported keys are\n * 'audio', 'video' and 'gif'.\n */\n saveAs(name) {\n let fileName = name[Object.keys(name)[0]];\n\n if (typeof navigator.msSaveOrOpenBlob !== 'undefined') {\n return navigator.msSaveOrOpenBlob(this.recordedData, fileName);\n } else if (typeof navigator.msSaveBlob !== 'undefined') {\n return navigator.msSaveBlob(this.recordedData, fileName);\n }\n\n let hyperlink = document.createElement('a');\n hyperlink.href = URL.createObjectURL(this.recordedData);\n hyperlink.download = fileName;\n\n hyperlink.style = 'display:none;opacity:0;color:transparent;';\n (document.body || document.documentElement).appendChild(hyperlink);\n\n if (typeof hyperlink.click === 'function') {\n hyperlink.click();\n } else {\n hyperlink.target = '_blank';\n hyperlink.dispatchEvent(new MouseEvent('click', {\n view: window,\n bubbles: true,\n cancelable: true\n }));\n }\n\n URL.revokeObjectURL(hyperlink.href);\n }\n}\n\n// expose component for external plugins\nvideojs.RecordEngine = RecordEngine;\nComponent.registerComponent('RecordEngine', RecordEngine);\n\nexport {\n RecordEngine,\n RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS, OPUSRECORDER\n};\n","/**\n * @file detect-browser.js\n * @since 2.0.0\n */\n\nimport window from 'global/window';\n\n/**\n * Browser detector.\n *\n * @private\n * @return {object} result containing browser, version and minVersion\n * properties.\n */\nconst detectBrowser = function() {\n // returned result object\n let result = {};\n result.browser = null;\n result.version = null;\n result.minVersion = null;\n\n // fail early if it's not a browser\n if (typeof window === 'undefined' || !window.navigator) {\n result.browser = 'Not a supported browser.';\n return result;\n }\n\n if (navigator.mozGetUserMedia) { // Firefox.\n result.browser = 'firefox';\n result.version = extractVersion(navigator.userAgent,\n /Firefox\\/(\\d+)\\./, 1);\n result.minVersion = 31;\n } else if (navigator.webkitGetUserMedia) {\n // Chrome, Chromium, Webview, Opera.\n // Version matches Chrome/WebRTC version.\n result.browser = 'chrome';\n result.version = extractVersion(navigator.userAgent,\n /Chrom(e|ium)\\/(\\d+)\\./, 2);\n result.minVersion = 38;\n } else if (navigator.mediaDevices &&\n navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/)) { // Edge.\n result.browser = 'edge';\n result.version = extractVersion(navigator.userAgent,\n /Edge\\/(\\d+).(\\d+)$/, 2);\n result.minVersion = 10547;\n } else if (window.RTCPeerConnection &&\n navigator.userAgent.match(/AppleWebKit\\/(\\d+)\\./)) { // Safari.\n result.browser = 'safari';\n result.version = extractVersion(navigator.userAgent,\n /AppleWebKit\\/(\\d+)\\./, 1);\n } else {\n // Default fallthrough: not supported.\n result.browser = 'Not a supported browser.';\n return result;\n }\n\n return result;\n};\n\n/**\n * Extract browser version out of the provided user agent string.\n *\n * @private\n * @param {!string} uastring - userAgent string.\n * @param {!string} expr - Regular expression used as match criteria.\n * @param {!number} pos - position in the version string to be\n * returned.\n * @return {!number} browser version.\n */\nconst extractVersion = function(uastring, expr, pos) {\n let match = uastring.match(expr);\n return match && match.length >= pos && parseInt(match[pos], 10);\n};\n\nconst isEdge = function() {\n return detectBrowser().browser === 'edge';\n};\n\nconst isSafari = function() {\n return detectBrowser().browser === 'safari';\n};\n\nconst isOpera = function() {\n return !!window.opera || navigator.userAgent.indexOf('OPR/') !== -1;\n};\n\nconst isChrome = function() {\n return detectBrowser().browser === 'chrome';\n};\n\nexport {\n detectBrowser, isEdge, isOpera, isChrome, isSafari\n};\n","module.exports = __WEBPACK_EXTERNAL_MODULE__5__;","/**\n * @file record-rtc.js\n * @since 2.0.0\n */\n\nimport { RecordEngine } from './record-engine';\nimport { isChrome } from '../utils/detect-browser';\nimport {IMAGE_ONLY, AUDIO_ONLY, VIDEO_ONLY, AUDIO_VIDEO, ANIMATION} from './record-mode';\n\nconst Component = videojs.getComponent('Component');\n\n/**\n * Engine used with the MRecordRTC class in the RecordRTC library.\n *\n * @class\n * @augments videojs.RecordEngine\n */\nclass RecordRTCEngine extends RecordEngine {\n\n /**\n * Setup recording engine.\n */\n setup(stream, mediaType, debug) {\n this.inputStream = stream;\n this.mediaType = mediaType;\n this.debug = debug;\n\n // setup RecordRTC\n this.engine = new RecordRTC.MRecordRTC();\n this.engine.mediaType = this.mediaType;\n this.engine.disableLogs = !this.debug;\n this.engine.mimeType = this.mimeType;\n\n // audio settings\n this.engine.bufferSize = this.bufferSize;\n this.engine.sampleRate = this.sampleRate;\n this.engine.numberOfAudioChannels = this.audioChannels;\n\n // video/canvas settings\n this.engine.video = this.video;\n this.engine.canvas = this.canvas;\n\n // animated gif settings\n this.engine.quality = this.quality;\n this.engine.frameRate = this.frameRate;\n if (this.onTimeStamp !== undefined) {\n this.engine.timeSlice = this.timeSlice;\n this.engine.onTimeStamp = this.onTimeStamp;\n }\n\n // connect stream to recording engine\n this.engine.addStream(this.inputStream);\n }\n\n /**\n * Remove any temporary data and references to streams.\n */\n dispose() {\n super.dispose();\n\n if (typeof this.engine.destroy === 'function') {\n this.engine.destroy();\n }\n }\n\n /**\n * Start recording.\n */\n start() {\n this.engine.startRecording();\n }\n\n /**\n * Stop recording. Result will be available async when onStopRecording\n * is called.\n */\n stop() {\n this.engine.stopRecording(this.onStopRecording.bind(this));\n }\n\n /**\n * Pause recording.\n */\n pause() {\n this.engine.pauseRecording();\n }\n\n /**\n * Resume recording.\n */\n resume() {\n this.engine.resumeRecording();\n }\n\n /**\n * Show save as dialog in browser so the user can store the recorded media\n * locally.\n *\n * @param {object} name - Object with names for the particular blob(s)\n * you want to save. File extensions are added automatically. For\n * example: {'video': 'name-of-video-file'}. Supported keys are\n * 'audio', 'video' and 'gif'.\n */\n saveAs(name) {\n if (this.engine && name !== undefined) {\n this.engine.save(name);\n }\n }\n\n /**\n * Invoked when recording is stopped and resulting stream is available.\n *\n * @private\n * @param {string} audioVideoURL - Reference to the recorded Blob\n * object, e.g. 'blob:http://localhost:8080/10100016-4248-9949-b0d6-0bb40db56eba'\n * @param {string} type - Media type, eg. 'video' or 'audio'.\n */\n onStopRecording(audioVideoURL, type) {\n // store reference to recorded stream URL\n this.mediaURL = audioVideoURL;\n\n // store reference to recorded stream data\n let recordType = this.player().record().getRecordType();\n this.engine.getBlob((recording) => {\n switch (recordType) {\n case AUDIO_ONLY:\n this.recordedData = recording.audio;\n\n this.addFileInfo(this.recordedData);\n\n // notify listeners\n this.trigger('recordComplete');\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n // when recording both audio and video, recordrtc\n // calls this twice on chrome, first with audio data\n // and then with video data.\n // on firefox it's called once but with a single\n // blob that includes both audio and video data.\n if (recording.video !== undefined) {\n // data is video-only but on firefox audio+video\n this.recordedData = recording.video;\n\n // on the chrome browser two blobs are created\n // containing the separate audio/video streams.\n if (recordType === AUDIO_VIDEO && isChrome()) {\n // store both audio and video\n this.recordedData = recording;\n\n for (let mtype in this.recordedData) {\n this.addFileInfo(this.recordedData[mtype]);\n }\n } else {\n this.addFileInfo(this.recordedData);\n }\n\n // notify listeners\n this.trigger('recordComplete');\n }\n break;\n\n case ANIMATION:\n this.recordedData = recording.gif;\n\n this.addFileInfo(this.recordedData);\n\n // notify listeners\n this.trigger('recordComplete');\n break;\n }\n });\n }\n}\n\n// expose plugin\nvideojs.RecordRTCEngine = RecordRTCEngine;\n\nComponent.registerComponent('RecordRTCEngine', RecordRTCEngine);\n\nexport default RecordRTCEngine;\n","var g;\r\n\r\n// This works in non-strict mode\r\ng = (function() {\r\n\treturn this;\r\n})();\r\n\r\ntry {\r\n\t// This works if eval is allowed (see CSP)\r\n\tg = g || Function(\"return this\")() || (1, eval)(\"this\");\r\n} catch (e) {\r\n\t// This works if the window reference is available\r\n\tif (typeof window === \"object\") g = window;\r\n}\r\n\r\n// g can still be undefined, but nothing to do about it...\r\n// We return undefined, instead of nothing here, so it's\r\n// easier to handle this case. if(!global) { ...}\r\n\r\nmodule.exports = g;\r\n","var win;\n\nif (typeof window !== \"undefined\") {\n win = window;\n} else if (typeof global !== \"undefined\") {\n win = global;\n} else if (typeof self !== \"undefined\"){\n win = self;\n} else {\n win = {};\n}\n\nmodule.exports = win;\n","/**\n * @file browser-shim.js\n * @since 2.0.0\n */\n\nconst setSrcObject = function (stream, element, ignoreCreateObjectURL) {\n if ('createObjectURL' in URL && !ignoreCreateObjectURL) {\n try {\n element.src = URL.createObjectURL(stream);\n } catch (e) {\n setSrcObject(stream, element, true);\n return;\n }\n } else if ('srcObject' in element) {\n element.srcObject = stream;\n } else if ('mozSrcObject' in element) {\n element.mozSrcObject = stream;\n } else {\n console.log('createObjectURL/srcObject both are not supported.');\n }\n};\n\nexport default setSrcObject;\n","/**\n * @file format-time.js\n * @since 2.0.0\n */\n\n/**\n * Format seconds as a time string, H:MM:SS, M:SS or M:SS:MMM.\n *\n * Supplying a guide (in seconds) will force a number of leading zeros\n * to cover the length of the guide.\n *\n * @param {number} seconds - Number of seconds to be turned into a\n * string.\n * @param {number} guide - Number (in seconds) to model the string\n * after.\n * @param {number} msDisplayMax - Number (in milliseconds) to model the string\n * after.\n * @return {string} Time formatted as H:MM:SS, M:SS or M:SS:MMM, e.g.\n * 0:00:12.\n * @private\n */\nconst formatTime = function(seconds, guide, msDisplayMax) {\n // Default to using seconds as guide\n seconds = seconds < 0 ? 0 : seconds;\n guide = guide || seconds;\n let s = Math.floor(seconds % 60),\n m = Math.floor(seconds / 60 % 60),\n h = Math.floor(seconds / 3600),\n gm = Math.floor(guide / 60 % 60),\n gh = Math.floor(guide / 3600),\n ms = Math.floor((seconds - s) * 1000);\n\n // handle invalid times\n if (isNaN(seconds) || seconds === Infinity) {\n // '-' is false for all relational operators (e.g. <, >=) so this\n // setting will add the minimum number of fields specified by the\n // guide\n h = m = s = ms = '-';\n }\n\n // Check if we need to show milliseconds\n if (guide > 0 && guide < msDisplayMax) {\n if (ms < 100) {\n if (ms < 10) {\n ms = '00' + ms;\n } else {\n ms = '0' + ms;\n }\n }\n ms = ':' + ms;\n } else {\n ms = '';\n }\n\n // Check if we need to show hours\n h = (h > 0 || gh > 0) ? h + ':' : '';\n\n // If hours are showing, we may need to add a leading zero.\n // Always show at least one digit of minutes.\n m = (((h || gm >= 10) && m < 10) ? '0' + m : m) + ':';\n\n // Check if leading zero is need for seconds\n s = ((s < 10) ? '0' + s : s);\n\n return h + m + s + ms;\n};\n\nexport default formatTime;\n","/**\n * @file defaults.js\n * @since 2.0.0\n */\n\n//plugin defaults\nconst pluginDefaultOptions = {\n // Single snapshot image.\n image: false,\n // Include audio in the recorded clip.\n audio: false,\n // Include video in the recorded clip.\n video: false,\n // Animated GIF.\n animation: false,\n // Maximum length of the recorded clip.\n maxLength: 10,\n // Width of the recorded video frames.\n frameWidth: 320,\n // Height of the recorded video frames.\n frameHeight: 240,\n // Enables console logging for debugging purposes.\n debug: false,\n // The mime type for the video recorder. Default to 'video/webm'.\n // Use 'video/mp4' (Firefox) or 'video/webm;codecs=H264' (Chrome 52 and\n // newer) for MP4.\n videoMimeType: 'video/webm',\n // Video recorder type to use. This allows you to specify an alternative\n // recorder class, e.g. WhammyRecorder. Defaults to 'auto' which let's\n // recordrtc specify the best available recorder type.\n videoRecorderType: 'auto',\n // Audio recording library to use. Legal values are 'recordrtc',\n // 'libvorbis.js', 'opus-recorder', 'lamejs' and 'recorder.js'.\n audioEngine: 'recordrtc',\n // Audio recorder type to use. This allows you to specify an alternative\n // recorder class, e.g. StereoAudioRecorder. Defaults to 'auto' which let's\n // recordrtc specify the best available recorder type. Currently this\n // setting is only used with the 'recordrtc' audioEngine.\n audioRecorderType: 'auto',\n // The mime type for the audio recorder. Defaults to 'auto' which will pick\n // the best option available in the browser (e.g. either 'audio/wav',\n // 'audio/ogg' or 'audio/webm').\n audioMimeType: 'auto',\n // The size of the audio buffer (in sample-frames) which needs to\n // be processed each time onprocessaudio is called.\n // From the spec: This value controls how frequently the audioprocess event is\n // dispatched and how many sample-frames need to be processed each call.\n // Lower values for buffer size will result in a lower (better) latency.\n // Higher values will be necessary to avoid audio breakup and glitches.\n // Legal values are 256, 512, 1024, 2048, 4096, 8192 or 16384.\n audioBufferSize: 4096,\n // The audio sample rate (in sample-frames per second) at which the\n // AudioContext handles audio. It is assumed that all AudioNodes\n // in the context run at this rate. In making this assumption,\n // sample-rate converters or \"varispeed\" processors are not supported\n // in real-time processing.\n // The sampleRate parameter describes the sample-rate of the\n // linear PCM audio data in the buffer in sample-frames per second.\n // An implementation must support sample-rates in at least\n // the range 22050 to 96000.\n audioSampleRate: 44100,\n // The audio bitrate in kbps (only used in lamejs plugin).\n audioBitRate: 128,\n // Allows you to record single-channel audio, which can reduce the\n // filesize.\n audioChannels: 2,\n // URL for the audio worker.\n audioWorkerURL: '',\n // Frame rate in frames per second.\n animationFrameRate: 200,\n // Sets quality of color quantization (conversion of images to the\n // maximum 256 colors allowed by the GIF specification).\n // Lower values (minimum = 1) produce better colors,\n // but slow processing significantly. 10 is the default,\n // and produces good color mapping at reasonable speeds.\n // Values greater than 20 do not yield significant improvements\n // in speed.\n animationQuality: 10,\n // Accepts numbers in milliseconds; use this to force intervals-based blobs.\n timeSlice: 0\n};\n\nexport default pluginDefaultOptions;\n","/**\n * @file record-indicator.js\n * @since 2.0.0\n */\n\nconst Component = videojs.getComponent('Component');\n\n/**\n * Icon indicating recording is active.\n *\n * @class\n * @augments videojs.Component\n*/\nclass RecordIndicator extends Component {\n /**\n * The constructor function for the class.\n *\n * @private\n * @param {(videojs.Player|Object)} player - Video.js player instance.\n * @param {Object} options - Player options.\n */\n constructor(player, options) {\n super(player, options);\n\n this.enable();\n }\n\n /**\n * Create the `RecordIndicator`s DOM element.\n *\n * @return {Element}\n * The dom element that gets created.\n */\n createEl() {\n return super.createEl('div', {\n className: 'vjs-record-indicator vjs-control',\n dir: 'ltr'\n });\n }\n\n /**\n * Enable event handlers.\n */\n enable() {\n this.on(this.player_, 'startRecord', this.show);\n this.on(this.player_, 'stopRecord', this.hide);\n }\n\n /**\n * Disable event handlers.\n */\n disable() {\n this.off(this.player_, 'startRecord', this.show);\n this.off(this.player_, 'stopRecord', this.hide);\n }\n}\n\nComponent.registerComponent('RecordIndicator', RecordIndicator);\n\nexport default RecordIndicator;\n","/**\n * @file record-toggle.js\n * @since 2.0.0\n */\n\nconst Button = videojs.getComponent('Button');\nconst Component = videojs.getComponent('Component');\n\n/**\n * Button to toggle between start and stop recording.\n *\n * @class\n * @augments videojs.Button\n*/\nclass RecordToggle extends Button {\n /**\n * Builds the default DOM `className`.\n *\n * @return {string}\n * The DOM `className` for this object.\n */\n buildCSSClass() {\n return 'vjs-record-button vjs-control vjs-button vjs-icon-record-start';\n }\n\n /**\n * Enable the `RecordToggle` element so that it can be activated or clicked.\n */\n enable() {\n super.enable();\n\n this.on(this.player_, 'startRecord', this.onStart);\n this.on(this.player_, 'stopRecord', this.onStop);\n }\n\n /**\n * Disable the `RecordToggle` element so that it cannot be activated or clicked.\n */\n disable() {\n super.disable();\n\n this.off(this.player_, 'startRecord', this.onStart);\n this.off(this.player_, 'stopRecord', this.onStop);\n }\n\n /**\n * This gets called when the button is clicked.\n *\n * @param {EventTarget~Event} event\n * The `tap` or `click` event that caused this function to be\n * called.\n *\n * @listens tap\n * @listens click\n */\n handleClick(event) {\n let recorder = this.player_.record();\n if (!recorder.isRecording()) {\n recorder.start();\n } else {\n recorder.stop();\n }\n }\n\n /**\n * Add the vjs-icon-record-stop class to the element so it can change appearance.\n *\n * @param {EventTarget~Event} [event]\n * The event that caused this function to run.\n *\n * @listens Player#startRecord\n */\n onStart(event) {\n // replace element class so it can change appearance\n this.removeClass('vjs-icon-record-start');\n this.addClass('vjs-icon-record-stop');\n\n // change the button text\n this.controlText('Stop');\n }\n\n /**\n * Add the vjs-icon-record-start class to the element so it can change appearance.\n *\n * @param {EventTarget~Event} [event]\n * The event that caused this function to run.\n *\n * @listens Player#stopRecord\n */\n onStop(event) {\n // replace element class so it can change appearance\n this.removeClass('vjs-icon-record-stop');\n this.addClass('vjs-icon-record-start');\n\n // change the button text\n this.controlText('Record');\n }\n}\n\n/**\n * The text that should display over the `RecordToggle`s controls. Added for localization.\n *\n * @type {string}\n * @private\n */\nRecordToggle.prototype.controlText_ = 'Record';\n\nComponent.registerComponent('RecordToggle', RecordToggle);\n\nexport default RecordToggle;\n","/**\n * @file camera-button.js\n * @since 2.0.0\n */\n\nconst Button = videojs.getComponent('Button');\nconst Component = videojs.getComponent('Component');\n\n/**\n * Button to toggle between create and retry snapshot image.\n *\n * @class\n * @augments videojs.Button\n*/\nclass CameraButton extends Button {\n /**\n * Builds the default DOM `className`.\n *\n * @return {string}\n * The DOM `className` for this object.\n */\n buildCSSClass() {\n return 'vjs-camera-button vjs-control vjs-button vjs-icon-photo-camera';\n }\n\n /**\n * Enable the `CameraButton` element so that it can be activated or clicked.\n */\n enable() {\n super.enable();\n\n this.on(this.player_, 'startRecord', this.onStart);\n this.on(this.player_, 'stopRecord', this.onStop);\n }\n\n /**\n * Disable the `CameraButton` element so that it cannot be activated or clicked.\n */\n disable() {\n super.disable();\n\n this.off(this.player_, 'startRecord', this.onStart);\n this.off(this.player_, 'stopRecord', this.onStop);\n }\n\n /**\n * This gets called when the button is clicked.\n *\n * @param {EventTarget~Event} event\n * The `tap` or `click` event that caused this function to be\n * called.\n *\n * @listens tap\n * @listens click\n */\n handleClick(event) {\n let recorder = this.player_.record();\n\n if (!recorder.isProcessing()) {\n // create snapshot\n recorder.start();\n } else {\n // retry\n recorder.retrySnapshot();\n\n // reset camera button\n this.onStop();\n }\n }\n\n /**\n * Add the vjs-icon-replay class to the element so it can change appearance.\n *\n * @param {EventTarget~Event} [event]\n * The event that caused this function to run.\n *\n * @listens Player#startRecord\n */\n onStart(event) {\n // replace element class so it can change appearance\n this.removeClass('vjs-icon-photo-camera');\n this.addClass('vjs-icon-replay');\n\n // change the button text\n this.controlText('Retry');\n }\n\n /**\n * Add the vjs-icon-photo-camera class to the element so it can change appearance.\n *\n * @param {EventTarget~Event} [event]\n * The event that caused this function to run.\n *\n * @listens Player#stopRecord\n */\n onStop(event) {\n // replace element class so it can change appearance\n this.removeClass('vjs-icon-replay');\n this.addClass('vjs-icon-photo-camera');\n\n // change the button text\n this.controlText('Image');\n }\n}\n\n/**\n * The text that should display over the `CameraButton`s controls. Added for localization.\n *\n * @type {string}\n * @private\n */\nCameraButton.prototype.controlText_ = 'Image';\n\nComponent.registerComponent('CameraButton', CameraButton);\n\nexport default CameraButton;\n","/**\n * @file device-button.js\n * @since 2.0.0\n */\n\nconst Button = videojs.getComponent('Button');\nconst Component = videojs.getComponent('Component');\n\n/**\n * Button to select recording device.\n *\n * @class\n * @augments videojs.Button\n*/\nclass DeviceButton extends Button {\n /**\n * This gets called when this button gets:\n *\n * - Clicked (via the `click` event, listening starts in the constructor)\n * - Tapped (via the `tap` event, listening starts in the constructor)\n *\n * @param {EventTarget~Event} event\n * The `keydown`, `tap`, or `click` event that caused this function to be\n * called.\n *\n * @listens tap\n * @listens click\n */\n handleClick(event) {\n // open device dialog\n this.player_.record().getDevice();\n }\n}\n\n/**\n * The text that should display over the `DeviceButton`s controls. Added for localization.\n *\n * @type {string}\n * @private\n */\nDeviceButton.prototype.controlText_ = 'Device';\n\nComponent.registerComponent('DeviceButton', DeviceButton);\n\nexport default DeviceButton;\n","/**\n * @file record-canvas\n * @since 2.0.0\n */\n\nconst Component = videojs.getComponent('Component');\n\n/**\n * Canvas for displaying snapshot image.\n *\n * @class\n * @augments videojs.Component\n*/\nclass RecordCanvas extends Component {\n\n /**\n * Create the `RecordCanvas`s DOM element.\n *\n * @return {Element}\n * The dom element that gets created.\n */\n createEl() {\n return super.createEl('div', {\n className: 'vjs-record-canvas',\n innerHTML: ''\n });\n }\n}\n\nComponent.registerComponent('RecordCanvas', RecordCanvas);\n\nexport default RecordCanvas;\n","/**\n * @file animation-display.js\n * @since 2.0.0\n */\n\nconst Component = videojs.getComponent('Component');\n\n/**\n * Image for displaying animated GIF image.\n *\n * @class\n * @augments videojs.Component\n*/\nclass AnimationDisplay extends Component {\n\n /**\n * Create the `AnimationDisplay`s DOM element.\n *\n * @return {Element}\n * The dom element that gets created.\n */\n createEl() {\n return super.createEl('div', {\n className: 'vjs-animation-display',\n innerHTML: ''\n });\n }\n}\n\nComponent.registerComponent('AnimationDisplay', AnimationDisplay);\n\nexport default AnimationDisplay;\n","/**\n * @file videojs.record.js\n *\n * The main file for the videojs-record project.\n * MIT license: https://github.com/collab-project/videojs-record/blob/master/LICENSE\n */\n\nimport AnimationDisplay from './controls/animation-display';\nimport RecordCanvas from './controls/record-canvas';\nimport DeviceButton from './controls/device-button';\nimport CameraButton from './controls/camera-button';\nimport RecordToggle from './controls/record-toggle';\nimport RecordIndicator from './controls/record-indicator';\n\nimport pluginDefaultOptions from './defaults';\nimport formatTime from './utils/format-time';\nimport setSrcObject from './utils/browser-shim';\nimport { detectBrowser, isChrome } from './utils/detect-browser';\n\nimport RecordRTCEngine from './engine/record-rtc';\nimport {RECORDRTC, LIBVORBISJS, RECORDERJS, LAMEJS, OPUSRECORDER} from './engine/record-engine';\nimport {IMAGE_ONLY, AUDIO_ONLY, VIDEO_ONLY, AUDIO_VIDEO, ANIMATION, getRecorderMode} from './engine/record-mode';\n\nimport videojs from 'video.js';\n\nconst Plugin = videojs.getPlugin('plugin');\nconst Player = videojs.getComponent('Player');\n\nconst AUTO = 'auto';\n\n\n// monkey-patch play (#152)\nPlayer.prototype.play = function play() {\n let retval = this.techGet_('play');\n // silence errors (unhandled promise from play)\n if (retval !== undefined && typeof retval.then === 'function') {\n retval.then(null, (e) => {});\n }\n return retval;\n};\n\n/**\n * Record audio/video/images using the Video.js player.\n *\n * @class\n * @augments videojs.Plugin\n */\nclass Record extends Plugin {\n /**\n * The constructor function for the class.\n *\n * @param {(videojs.Player|Object)} player\n * @param {Object} options - Player options.\n */\n constructor(player, options) {\n super(player, options);\n\n // add plugin style\n player.addClass('vjs-record');\n\n // setup plugin options\n this.loadOptions();\n\n // (re)set recorder state\n this.resetState();\n\n // add device button with icon based on type\n let deviceIcon = 'av-perm';\n switch (this.getRecordType()) {\n case IMAGE_ONLY:\n case VIDEO_ONLY:\n case ANIMATION:\n deviceIcon = 'video-perm';\n break;\n case AUDIO_ONLY:\n deviceIcon = 'audio-perm';\n break;\n }\n DeviceButton.prototype.buildCSSClass = function() {\n // use dynamic icon class\n return 'vjs-record vjs-device-button vjs-control vjs-icon-' + deviceIcon;\n };\n player.deviceButton = new DeviceButton(player, options);\n player.addChild(player.deviceButton);\n\n // add blinking record indicator\n player.recordIndicator = new RecordIndicator(player, options);\n player.recordIndicator.hide();\n player.addChild(player.recordIndicator);\n\n // add canvas for recording and displaying image\n player.recordCanvas = new RecordCanvas(player, options);\n player.recordCanvas.hide();\n player.addChild(player.recordCanvas);\n\n // add image for animation display\n player.animationDisplay = new AnimationDisplay(player, options);\n player.animationDisplay.hide();\n player.addChild(player.animationDisplay);\n\n // add camera button\n player.cameraButton = new CameraButton(player, options);\n player.cameraButton.hide();\n\n // add record toggle\n player.recordToggle = new RecordToggle(player, options);\n player.recordToggle.hide();\n\n // wait until player ui is ready\n this.player.one('ready', this.setupUI.bind(this));\n }\n\n /**\n * Setup plugin options.\n */\n loadOptions() {\n let recordOptions = videojs.mergeOptions(pluginDefaultOptions,\n this.player.options_.plugins.record);\n\n // record settings\n this.recordImage = recordOptions.image;\n this.recordAudio = recordOptions.audio;\n this.recordVideo = recordOptions.video;\n this.recordAnimation = recordOptions.animation;\n this.maxLength = recordOptions.maxLength;\n this.debug = recordOptions.debug;\n this.recordTimeSlice = recordOptions.timeSlice;\n\n // video/canvas settings\n this.videoFrameWidth = recordOptions.frameWidth;\n this.videoFrameHeight = recordOptions.frameHeight;\n this.videoRecorderType = recordOptions.videoRecorderType;\n this.videoMimeType = recordOptions.videoMimeType;\n\n // audio settings\n this.audioEngine = recordOptions.audioEngine;\n this.audioRecorderType = recordOptions.audioRecorderType;\n this.audioWorkerURL = recordOptions.audioWorkerURL;\n this.audioBufferSize = recordOptions.audioBufferSize;\n this.audioSampleRate = recordOptions.audioSampleRate;\n this.audioBitRate = recordOptions.audioBitRate;\n this.audioChannels = recordOptions.audioChannels;\n this.audioMimeType = recordOptions.audioMimeType;\n\n // animation settings\n this.animationFrameRate = recordOptions.animationFrameRate;\n this.animationQuality = recordOptions.animationQuality;\n }\n\n /**\n * Player UI is ready.\n * @private\n */\n setupUI() {\n // insert custom controls on left-side of controlbar\n this.player.controlBar.addChild(this.player.cameraButton);\n this.player.controlBar.el().insertBefore(\n this.player.cameraButton.el(),\n this.player.controlBar.el().firstChild);\n this.player.controlBar.el().insertBefore(\n this.player.recordToggle.el(),\n this.player.controlBar.el().firstChild);\n\n // get rid of unused controls\n if (this.player.controlBar.remainingTimeDisplay !== undefined) {\n this.player.controlBar.remainingTimeDisplay.el().style.display = 'none';\n }\n if (this.player.controlBar.liveDisplay !== undefined) {\n this.player.controlBar.liveDisplay.el().style.display = 'none';\n }\n\n // loop feature is never used in this plugin\n this.player.loop(false);\n\n // tweak player UI based on type\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // reference to videojs-wavesurfer plugin\n this.surfer = this.player.wavesurfer();\n break;\n\n case IMAGE_ONLY:\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n // customize controls\n this.player.bigPlayButton.hide();\n\n // loadedmetadata resets the durationDisplay for the\n // first time\n this.player.one('loadedmetadata', () => {\n // display max record time\n this.setDuration(this.maxLength);\n });\n\n // the native controls don't work for this UI so disable\n // them no matter what\n if (this.player.usingNativeControls_ === true) {\n if (this.player.tech_.el_ !== undefined) {\n this.player.tech_.el_.controls = false;\n }\n }\n\n // clicking or tapping the player video element should not try\n // to start playback\n this.player.removeTechControlsListeners_();\n\n if (this.player.options_.controls) {\n // progress control isn't used by this plugin\n this.player.controlBar.progressControl.hide();\n\n // prevent controlbar fadeout\n this.player.on('userinactive', (event) => {\n this.player.userActive(true);\n });\n\n // videojs automatically hides the controls when no valid 'source'\n // element is included in the video or audio tag. Don't. Ever again.\n this.player.controlBar.show();\n this.player.controlBar.el().style.display = 'flex';\n }\n break;\n }\n\n // disable time display events that constantly try to reset the current time\n // and duration values\n this.player.off('timeupdate');\n this.player.off('durationchange');\n this.player.off('loadedmetadata');\n\n // display max record time\n this.setDuration(this.maxLength);\n\n // hide play control\n this.player.controlBar.playToggle.hide();\n }\n\n /**\n * Indicates whether the plugin is currently recording or not.\n *\n * @return {boolean} Plugin currently recording or not.\n */\n isRecording() {\n return this._recording;\n }\n\n /**\n * Indicates whether the plugin is currently processing recorded data\n * or not.\n *\n * @return {boolean} Plugin processing or not.\n */\n isProcessing() {\n return this._processing;\n }\n\n /**\n * Indicates whether the plugin is destroyed or not.\n *\n * @return {boolean} Plugin destroyed or not.\n */\n isDestroyed() {\n return this.player && (this.player.children() === null);\n }\n\n /**\n * Open the browser's recording device selection dialog.\n */\n getDevice() {\n // define device callbacks once\n if (this.deviceReadyCallback === undefined) {\n this.deviceReadyCallback = this.onDeviceReady.bind(this);\n }\n if (this.deviceErrorCallback === undefined) {\n this.deviceErrorCallback = this.onDeviceError.bind(this);\n }\n if (this.engineStopCallback === undefined) {\n this.engineStopCallback = this.onRecordComplete.bind(this);\n }\n // ask the browser to give the user access to the media device\n // and get a stream reference in the callback function\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // setup microphone\n this.mediaType = {\n audio: (this.audioRecorderType === AUTO) ? true : this.audioRecorderType,\n video: false\n };\n // remove existing microphone listeners\n this.surfer.surfer.microphone.un('deviceReady',\n this.deviceReadyCallback);\n this.surfer.surfer.microphone.un('deviceError',\n this.deviceErrorCallback);\n\n // setup new microphone listeners\n this.surfer.surfer.microphone.on('deviceReady',\n this.deviceReadyCallback);\n this.surfer.surfer.microphone.on('deviceError',\n this.deviceErrorCallback);\n\n // disable existing playback events\n this.surfer.setupPlaybackEvents(false);\n\n // (re)set surfer liveMode\n this.surfer.liveMode = true;\n this.surfer.surfer.microphone.paused = false;\n\n // open browser device selection dialog\n this.surfer.surfer.microphone.start();\n break;\n\n case IMAGE_ONLY:\n case VIDEO_ONLY:\n // setup camera\n this.mediaType = {\n audio: false,\n video: (this.videoRecorderType === AUTO) ? true : this.videoRecorderType\n };\n navigator.mediaDevices.getUserMedia({\n audio: false,\n video: (this.getRecordType() === IMAGE_ONLY) ? this.recordImage : this.recordVideo\n }).then(\n this.onDeviceReady.bind(this)\n ).catch(\n this.onDeviceError.bind(this)\n );\n break;\n\n case AUDIO_VIDEO:\n // setup camera and microphone\n this.mediaType = {\n audio: (this.audioRecorderType === AUTO) ? true : this.audioRecorderType,\n video: (this.videoRecorderType === AUTO) ? true : this.videoRecorderType\n };\n navigator.mediaDevices.getUserMedia({\n audio: this.recordAudio,\n video: this.recordVideo\n }).then(\n this.onDeviceReady.bind(this)\n ).catch(\n this.onDeviceError.bind(this)\n );\n break;\n\n case ANIMATION:\n // setup camera\n this.mediaType = {\n // animated GIF\n audio: false,\n video: false,\n gif: true\n };\n navigator.mediaDevices.getUserMedia({\n audio: false,\n video: this.recordAnimation\n }).then(\n this.onDeviceReady.bind(this)\n ).catch(\n this.onDeviceError.bind(this)\n );\n break;\n }\n }\n\n /**\n * Invoked when the device is ready.\n * @private\n * @param stream: LocalMediaStream instance.\n */\n onDeviceReady(stream) {\n this._deviceActive = true;\n\n // store reference to stream for stopping etc.\n this.stream = stream;\n\n // hide device selection button\n this.player.deviceButton.hide();\n\n // reset time (e.g. when stopDevice was used)\n this.setDuration(this.maxLength);\n this.setCurrentTime(0);\n\n // hide play/pause control (e.g. when stopDevice was used)\n this.player.controlBar.playToggle.hide();\n\n // reset playback listeners\n this.off(this.player, 'timeupdate', this.playbackTimeUpdate);\n this.off(this.player, 'ended', this.playbackTimeUpdate);\n\n // setup recording engine\n if (this.getRecordType() !== IMAGE_ONLY) {\n // currently libvorbis.js, recorder.js, opus-recorder and lamejs\n // are only supported in audio-only mode\n if (this.getRecordType() !== AUDIO_ONLY &&\n (this.audioEngine === LIBVORBISJS ||\n this.audioEngine === RECORDERJS ||\n this.audioEngine === LAMEJS ||\n this.audioEngine === OPUSRECORDER)) {\n throw new Error('Currently ' + this.audioEngine +\n ' is only supported in audio-only mode.');\n }\n\n // get recorder class\n var EngineClass;\n switch (this.audioEngine) {\n case RECORDRTC:\n // RecordRTC.js (default)\n EngineClass = videojs.RecordRTCEngine;\n break;\n\n case LIBVORBISJS:\n // libvorbis.js\n EngineClass = videojs.LibVorbisEngine;\n break;\n\n case RECORDERJS:\n // recorder.js\n EngineClass = videojs.RecorderjsEngine;\n break;\n\n case LAMEJS:\n // lamejs\n EngineClass = videojs.LamejsEngine;\n break;\n\n case OPUSRECORDER:\n // opus-recorder\n EngineClass = videojs.OpusRecorderEngine;\n break;\n\n default:\n // unknown engine\n throw new Error('Unknown audioEngine: ' + this.audioEngine);\n }\n try {\n // connect stream to recording engine\n this.engine = new EngineClass(this.player, this.player.options_);\n }\n catch (err) {\n console.error(err);\n throw new Error('Could not load ' + this.audioEngine +\n ' plugin');\n }\n\n // listen for events\n this.engine.on('recordComplete', this.engineStopCallback);\n\n // audio settings\n this.engine.bufferSize = this.audioBufferSize;\n this.engine.sampleRate = this.audioSampleRate;\n this.engine.bitRate = this.audioBitRate;\n this.engine.audioChannels = this.audioChannels;\n this.engine.audioWorkerURL = this.audioWorkerURL;\n\n // mime type\n this.engine.mimeType = {\n video: this.videoMimeType,\n gif: 'image/gif'\n };\n if (this.audioMimeType !== null &&\n this.audioMimeType !== AUTO) {\n this.engine.mimeType.audio = this.audioMimeType;\n }\n\n // video/canvas settings\n this.engine.video = {\n width: this.videoFrameWidth,\n height: this.videoFrameHeight\n };\n this.engine.canvas = {\n width: this.videoFrameWidth,\n height: this.videoFrameHeight\n };\n\n // animated GIF settings\n this.engine.quality = this.animationQuality;\n this.engine.frameRate = this.animationFrameRate;\n\n // timeSlice\n if (this.recordTimeSlice && this.recordTimeSlice > 0) {\n this.engine.timeSlice = this.recordTimeSlice;\n this.engine.onTimeStamp = this.onTimeStamp.bind(this);\n }\n\n // initialize recorder\n this.engine.setup(this.stream, this.mediaType, this.debug);\n\n // show elements that should never be hidden in animation,\n // audio and/or video modus\n let uiElements = [this.player.controlBar.currentTimeDisplay,\n this.player.controlBar.timeDivider,\n this.player.controlBar.durationDisplay];\n uiElements.forEach((element) => {\n if (element !== undefined) {\n element.el().style.display = 'block';\n element.show();\n }\n });\n\n // show record button\n this.player.recordToggle.show();\n } else {\n // disable record indicator\n this.player.recordIndicator.disable();\n\n // setup UI for retrying snapshot (e.g. when stopDevice was\n // used)\n this.retrySnapshot();\n\n // reset and show camera button\n this.player.cameraButton.onStop();\n this.player.cameraButton.show();\n }\n\n // setup preview\n if (this.getRecordType() !== AUDIO_ONLY) {\n // show live preview\n this.mediaElement = this.player.el().firstChild;\n this.mediaElement.controls = false;\n\n // mute incoming audio for feedback loops\n this.mediaElement.muted = true;\n\n // hide the volume bar while it's muted\n this.displayVolumeControl(false);\n\n // load stream\n this.load(this.stream);\n\n // stream loading is async, so we wait until it's ready to play\n // the stream\n this.player.one('loadedmetadata', () => {\n // start stream\n this.mediaElement.play();\n\n // forward to listeners\n this.player.trigger('deviceReady');\n });\n } else {\n // forward to listeners\n this.player.trigger('deviceReady');\n }\n }\n\n /**\n * Invoked when an device error occurred.\n * @private\n */\n onDeviceError(code) {\n this._deviceActive = false;\n\n // store code\n this.player.deviceErrorCode = code;\n\n // forward error to player\n this.player.trigger('deviceError');\n }\n\n /**\n * Start recording.\n */\n start() {\n if (!this.isProcessing()) {\n this._recording = true;\n\n // hide play/pause control\n this.player.controlBar.playToggle.hide();\n\n // reset playback listeners\n this.off(this.player, 'timeupdate', this.playbackTimeUpdate);\n this.off(this.player, 'ended', this.playbackTimeUpdate);\n\n // start preview\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // disable playback events\n this.surfer.setupPlaybackEvents(false);\n\n // start/resume live audio visualization\n this.surfer.surfer.microphone.paused = false;\n this.surfer.liveMode = true;\n this.surfer.surfer.microphone.play();\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n // preview video stream in video element\n this.startVideoPreview();\n break;\n\n case ANIMATION:\n // hide the first frame\n this.player.recordCanvas.hide();\n\n // hide the animation\n this.player.animationDisplay.hide();\n\n // show preview video\n this.mediaElement.style.display = 'block';\n\n // for animations, capture the first frame\n // that can be displayed as soon as recording\n // is complete\n this.captureFrame().then((result) => {\n // start video preview **after** capturing first frame\n this.startVideoPreview();\n });\n break;\n }\n\n // start recording\n switch (this.getRecordType()) {\n case IMAGE_ONLY:\n // create snapshot\n this.createSnapshot();\n\n // notify UI\n this.player.trigger('startRecord');\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n // wait for media stream on video element to actually load\n this.player.one('loadedmetadata', () => {\n // start actually recording process\n this.startRecording();\n });\n break;\n\n default:\n // all resources have already loaded, so we can start\n // recording right away\n this.startRecording();\n }\n }\n }\n\n /**\n * Start recording.\n * @private\n */\n startRecording() {\n // register starting point\n this.paused = false;\n this.pauseTime = this.pausedTime = 0;\n this.startTime = new Date().getTime();\n\n // start countdown\n this.countDown = this.player.setInterval(\n this.onCountDown.bind(this), 100);\n\n // cleanup previous recording\n if (this.engine !== undefined) {\n this.engine.dispose();\n }\n\n // start recording stream\n this.engine.start();\n\n // notify UI\n this.player.trigger('startRecord');\n }\n\n /**\n * Stop recording.\n */\n stop() {\n if (!this.isProcessing()) {\n this._recording = false;\n this._processing = true;\n\n if (this.getRecordType() !== IMAGE_ONLY) {\n // notify UI\n this.player.trigger('stopRecord');\n\n // stop countdown\n this.player.clearInterval(this.countDown);\n\n // stop recording stream (result will be available async)\n if (this.engine) {\n this.engine.stop();\n }\n } else {\n if (this.player.recordedData) {\n // notify listeners that image data is (already) available\n this.player.trigger('finishRecord');\n }\n }\n }\n }\n\n /**\n * Stop device(s) and recording if active.\n */\n stopDevice() {\n if (this.isRecording()) {\n // stop stream once recorded data is available,\n // otherwise it'll break recording\n this.player.one('finishRecord', this.stopStream.bind(this));\n\n // stop recording\n this.stop();\n } else {\n // stop stream now, since there's no recorded data available\n this.stopStream();\n }\n }\n\n /**\n * Stop stream and device.\n */\n stopStream() {\n // stop stream and device\n if (this.stream) {\n this._deviceActive = false;\n\n if (this.getRecordType() === AUDIO_ONLY) {\n // make the microphone plugin stop it's device\n this.surfer.surfer.microphone.stopDevice();\n return;\n }\n this.stream.getTracks().forEach((stream) => {\n stream.stop();\n });\n }\n }\n\n /**\n * Pause recording.\n */\n pause() {\n if (!this.paused) {\n this.pauseTime = new Date().getTime();\n this.paused = true;\n\n this.engine.pause();\n }\n }\n\n /**\n * Resume recording.\n */\n resume() {\n if (this.paused) {\n this.pausedTime += new Date().getTime() - this.pauseTime;\n\n this.engine.resume();\n this.paused = false;\n }\n }\n\n /**\n * Invoked when recording completed and the resulting stream is\n * available.\n * @private\n */\n onRecordComplete() {\n // store reference to recorded stream data\n this.player.recordedData = this.engine.recordedData;\n\n // change the replay button back to a play button\n this.player.controlBar.playToggle.removeClass('vjs-ended');\n this.player.controlBar.playToggle.show();\n\n // notify listeners that data is available\n this.player.trigger('finishRecord');\n\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // pause player so user can start playback\n this.surfer.pause();\n\n // setup events for playback\n this.surfer.setupPlaybackEvents(true);\n\n // display loader\n this.player.loadingSpinner.show();\n\n // restore interaction with controls after waveform\n // rendering is complete\n this.surfer.surfer.once('ready', () => {\n this._processing = false;\n });\n\n // visualize recorded stream\n this.load(this.player.recordedData);\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n // pausing the player so we can visualize the recorded data\n // will trigger an async video.js 'pause' event that we\n // have to wait for.\n this.player.one('pause', () => {\n // video data is ready\n this._processing = false;\n\n // hide loader\n this.player.loadingSpinner.hide();\n\n // show stream total duration\n this.setDuration(this.streamDuration);\n\n // update time during playback and at end\n this.on(this.player, 'timeupdate',\n this.playbackTimeUpdate);\n this.on(this.player, 'ended',\n this.playbackTimeUpdate);\n\n // unmute local audio during playback\n if (this.getRecordType() === AUDIO_VIDEO) {\n this.mediaElement.muted = false;\n\n // show the volume bar when it's unmuted\n this.displayVolumeControl(true);\n }\n\n // load recorded media\n if (isChrome() && this.getRecordType() === AUDIO_VIDEO) {\n // use video property on Chrome\n this.load(this.player.recordedData.video);\n } else {\n this.load(this.player.recordedData);\n }\n });\n\n // pause player so user can start playback\n this.player.pause();\n break;\n\n case ANIMATION:\n // animation data is ready\n this._processing = false;\n\n // hide loader\n this.player.loadingSpinner.hide();\n\n // show animation total duration\n this.setDuration(this.streamDuration);\n\n // hide preview video\n this.mediaElement.style.display = 'none';\n\n // show the first frame\n this.player.recordCanvas.show();\n\n // pause player so user can start playback\n this.player.pause();\n\n // show animation on play\n this.on(this.player, 'play', this.showAnimation);\n\n // hide animation on pause\n this.on(this.player, 'pause', this.hideAnimation);\n break;\n }\n }\n\n /**\n * Invoked during recording and displays the remaining time.\n * @private\n */\n onCountDown() {\n if (!this.paused) {\n var now = new Date().getTime();\n var duration = this.maxLength;\n var currentTime = (now - (this.startTime + this.pausedTime)) / 1000;\n\n this.streamDuration = currentTime;\n\n if (currentTime >= duration) {\n // at the end\n currentTime = duration;\n\n // stop recording\n this.stop();\n }\n\n // update duration\n this.setDuration(duration);\n\n // update current time\n this.setCurrentTime(currentTime, duration);\n\n // notify listeners\n this.player.trigger('progressRecord');\n }\n }\n\n /**\n * Get the current time of the recorded stream during playback.\n *\n * Returns 0 if no recording is available (yet).\n */\n getCurrentTime() {\n let currentTime = isNaN(this.streamCurrentTime) ? 0 : this.streamCurrentTime;\n\n if (this.getRecordType() === AUDIO_ONLY) {\n currentTime = this.surfer.getCurrentTime();\n }\n\n return currentTime;\n }\n\n /**\n * Updates the player's element displaying the current time.\n *\n * @private\n * @param {number} [currentTime=0] - Current position of the\n * playhead (in seconds).\n * @param {number} [duration=0] - Duration in seconds.\n */\n setCurrentTime(currentTime, duration) {\n currentTime = isNaN(currentTime) ? 0 : currentTime;\n duration = isNaN(duration) ? 0 : duration;\n\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n this.surfer.setCurrentTime(currentTime, duration);\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n this.streamCurrentTime = Math.min(currentTime, duration);\n\n // update current time display component\n this.player.controlBar.currentTimeDisplay.formattedTime_ =\n this.player.controlBar.currentTimeDisplay.contentEl().lastChild.textContent =\n formatTime(this.streamCurrentTime, duration, this.msDisplayMax);\n break;\n }\n }\n\n /**\n * Get the length of the recorded stream in seconds.\n *\n * Returns 0 if no recording is available (yet).\n */\n getDuration() {\n let duration = isNaN(this.streamDuration) ? 0 : this.streamDuration;\n\n return duration;\n }\n\n /**\n * Updates the player's element displaying the duration time.\n *\n * @param {number} [duration=0] - Duration in seconds.\n * @private\n */\n setDuration(duration) {\n duration = isNaN(duration) ? 0 : duration;\n\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n this.surfer.setDuration(duration);\n break;\n\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n // update duration display component\n this.player.controlBar.durationDisplay.formattedTime_ =\n this.player.controlBar.durationDisplay.contentEl().lastChild.textContent =\n formatTime(duration, duration, this.msDisplayMax);\n break;\n }\n }\n\n /**\n * Start loading data.\n *\n * @param {(string|blob|file)} url - Either the URL of the media file,\n * a Blob, a File object or MediaStream.\n */\n load(url) {\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // visualize recorded Blob stream\n this.surfer.load(url);\n break;\n\n case IMAGE_ONLY:\n case VIDEO_ONLY:\n case AUDIO_VIDEO:\n case ANIMATION:\n if (url instanceof Blob || url instanceof File) {\n // assign blob using createObjectURL\n setSrcObject(url, this.mediaElement, false);\n } else {\n // assign stream without createObjectURL\n setSrcObject(url, this.mediaElement, true);\n }\n break;\n }\n }\n\n /**\n * Show save as dialog in browser so the user can store the recorded media\n * locally.\n *\n * @param {object} name - Object with one or more names for the particular\n * blob(s) you want to save. File extensions are added automatically.\n * For example: {'video': 'name-of-video-file'}. Supported keys are\n * 'audio', 'video' and 'gif'.\n */\n saveAs(name) {\n if (this.engine && name !== undefined) {\n this.engine.saveAs(name);\n }\n }\n\n /**\n * Destroy plugin only.\n *\n * Use `destroy` to remove the plugin and the player.\n */\n dispose() {\n // disable common event listeners\n this.player.off('ready');\n this.player.off('userinactive');\n this.player.off('loadedmetadata');\n\n // prevent callbacks if recording is in progress\n if (this.engine) {\n this.engine.dispose();\n this.engine.off('recordComplete', this.engineStopCallback);\n }\n\n // stop recording and device\n this.stop();\n this.stopDevice();\n\n // stop countdown\n this.player.clearInterval(this.countDown);\n\n // dispose wavesurfer.js\n if (this.getRecordType() == AUDIO_ONLY) {\n if (this.surfer) {\n // also disposes player\n this.surfer.destroy();\n }\n }\n\n this.resetState();\n\n super.dispose();\n }\n\n /**\n * Destroy plugin and players and cleanup resources.\n */\n destroy() {\n this.player.dispose();\n }\n\n /**\n * Reset the plugin.\n */\n reset() {\n // prevent callbacks if recording is in progress\n if (this.engine) {\n this.engine.dispose();\n this.engine.off('recordComplete', this.engineStopCallback);\n }\n\n // stop recording and device\n this.stop();\n this.stopDevice();\n\n // stop countdown\n this.player.clearInterval(this.countDown);\n\n // reset options\n this.loadOptions();\n\n // reset recorder state\n this.resetState();\n\n // reset record time\n this.setDuration(this.maxLength);\n this.setCurrentTime(0);\n\n // reset player\n this.player.reset();\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n if (this.surfer && this.surfer.surfer) {\n // empty last frame\n this.surfer.surfer.empty();\n }\n break;\n\n case IMAGE_ONLY:\n case ANIMATION:\n // reset UI\n this.player.recordCanvas.hide();\n this.player.cameraButton.hide();\n break;\n }\n\n // hide play control\n this.player.controlBar.playToggle.hide();\n\n // show device selection button\n this.player.deviceButton.show();\n\n // hide record button\n this.player.recordToggle.hide();\n\n // loadedmetadata resets the durationDisplay for the\n // first time\n this.player.one('loadedmetadata', () => {\n // display max record time\n this.setDuration(this.maxLength);\n });\n }\n\n /**\n * Reset the plugin recorder state.\n * @private\n */\n resetState() {\n this._recording = false;\n this._processing = false;\n this._deviceActive = false;\n this.devices = [];\n }\n\n /**\n * Get recorder type.\n */\n getRecordType() {\n return getRecorderMode(this.recordImage, this.recordAudio,\n this.recordVideo, this.recordAnimation);\n }\n\n /**\n * Create and display snapshot image.\n * @private\n */\n createSnapshot() {\n this.captureFrame().then((result) => {\n // turn the canvas data into base64 data with a PNG header\n this.player.recordedData = result.toDataURL('image/png');\n\n // hide preview video\n this.mediaElement.style.display = 'none';\n\n // show the snapshot\n this.player.recordCanvas.show();\n\n // stop recording\n this.stop();\n });\n }\n\n /**\n * Reset UI for retrying a snapshot image.\n * @private\n */\n retrySnapshot() {\n this._processing = false;\n\n // retry: hide the snapshot\n this.player.recordCanvas.hide();\n\n // show preview video\n this.player.el().firstChild.style.display = 'block';\n }\n\n /**\n * Capture frame from camera and copy data to canvas.\n * @private\n */\n captureFrame() {\n var detected = detectBrowser();\n var recordCanvas = this.player.recordCanvas.el().firstChild;\n\n // set the canvas size to the dimensions of the camera,\n // which also wipes the content of the canvas\n recordCanvas.width = this.player.width();\n recordCanvas.height = this.player.height();\n\n return new Promise((resolve, reject) => {\n // MediaCapture is only supported on:\n // - Chrome 60 and newer (see\n // https://github.com/w3c/mediacapture-image/blob/gh-pages/implementation-status.md)\n // - Firefox behind flag (https://bugzilla.mozilla.org/show_bug.cgi?id=888177)\n //\n // importing ImageCapture can fail when enabling chrome flag is still required.\n // if so; ignore and continue\n if ((detected.browser === 'chrome' && detected.version >= 60) &&\n (typeof ImageCapture === typeof Function)) {\n try {\n var track = this.stream.getVideoTracks()[0];\n var imageCapture = new ImageCapture(track);\n // take picture\n imageCapture.grabFrame().then((imageBitmap) => {\n // get a frame and copy it onto the canvas\n this.drawCanvas(recordCanvas, imageBitmap);\n\n // notify others\n resolve(recordCanvas);\n }).catch((error) => {\n // ignore, try oldskool\n });\n } catch(err) {}\n }\n // no ImageCapture available: do it the oldskool way\n\n // get a frame and copy it onto the canvas\n this.drawCanvas(recordCanvas, this.mediaElement);\n\n // notify others\n resolve(recordCanvas);\n });\n }\n\n /**\n * Draw image frame on canvas element.\n * @private\n */\n drawCanvas(canvas, element) {\n canvas.getContext('2d').drawImage(\n element, 0, 0,\n canvas.width,\n canvas.height\n );\n }\n\n /**\n * Start preview of video stream.\n * @private\n */\n startVideoPreview() {\n // disable playback events\n this.off('timeupdate');\n this.off('durationchange');\n this.off('loadedmetadata');\n this.off('play');\n\n // mute local audio\n this.mediaElement.muted = true;\n\n // hide volume control to prevent feedback\n this.displayVolumeControl(false);\n\n // start or resume live preview\n this.load(this.stream);\n this.mediaElement.play();\n }\n\n /**\n * Show animated GIF.\n * @private\n */\n showAnimation() {\n var animationDisplay = this.player.animationDisplay.el().firstChild;\n\n // set the image size to the dimensions of the recorded animation\n animationDisplay.width = this.player.width();\n animationDisplay.height = this.player.height();\n\n // hide the first frame\n this.player.recordCanvas.hide();\n\n // show the animation\n setSrcObject(this.player.recordedData, animationDisplay, false);\n this.player.animationDisplay.show();\n }\n\n /**\n * Hide animated GIF.\n * @private\n */\n hideAnimation() {\n // show the first frame\n this.player.recordCanvas.show();\n\n // hide the animation\n this.player.animationDisplay.hide();\n }\n\n /**\n * Update time during playback.\n * @private\n */\n playbackTimeUpdate() {\n this.setCurrentTime(this.player.currentTime(),\n this.streamDuration);\n }\n\n /**\n * Received new timestamp (when timeSlice option is enabled).\n * @private\n */\n onTimeStamp(current, all) {\n this.player.currentTimestamp = current;\n this.player.allTimestamps = all;\n\n // get blob (only for MediaStreamRecorder)\n var internal;\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n internal = this.engine.engine.audioRecorder;\n break;\n\n case ANIMATION:\n internal = this.engine.engine.gifRecorder;\n break;\n\n default:\n internal = this.engine.engine.videoRecorder;\n }\n internal = internal.getInternalRecorder();\n if ((internal instanceof MediaStreamRecorder) === true) {\n this.player.recordedData = internal.getArrayOfBlobs();\n\n // inject file info for newest blob\n this.engine.addFileInfo(\n this.player.recordedData[this.player.recordedData.length - 1]);\n }\n\n // notify others\n this.player.trigger('timestamp');\n }\n\n /**\n * Collects information about the media input and output devices\n * available on the system.\n *\n * Returns an array.\n */\n enumerateDevices() {\n if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {\n this.player.enumerateErrorCode = 'enumerateDevices() not supported.';\n this.player.trigger('enumerateError');\n return;\n }\n\n // List cameras and microphones.\n navigator.mediaDevices.enumerateDevices(this).then((devices) => {\n this.devices = [];\n devices.forEach((device) => {\n this.devices.push(device);\n });\n\n // notify listeners\n this.player.trigger('enumerateReady');\n }).catch((err) => {\n this.player.enumerateErrorCode = err;\n this.player.trigger('enumerateError');\n });\n }\n\n /**\n * Change the audio output device.\n *\n * @param {string} deviceId - Id of audio output device.\n */\n setAudioOutput(deviceId) {\n let errorMessage;\n\n switch (this.getRecordType()) {\n case AUDIO_ONLY:\n // use wavesurfer\n this.surfer.surfer.setSinkId(deviceId).then((result) => {\n // notify listeners\n this.player.trigger('audioOutputReady');\n return;\n }).catch((err) => {\n errorMessage = err;\n });\n break;\n\n default:\n let element = player.tech_.el_;\n if (deviceId) {\n if (typeof element.sinkId !== 'undefined') {\n element.setSinkId(deviceId).then((result) => {\n // notify listeners\n this.player.trigger('audioOutputReady');\n return;\n }).catch((err) => {\n errorMessage = err;\n });\n } else {\n errorMessage = 'Browser does not support audio output device selection.';\n }\n } else {\n errorMessage = 'Invalid deviceId: ' + deviceId;\n }\n break;\n }\n\n // error if we get here: notify listeners\n this.player.trigger('error', errorMessage);\n }\n\n /**\n * Show or hide the volume menu.\n *\n * @private\n * @param {boolean} display - Hide/show volume control.\n */\n displayVolumeControl(display) {\n if (this.player.controlBar.volumePanel !== undefined) {\n if (display === true) {\n display = 'flex';\n } else {\n display = 'none';\n }\n this.player.controlBar.volumePanel.el().style.display = display;\n }\n }\n}\n\n// version nr is injected during build\nRecord.VERSION = __VERSION__;\n\n// register plugin\nvideojs.Record = Record;\nif (videojs.getPlugin('record') === undefined) {\n videojs.registerPlugin('record', Record);\n}\n\n// export plugin\nmodule.exports = {\n Record\n};\n"],"sourceRoot":""}