Enhance video modal: increase size and add download functionality

This commit is contained in:
2025-12-28 11:13:53 +11:00
parent 4eb2b45cbe
commit 03ce5f1e9b
3 changed files with 77 additions and 4 deletions

View File

@@ -251,6 +251,7 @@
<div id="video-progress-fill" class="video-progress-fill"></div>
</div>
<span id="video-time">0.0s</span>
<button id="video-download-btn" onclick="downloadVideo()" style="background: var(--color-accent-success); margin-left: 0.5rem;">⬇ Download</button>
</div>
</div>
</div>

72
main.js
View File

@@ -622,6 +622,78 @@ function updateVideoFrame() {
document.getElementById('video-progress-fill').style.width = `${progress}%`;
}
async function downloadVideo() {
if (!videoFrames || videoFrames.length === 0) {
alert('No video data to download');
return;
}
const downloadBtn = document.getElementById('video-download-btn');
downloadBtn.disabled = true;
downloadBtn.textContent = '⏳ Creating...';
try {
// Create canvas for rendering
const canvas = document.createElement('canvas');
canvas.width = 1280;
canvas.height = 720;
const ctx = canvas.getContext('2d');
// Setup MediaRecorder
const stream = canvas.captureStream(10); // 10 FPS
const recorder = new MediaRecorder(stream, {
mimeType: 'video/webm;codecs=vp9',
videoBitsPerSecond: 2500000
});
const chunks = [];
recorder.ondataavailable = e => chunks.push(e.data);
recorder.onstop = () => {
const blob = new Blob(chunks, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `page-load-${Date.now()}.webm`;
a.click();
URL.revokeObjectURL(url);
downloadBtn.disabled = false;
downloadBtn.textContent = '⬇ Download';
};
recorder.start();
// Render frames
for (let i = 0; i < videoFrames.length; i++) {
const img = new Image();
await new Promise((resolve, reject) => {
img.onload = resolve;
img.onerror = reject;
img.src = videoFrames[i].data;
});
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const scale = Math.min(canvas.width / img.width, canvas.height / img.height);
const x = (canvas.width - img.width * scale) / 2;
const y = (canvas.height - img.height * scale) / 2;
ctx.drawImage(img, x, y, img.width * scale, img.height * scale);
await new Promise(r => setTimeout(r, 100)); // 100ms per frame = 10fps
}
recorder.stop();
} catch (error) {
console.error('Video download error:', error);
alert('Failed to create video. Your browser may not support this feature.');
downloadBtn.disabled = false;
downloadBtn.textContent = '⬇ Download';
}
}
// Initialization
document.addEventListener('DOMContentLoaded', () => {

View File

@@ -714,12 +714,12 @@ body::before {
.modal-content {
position: relative;
background: var(--color-bg-secondary);
margin: 5% auto;
margin: 3% auto;
padding: 0;
border: 1px solid var(--color-border);
border-radius: var(--radius-xl);
width: 90%;
max-width: 900px;
width: 95%;
max-width: 1400px;
box-shadow: var(--shadow-lg);
animation: slideIn 0.3s ease-out;
}
@@ -769,7 +769,7 @@ body::before {
}
.video-modal-content {
max-width: 800px;
max-width: 1200px;
background: var(--color-bg-secondary);
}