Streamable Video


Streamable Video -1; if ((chrome) && (safari)) safari = false; return safari || iOS } function copyTextToClipboard(text) { var textArea = document.createElement(“textarea”); // Place in top-left corner of screen regardless of scroll position. textArea.style.position = ‘fixed’; textArea.style.top = 0; textArea.style.left = 0; // Ensure it has a small width and height. Setting to 1px / 1em // doesn’t work as this gives a negative w/h on some browsers. textArea.style.width = ‘2em’; textArea.style.height = ‘2em’; // We don’t need padding, reducing the size if it does flash render. textArea.style.padding = 0; // Clean up any borders. textArea.style.border = ‘none’; textArea.style.outline = ‘none’; textArea.style.boxShadow = ‘none’; // Avoid flash of white box if rendered for any reason. textArea.style.background = ‘transparent’; textArea.value = text; document.body.appendChild(textArea); textArea.select(); try { var successful = document.execCommand(‘copy’); var msg = successful ? ‘successful’ : ‘unsuccessful’; log(‘Copying text command was ‘ + msg); } catch (err) { log(‘Oops, unable to copy’); } document.body.removeChild(textArea); } VideoPlayer = function(video, player, id, options) { this.options = options || {}; this.video = video; this.player = player; this.id = id; this.onTimeUpdate = this.onTimeUpdate.bind(this) this.onProgress = this.onProgress.bind(this) this.update_player_controls = this.update_player_controls.bind(this) this.update_player_controls_loop = this.update_player_controls_loop.bind(this) this.update_player_progress = this.update_player_progress.bind(this) this.bufferCheckInterval = null; this.client_data = {}; this.onFullScreenChange = this.onFullScreenChange.bind(this) this.session_id = session || Math.random().toString(36).substr(2, 16); this.saveVolume = true this.isMobile = isMobile() this.isAndroid = isAndroid() }; VideoPlayer.prototype.setupMediaSession = function() { try { const artwork = [] if (this.video.poster_url) { artwork.push({ src: this.video.poster_url, sizes: `${this.video.width}x${this.video.height}`, type: ‘image/jpg’ }) } if (this.video.thumbnail_url) { artwork.push({ src: this.video.thumbnail_url, sizes: `${this.video.width}x${this.video.height}`, type: ‘image/jpg’ }) } if (‘mediaSession’ in navigator) { navigator.mediaSession.metadata = new MediaMetadata({ title: this.video.title || ‘Streamable Video’, artwork: artwork }); } } catch (e) { console.log(“Failed to set up media session.”, e) } } VideoPlayer.prototype.recordStat = function(name, data) { data = data || {}; data.type = name; data.shortcode = this.video.shortcode; data.timestamp = Math.floor(Date.now() / 1000); data.id = this.session_id; //cookie loaded in common data.referrer = encodeURIComponent(document.referrer) data.embedid = this.id for (var a in this.client_data ) { data[a] = this.client_data[a]; } data.ad = data.ad ? data.ad.tag : null window.STM_TRANSPORT.push(data) } VideoPlayer.prototype.onFullScreenChange = function () { if (screenfull.isFullscreen) { addClass(this.playerDiv, “fullscreen”); } else { removeClass(this.playerDiv, “fullscreen”); } }; VideoPlayer.prototype.initialize = function() { var self = this; var video = this.video; this.scrubTime = null var files = video.files; var bufferingDetected = null; var player = this.player; var playerDiv = this.player.parentNode; this.playerDiv = playerDiv; this.spinner = playerDiv.getElementsByClassName(‘player-spinner’)[0]; this.paused = !this.started this.lastTime = null; this.lastReportedLoop = -1; this.lastProgressReport = 0; this.loops = 0; this.settingsOpen = false; document.body.addEventListener(“keyup”, this.onKeyPress.bind(this)); this.setupMediaSession(); var playPauseInput = document.getElementById(‘player-play-pause-button-input’) if (player.hasAttribute(‘autoplay’)) { //force autoplay this.play(); } if (userInteractionRequired()) { removeClass(playerDiv, “playing”); } var playing = false; player.onpause = function() { if (self.scrubTime) return; if (playPauseInput) { playPauseInput.checked = true; } } player.onplay = function() { if (playPauseInput) { playPauseInput.checked = false; } if (playOverlay) { playOverlay.style.display = “none” } playing = true; self.paused_ = false self.started = true }; player.oncanplay = function() { if (self.spinner) { self.spinner.style.display = ‘none’; } setTimeout(function() { if (!playing && !self.paused) { log(“Video can play, forcing play”) onUserActivity() self.play() } }, 100); }; var menu = document.getElementById(‘context-menu’); menu.addEventListener(“mousedown”, function(e) { e.stopPropagation(); }); var closeContextMenu = function(e) { if (e) { e.stopPropagation(); e.preventDefault(); } menu.style.display = “none”; self.player.removeEventListener(“mousedown”, closeContextMenu); document.removeEventListener(“mousedown”, closeContextMenu); } var downloadButton = document.getElementById(“download”) if (downloadButton) { downloadButton.addEventListener(“click”, function() { closeContextMenu(); }) } var copyUrlButton = document.getElementById(“copyurl”) if (copyUrlButton) { copyUrlButton.addEventListener(“click”, function() { copyTextToClipboard(“https://streamable.com/” + self.video.shortcode); closeContextMenu(); }) } var copyEmbedButton = document.getElementById(“copyembed”) if (copyEmbedButton) { copyEmbedButton.addEventListener(“click”, function() { self.copyEmbedCodeToClipboard(); closeContextMenu(); }) } var speedButtons = document.getElementsByClassName(‘speed-button’); for (var i = 0; i < speedButtons.length; i++) { var speedButton = speedButtons[i]; speedButton.addEventListener("click", function(e) { var speed = parseFloat(e.target.getAttribute("data-speed")) player.playbackRate = speed for (var x = 0; x < speedButtons.length; x++) { var sb2 = speedButtons[x]; removeClass(sb2, "active"); } addClass(e.target, "active"); player.play() }) } var downloadButtons = document.getElementsByClassName('download-button'); for (var i = 0; i < downloadButtons.length; i++) { var downloadButton = downloadButtons[i]; downloadButton.addEventListener("click", function(e) { var url = e.target.getAttribute("data-url") if (!url) { url = 'https://ajax.streamable.com/videos/' + video.shortcode + '/download' } window.open(url, 'Download') }) } var fullScreenButton = playerDiv.getElementsByClassName('player-fullscreen-button')[0]; var settingsButton = playerDiv.getElementsByClassName('player-settings-button')[0]; var settingsOverlay = playerDiv.getElementsByClassName('player-settings-overlay')[0]; var playButton = document.getElementById('play-button') var playOverlay = document.getElementById('play-overlay') if (this.isMobile && this.options.noControls) { player.addEventListener('click', function(){ if (player.paused) { this.play(); } else { this.pause(); } }); } playerDiv.onmousemove = function(e) { self.mouseOverControls = playerDiv.clientHeight - e.clientY self.player.offsetWidth) { menu.style.left = e.offsetX - 200 + "px"; } else { menu.style.left = e.offsetX + "px"; } if (e.offsetY + 150 > self.player.offsetHeight) { menu.style.top = e.offsetY – 150 + “px”; } else { menu.style.top = e.offsetY + “px”; } menu.style.display = “block”; } e.preventDefault(); return false; } if (playButton) { playButton.addEventListener(‘contextmenu’, showContextMenu); } this.player.addEventListener(‘contextmenu’, showContextMenu); player.addEventListener(“timeupdate”, self.onTimeUpdate); player.addEventListener(“progress”, self.onProgress); player.addEventListener(“canplaythrough”, self.onProgress); var vol = parseFloat(getCookie(“volume”) || .51); var muted = getCookie(“muted”) || “false”; if (vol) { player.volume = vol; } if (muted == “true”) { player.muted = muted; } player.addEventListener(“error”, function(e) { var code = -1; if (e.target.error && e.target.error.code) { code = e.target.error.code; } self.recordStat(“error”, { code: code, src: e.target.src, networkState: player.networkState, currentTime: player.currentTime, readyState: player.readyState, type: ‘video’ }) }); var loadedMetadata = function() { if (self.scrubTime != null) { player.currentTime = self.scrubTime; self.scrubTime = null; } var time = getQueryVariable(‘t’); if (time) { player.currentTime = time; } if (!self.isMobile) { window.requestAnimationFrame(self.update_player_progress); } } if (player.duration) { loadedMetadata() } else { player.addEventListener(“loadedmetadata”, loadedMetadata); } player.onvolumechange = function() { if (player.hasAttribute(“muted”)) { return; } if (self.saveVolume) { if (!player.muted) { setCookie(“volume”, player.volume); } setCookie(“muted”, player.muted); } self.update_player_controls(); }; var activityTimeout = null; var setHideTimeout = function(duration) { duration = duration || 2000; activityTimeout = setTimeout(function() { if (self.settingsOpen || self.mouseOverControls) { setHideTimeout(); return; } if (self.scrubTime != null) { return; } removeClass(playerDiv, “user-activity”); }, duration) } var onUserActivity = function(e) { if (!self.started) { return } if (activityTimeout) { clearTimeout(activityTimeout); } if (self.options.noControls) { return } addClass(playerDiv, “user-activity”); setHideTimeout(); } setHideTimeout(); var watermarkShown = false; player.addEventListener(“playing”, function(e) { canShowBuffering = true; if (!watermarkShown) { var watermarkContainers = playerDiv.getElementsByClassName(‘watermark’); for (var i = 0; i < watermarkContainers.length; i++) { var watermark = watermarkContainers[i] if (watermark.getAttribute('data-animated')) { watermark.style.right = '-120px' setTimeout(function() { watermark.style.visibility = 'visible' var right = watermark.getAttribute('data-right'); if (!right) { right = '10px'; } watermark.style.right = right; }, 500); } else { watermark.style.visibility = 'visible' } } watermarkShown = true; } }) if (this.isMobile) { if (this.isAndroid) { var settingsButtonMobile = playerDiv.getElementsByClassName('player-settings-button-mobile')[0]; var settingsOverlayMobile = playerDiv.getElementsByClassName('player-settings-overlay-mobile')[0]; var settingsButtonMobileClose = playerDiv.getElementsByClassName('player-settings-button-mobile-close')[0]; playerDiv.addEventListener("touchstart", onUserActivity); if (settingsButtonMobile) { settingsButtonMobile.onclick = function(e) { settingsOverlayMobile.style.display = "block"; } settingsButtonMobileClose.onclick = function(e) { settingsOverlayMobile.style.display = "none"; } var qualityOptions = playerDiv.getElementsByClassName('player-settings-quality-option-mobile'); for (var i = 0; i < qualityOptions.length; i++) { qualityOptions[i].onclick = function(e) { var preset = e.target.getAttribute("data-quality") e.stopPropagation(); e.preventDefault(); for (var i2 = 0; i2 lastPlayPos && !player.paused) { self.spinner.style.display = 'none'; bufferingDetected = false; } lastPlayPos = player.currentTime }, 500.0); player.addEventListener("playing", function(e) { canShowBuffering = true; }) this.update_player_controls_loop(); //this must be click for ie if (fullScreenButton) { fullScreenButton.onclick = function(e) { hideSettings(); if (screenfull.isEnabled) { screenfull.toggle(playerDiv); setTimeout(function() { player.style.maxHeight = document.body.offsetHeight + "px"; }, 1000); } } fullScreenButton.onmousedown = function(e) { e.stopPropagation(); } } if (settingsButton) { settingsButton.onclick = function(e) { if (self.settingsOpen) { removeClass(settingsButton, 'open') settingsOverlay.style.display = "none"; } else { addClass(settingsButton, 'open') settingsOverlay.style.display = "block"; } self.settingsOpen = !self.settingsOpen; } var qualityOptions = playerDiv.getElementsByClassName('player-settings-quality-option'); for (var i = 0; i < qualityOptions.length; i++) { qualityOptions[i].onmousedown = function(e) { e.stopPropagation(); e.preventDefault(); } qualityOptions[i].onclick = function(e) { e.stopPropagation(); e.preventDefault(); for (var i2 = 0; i2 < qualityOptions.length; i2++) { removeClass(qualityOptions[i2], "checked"); } addClass(e.target, "checked"); var currentTime = self.player.currentTime; var preset = e.target.getAttribute("data-quality") self.player.src = files[preset].url self.player.currentTime = currentTime; self.player.play() hideSettings(); } } } playerDiv.addEventListener("mousemove", onUserActivity); this.player.addEventListener("mousedown", function(e) { onUserActivity(e); var button = e.which || e.button; if (button == 3) { return; } if (hideSettings()) { return; } if (player.paused) { var promise = player.play() if (promise !== undefined) { promise.then(function() { }).catch(function(err) { console.log("Play blocked: " + err) }); } self.update_player_controls(); } else { player.pause(); self.update_player_controls(); } }) if (screenfull.isEnabled) { document.addEventListener(screenfull.raw.fullscreenchange, self.onFullScreenChange) } else { if (fullScreenButton) { fullScreenButton.style.display = "none"; } } if (playPauseInput) { playPauseInput.onchange = function(e) { if (e.target.checked) { player.pause(); } else { player.play(); } } } var muteButton = playerDiv.getElementsByClassName('player-mute-button')[0]; if (muteButton) { muteButton.onmousedown = function(e) { hideSettings(); if (player.muted) { player.muted = false; } else { player.muted = true; } e.stopPropagation(); } } var wasPaused; var handleMouseMove = function(e) { log("Mouse move pause") player.pause(); var newTime = calculateDistance(e, playerDiv.getElementsByClassName('player-progress')[0]) * player.duration; // Don't let video end while scrubbing. if (newTime === player.duration) { newTime = newTime - 0.1; } if (!isNaN(newTime)) { // Set new time (tell player to seek to new time) player.currentTime = newTime; self.scrubTime = newTime; } self.update_player_controls(); } var handleMouseUp = function(e) { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); document.removeEventListener("touchmove", handleMouseMove); document.removeEventListener("touchend", handleMouseUp); self.scrubTime = null; if (!wasPaused) { log("Playing after progress change") player.play() var promise = player.play() if (promise !== undefined) { promise.then(function() { }).catch(function(err) { console.log("Play blocked: " + err) }); } } } var progressBar = playerDiv.getElementsByClassName('player-progress')[0] var progressBarHover = document.getElementById('player-progress-hover') var progressBarTrackHover = document.getElementById('player-progress-value-hover') progressBar.onmousedown = function(e) { hideSettings(); wasPaused = player.paused; document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); document.addEventListener("touchmove", handleMouseMove); document.addEventListener("touchend", handleMouseUp); handleMouseMove(e); //so we don't trigger mousedown on player e.stopPropagation(); } progressBar.onmousemove = function(e) { var newTime = calculateDistance(e, progressBar) * player.duration; // Don't let video end while scrubbing. if (newTime === player.duration) { newTime = newTime - 0.1; } if (!isNaN(newTime)) { var percent = newTime / player.duration * 100; var left = newTime / player.duration * progressBar.offsetWidth; var right = progressBar.offsetWidth - left; if (left < 100) { progressBarHover.style.right = null; progressBarHover.style.left = left - (percent / 2) + "px"; progressBarHover.style.textAlign = "left" } else if (right < 100) { progressBarHover.style.left = null; progressBarHover.style.right = right - (50 - percent / 2) + "px"; progressBarHover.style.textAlign = "right" } else { progressBarHover.style.right = null; progressBarHover.style.left = (left - 50) + "px"; progressBarHover.style.textAlign = "center" } var minutes = Math.floor(newTime / 60) var seconds = Math.round(newTime - minutes * 60) if (seconds 100) { width = 100; } progressBarTrackHover.style.width = width + "%"; progressBarTrackHover.style.opacity = 1 } else { progressBarHover.style.opacity = 0 progressBarTrackHover.style.opacity = 0 } } progressBar.onmouseleave = function(e) { progressBarHover.style.opacity = 0 progressBarTrackHover.style.opacity = 0 } var volumeBar = playerDiv.getElementsByClassName('player-volume')[0]; if (volumeBar) { var handleVolumeMouseMove = function(e) { var distance = calculateDistance(e, volumeBar); if (distance 1) volume = 1; this.player.volume = volume; this.player.muted = false; } else if (e.keyCode == 40) { var volume = this.player.volume - .1; if (volume this.player.duration || time this.player.duration || time = 48 && e.keyCode <= 57) { if (!this.player.duration) return; var percent = (e.keyCode - 48) / 10; this.player.currentTime = percent * this.player.duration } } VideoPlayer.prototype.copyEmbedCodeToClipboard = function(source) { var self = this; var padding = (self.video.height / self.video.width * 100).toFixed(3); if (self.video.shortcode) { var code = ''; } else { var code = ''; } copyTextToClipboard(code); } VideoPlayer.prototype.onProgress = function(e) { this.updateBuffered() } VideoPlayer.prototype.updateBuffered = function(e) { var loaded = 0 for (var i = 0; i = 30) { reportProgress(player.seeking); } //ignore if seeking, unless its a loop if (player.seeking && player.currentTime != 0) { self.lastTime = player.currentTime; return; } if (self.spinner && player.currentTime != 0) { self.spinner.style.display = "none"; } //reset on returning to beginning if (self.lastTime > player.currentTime && player.currentTime == 0) { self.loops += 1; self.lastTime = null; } //if we returned to beginning, or it’s been 5 seconds if (self.loops > self.lastReportedLoop) { if (self.loops <= 10) { self.recordStat("play", { loops: self.loops, progress: player.duration ? (player.currentTime / player.duration).toFixed(2) : 0 }) self.lastReportedLoop = self.loops; } self.lastProgressReport = player.currentTime; } self.update_player_controls(); self.lastTime = player.currentTime; } VideoPlayer.prototype.update_player_controls_loop = function() { var player = this.player var self = this setTimeout(function() { self.update_player_controls(); self.update_player_controls_loop(); }, 2000); }; VideoPlayer.prototype.update_player_controls = function() { var player = this.player var playerDiv = this.playerDiv var muteButton = playerDiv.getElementsByClassName('player-mute-button')[0]; if (muteButton) { removeClass(muteButton, "muted"); removeClass(muteButton, "low"); if (player.muted) { addClass(muteButton, "muted"); } else if (player.volume 100) { width = 100; } progressBar.style.width = width + "%"; } window.requestAnimationFrame(self.update_player_progress); } VideoPlayer.prototype.pause = function() { log('Pausing'); this.paused_ = true this.player.pause(); } VideoPlayer.prototype.setVolume = function(volume, save) { log('Set volume ' + volume.toString() + " save: " + save.toString()); // don't store if we're silently muting if (volume || save) { this.player.volume = volume } if (volume == 0) { this.player.muted = true; } else { this.player.muted = false; } this.saveVolume = save setTimeout(function() { self.saveVolume = true }, 100) } // returns whether player should pause for ad VideoPlayer.prototype.adOpportunity = function() { if (window.STM_PLAYERS) { for (var i = 0; i window.innerHeight – padding) { height = window.innerHeight – padding; var MIN_HEIGHT = 140; var minHeight = h < MIN_HEIGHT ? h : MIN_HEIGHT; if (height 800 && window.innerWidth
Source

Leave a Reply