Created
January 18, 2025 03:52
-
-
Save coryvirok/40e610f12d0fdd23cc074d7e08e4be80 to your computer and use it in GitHub Desktop.
Download embedded videos in your browser (even blob: sources)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function addDownloadButtonsToVideos() { | |
const addButton = (video) => { | |
// Check if a download button already exists for this video | |
if (video.parentElement.querySelector('.download-button')) return; | |
// Create the download button | |
const button = document.createElement('button'); | |
button.textContent = 'Download'; | |
button.className = 'download-button'; | |
Object.assign(button.style, { | |
position: 'absolute', | |
top: '10px', | |
right: '10px', | |
zIndex: 10000, | |
backgroundColor: '#007bff', | |
color: '#fff', | |
border: 'none', | |
padding: '5px 10px', | |
cursor: 'pointer', | |
borderRadius: '5px', | |
}); | |
// Set up the download functionality | |
button.addEventListener('click', async () => { | |
try { | |
const videoSrc = video.currentSrc || video.src; | |
if (videoSrc.startsWith('blob:')) { | |
// Extract data from the video element | |
const mimeType = video.getAttribute('type') || 'video/mp4'; | |
const chunks = []; | |
const stream = video.captureStream(); | |
const recorder = new MediaRecorder(stream, { mimeType }); | |
recorder.ondataavailable = (e) => chunks.push(e.data); | |
recorder.onstop = () => { | |
const blob = new Blob(chunks, { type: mimeType }); | |
const objectUrl = URL.createObjectURL(blob); | |
// Trigger download | |
const a = document.createElement('a'); | |
a.href = objectUrl; | |
a.download = 'video.mp4'; | |
a.click(); | |
URL.revokeObjectURL(objectUrl); // Clean up the object URL | |
}; | |
recorder.start(); | |
setTimeout(() => recorder.stop(), video.duration * 1000); // Record until video ends | |
} else if (videoSrc) { | |
// Handle regular URLs | |
const a = document.createElement('a'); | |
a.href = videoSrc; | |
a.download = 'video.mp4'; | |
a.click(); | |
} else { | |
alert('No video source found!'); | |
} | |
} catch (err) { | |
console.error('Error downloading video:', err); | |
alert('Failed to download the video.'); | |
} | |
}); | |
// Add the button to the video's parent element | |
const parent = video.parentElement; | |
parent.style.position = 'relative'; | |
parent.appendChild(button); | |
}; | |
// Add buttons to existing videos | |
document.querySelectorAll('video').forEach(addButton); | |
// Observe the DOM for new video elements | |
const observer = new MutationObserver((mutationsList) => { | |
mutationsList.forEach((mutation) => { | |
mutation.addedNodes.forEach((node) => { | |
if (node.tagName === 'VIDEO') { | |
addButton(node); | |
} else if (node.querySelectorAll) { | |
node.querySelectorAll('video').forEach(addButton); | |
} | |
}); | |
}); | |
}); | |
observer.observe(document.body, { childList: true, subtree: true }); | |
} | |
// Call the function | |
addDownloadButtonsToVideos(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment