StreamableDownloader

Downloads the current Streamable video when you click the button.

  1. // ==UserScript==
  2. // @name StreamableDownloader
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.3.2
  5. // @description Downloads the current Streamable video when you click the button.
  6. // @author Contrapunctus-XIV
  7. // @match *://streamable.com/*
  8. // @icon https://cdn0.iconfinder.com/data/icons/ui-line-pixel-perfect-3/32/user_interface_UI_line_download_unduh_media_ui-512.png
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. const DELAY = 850;
  13.  
  14. (function() {
  15. 'use strict'
  16. const videoID = window.location.href.split('/')[3];
  17. const bar = document.querySelector('#player-' + videoID +'-info > div.flex.gap-3');
  18. const btn = document.createElement('button');
  19.  
  20. const handleClick = (event) => {
  21. const videoURL = document.getElementsByTagName('video')[0].getElementsByTagName('source')[0].getAttribute('src');
  22. if (videoURL.includes('cdn-cf-east.streamable.com')) {
  23. window.location.href = videoURL;
  24. }
  25. else {
  26. alert('Your download will begin in a few seconds');
  27.  
  28. fetch(videoURL).then(response => { return response.blob(); })
  29. .then(blob => {
  30. var urlCreator = window.URL || window.webkitURL;
  31. var videoLink = urlCreator.createObjectURL(blob);
  32. var tag = document.createElement('a');
  33. tag.href = videoLink;
  34. tag.target = '_blank';
  35. tag.download = videoID + '.mp4';
  36. document.body.appendChild(tag);
  37. tag.click();
  38. document.body.removeChild(tag);
  39. })
  40. .catch(err => {
  41. alert('ERROR : Failed to download the video. Please try again. \n If it still doesn\'t work, you can contact the script author on greatest.deepsurf.us with the video URL.');
  42. });
  43. }
  44. }
  45. btn.setAttribute('class', "below-video__video-actions__cta js-download-btn tw-box-border tw-inline-flex tw-flex-row tw-flex-nowrap tw-justify-center tw-items-center tw-font-semibold tw-relative after:tw-content-[''] after:tw-block after:tw-w-full after:tw-h-full after:tw-absolute after:tw-top-0 after:tw-left-0 after:tw-opacity-0 after:tw-transition-opacity disabled:tw-border-gray-100 disabled:tw-text-gray-700/38 disabled:after:tw-hidden dark:disabled:tw-text-gray-300/38 disabled:tw-text-label-tertiary tw-shadow-sm disabled:tw-bg-gray-100 dark:disabled:tw-bg-gray-700 disabled:tw-bg-surface-tertiary tw-bg-brand-secondary tw-text-gray-700 after:tw-bg-gray-700 hover:after:tw-opacity-8 active:after:tw-opacity-8 focus:after:tw-opacity-8 dark:tw-bg-brand-secondary-dark-mode dark:tw-text-gray-300 dark:after:tw-bg-gray-300 child:tw-fill-black child:dark:tw-fill-gray-300 tw-text-base tw-rounded tw-h-9 after:tw-rounded tw-px-3 tw-gap-1");
  46. btn.addEventListener('click', handleClick);
  47.  
  48. const img_download = document.createElement('span');
  49. img_download.setAttribute('class', 'material-icons -ml-1 -mt-0.5');
  50. img_download.textContent = 'download';
  51.  
  52. const txt_download = document.createElement('span');
  53. txt_download.textContent = 'Download';
  54.  
  55. btn.appendChild(img_download);
  56. btn.appendChild(txt_download);
  57.  
  58. setTimeout(function() {
  59. bar.appendChild(btn);
  60. }, DELAY);
  61. })();