Skip to content

Instantly share code, notes, and snippets.

@semanticentity
Last active May 5, 2025 16:46
Show Gist options
  • Save semanticentity/796077fd21e3f7ac1dcea953322d4a31 to your computer and use it in GitHub Desktop.
Save semanticentity/796077fd21e3f7ac1dcea953322d4a31 to your computer and use it in GitHub Desktop.
LEWM: Loom, Except Without Money
javascript:(async function(){
if(!navigator.mediaDevices||!navigator.mediaDevices.getDisplayMedia){
alert("Screen recording not supported");
return;
}
var filename = prompt("Make sure you are in a tab other than the one you are recording.\nEnter filename (no extension):","lewm-recording");
if(!filename) filename = "lewm-recording";
alert("Select a TAB and check 'Share tab audio' in the popup. For audio, do NOT chose full screen or window.");
try{
var stream = await navigator.mediaDevices.getDisplayMedia({
video: true,
audio: true
});
var chunks = [];
var recorder = new MediaRecorder(stream, {
mimeType: "video/webm;codecs=vp9"
});
recorder.ondataavailable = function(e){
if(e.data.size > 0) chunks.push(e.data);
};
recorder.onstop = function(){
var blob = new Blob(chunks, {type:"video/webm"});
var url = URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = url;
a.download = filename + ".webm";
a.click();
document.body.removeChild(stopBtn);
};
var stopBtn = document.createElement("button");
stopBtn.textContent = "Stop Recording";
stopBtn.style.position = "fixed";
stopBtn.style.top = "10px";
stopBtn.style.right = "10px";
stopBtn.style.zIndex = 2147483647;
stopBtn.style.padding = "10px";
stopBtn.style.background = "#f00";
stopBtn.style.color = "#fff";
stopBtn.style.fontSize = "16px";
stopBtn.style.border = "none";
stopBtn.style.borderRadius = "4px";
stopBtn.style.boxShadow = "0 2px 4px rgba(0,0,0,0.3)";
stopBtn.onclick = function(){
stopBtn.style.top = "-1000px";
stopBtn.style.left = "-1000px";
setTimeout(function(){
recorder.stop();
stream.getTracks().forEach(function(track){ track.stop(); });
}, 100);
};
document.body.appendChild(stopBtn);
recorder.start();
} catch(err){
alert("Error: " + err);
}
})();
@semanticentity
Copy link
Author

semanticentity commented May 4, 2025

   ██╗     ███████╗██╗    ██╗███╗   ███╗  Loom, Except Without Money
   ██║     ██╔════╝██║    ██║████╗ ████║  LEWM is a simple bookmarklet that lets you record video
   ██║     █████╗  ██║ █╗ ██║██╔████╔██║  and audio from the active browser tab. It uses the built-in
   ██║     ██╔══╝  ██║███╗██║██║╚██╔╝██║  mediaDevices API in modern browsers. All work happens
   ███████╗███████╗╚███╔███╔╝██║ ╚═╝ ██║  locally in your browser. No server or external service is needed.
   ╚══════╝╚══════╝ ╚══╝╚══╝ ╚═╝     ╚═╝

Sorry, Loom.

Setup

  1. Create a new bookmark in your browser
  2. Edit the bookmark, name it "lewm"
  3. Paste the code snippet into the URL field
  4. Save the bookmark

Usage

  1. Open or switch to a different tab from the one you want to record

  2. Click the LEWM bookmark from your bookmarks bar

  3. Enter the output filename when prompted

  4. In the screen picker, select a tab and check Share tab audio

    • Audio will not record if you choose window or full screen
  5. When finished, click Stop Recording in the top-right corner

  6. Your recording will download automatically as a .webm file

How it works

LEWM uses getDisplayMedia to request a video/audio stream from a selected tab.
MediaRecorder gathers the data in chunks. When recording stops, it collects the data
into a single .webm blob and triggers a download. A temporary button lets you stop
recording and cleans up after.

Replicate Loom Features (Manually)

LEWM doesn't share, host, or transcode your video. For that, use your own tools or cloud storage.

Or pay Loom $180/year: https://x.com/nico_jeannen/status/1918640439265206680

LEWM gives you the core: local video + audio capture. The rest is DIY using free tools.

Share videos via link

  • Upload the .webm file to Google Drive, Dropbox, or OneDrive
  • Set file permissions to "Anyone with the link can view"
  • Send the link

Speed up video playback

  • Most browsers support right-click > Playback speed
  • You can also open the file in VLC or upload to YouTube (unlisted)

Auto-captions + edits

  • Upload to YouTube
  • YouTube auto-generates subtitles
  • Edit captions in YouTube Studio under the Subtitles tab

LEWM FAQ

Q: Does this work on mobile?
A: No. But neither does editing video on a phone, so you're fine.

Q: Can it export to MP4?
A: Only if your browser is a time traveler. Convert with ffmpeg or let YouTube handle it.

Q: Where does the video go?
A: Nowhere. It stays on your machine. LEWM records, saves, and disappears like a polite ghost.

@semanticentity
Copy link
Author

javascript:(async function(){if(!navigator.mediaDevices||!navigator.mediaDevices.getDisplayMedia){alert("Screen recording not supported");return;}var filename=prompt("Make sure you are in a tab other than the one you are recording.\nEnter filename (no extension):","lewm-recording");if(!filename)filename="lewm-recording";alert("Select a TAB and check 'Share tab audio' in the popup. For audio, do NOT chose full screen or window.");try{var stream=await navigator.mediaDevices.getDisplayMedia({video:true,audio:true});var chunks=[];var recorder=new MediaRecorder(stream,{mimeType:"video/webm;codecs=vp9"});recorder.ondataavailable=function(e){if(e.data.size>0)chunks.push(e.data);};recorder.onstop=function(){var blob=new Blob(chunks,{type:"video/webm"});var url=URL.createObjectURL(blob);var a=document.createElement("a");a.href=url;a.download=filename+".webm";a.click();document.body.removeChild(stopBtn);};var stopBtn=document.createElement("button");stopBtn.textContent="Stop Recording";stopBtn.style.position="fixed";stopBtn.style.top="10px";stopBtn.style.right="10px";stopBtn.style.zIndex=2147483647;stopBtn.style.padding="10px";stopBtn.style.background="#f00";stopBtn.style.color="#fff";stopBtn.style.fontSize="16px";stopBtn.style.border="none";stopBtn.style.borderRadius="4px";stopBtn.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)";stopBtn.onclick=function(){stopBtn.style.top="-1000px";stopBtn.style.left="-1000px";setTimeout(function(){recorder.stop();stream.getTracks().forEach(function(track){track.stop();});},100);};document.body.appendChild(stopBtn);recorder.start();}catch(err){alert("Error: "+err);}})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment