Restore three-button capture interface: Share Entire Screen, Snip, Cancel
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
# Screen Capture Tool
|
||||
|
||||
A standalone utility for capturing screenshots from user's screen using the native Browser Screen Capture API.
|
||||
|
||||
## Features
|
||||
|
||||
- 📸 Capture screenshots from user-selected screen/window
|
||||
- 🎯 No external dependencies
|
||||
- ⚡ Returns canvas for flexible post-processing
|
||||
- 🛡️ Graceful error handling
|
||||
- ♿ Respects user permissions
|
||||
|
||||
## Installation
|
||||
|
||||
Copy the `screen-capture` folder to your project:
|
||||
|
||||
```
|
||||
your-project/
|
||||
├── tools/
|
||||
│ └── screen-capture/
|
||||
│ ├── index.js
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Screenshot Capture
|
||||
|
||||
```javascript
|
||||
import { captureScreenshot } from './tools/screen-capture/index.js';
|
||||
|
||||
const canvas = await captureScreenshot();
|
||||
if (canvas) {
|
||||
// Canvas is ready for use
|
||||
// Convert to File, display, or manipulate further
|
||||
}
|
||||
```
|
||||
|
||||
### Convert to File
|
||||
|
||||
```javascript
|
||||
import { captureScreenshot, canvasToFile } from './tools/screen-capture/index.js';
|
||||
|
||||
const canvas = await captureScreenshot();
|
||||
if (canvas) {
|
||||
const file = await canvasToFile(canvas, 'my-screenshot.png');
|
||||
// Use file with FormData, attachments, etc.
|
||||
}
|
||||
```
|
||||
|
||||
### One-liner with Blob
|
||||
|
||||
```javascript
|
||||
const canvas = await captureScreenshot();
|
||||
canvas?.toBlob((blob) => {
|
||||
const file = new File([blob], `screenshot-${Date.now()}.png`, { type: 'image/png' });
|
||||
// Use file...
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `captureScreenshot()`
|
||||
|
||||
**Returns:** `Promise<Canvas | null>`
|
||||
|
||||
Opens native browser dialog for user to select screen/window to capture. Returns a canvas element containing the screenshot, or null if user cancels or error occurs.
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
const canvas = await captureScreenshot();
|
||||
```
|
||||
|
||||
### `canvasToFile(canvas, filename?)`
|
||||
|
||||
**Parameters:**
|
||||
- `canvas` (Canvas): Canvas element to convert
|
||||
- `filename` (string, optional): Custom filename. Defaults to `screenshot-{timestamp}.png`
|
||||
|
||||
**Returns:** `Promise<File>`
|
||||
|
||||
Converts canvas to PNG File object for easy handling in file uploads or attachments.
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
const file = await canvasToFile(canvas, 'custom-name.png');
|
||||
```
|
||||
|
||||
## Browser Support
|
||||
|
||||
Requires browsers supporting the Screen Capture API:
|
||||
- Chrome 72+
|
||||
- Edge 79+
|
||||
- Firefox 66+
|
||||
- Safari 13+
|
||||
|
||||
Note: User must grant permission for each capture request.
|
||||
|
||||
## Error Handling
|
||||
|
||||
The tool gracefully handles:
|
||||
- User cancellation of the capture dialog
|
||||
- Browser permission denial
|
||||
- Browser incompatibility
|
||||
- Missing canvas/video support
|
||||
|
||||
All errors are logged to console and return null.
|
||||
|
||||
## Examples
|
||||
|
||||
### React Component
|
||||
|
||||
```jsx
|
||||
import { captureScreenshot, canvasToFile } from './tools/screen-capture/index.js';
|
||||
|
||||
export function ScreenshotButton() {
|
||||
const handleCapture = async () => {
|
||||
const canvas = await captureScreenshot();
|
||||
if (canvas) {
|
||||
const file = await canvasToFile(canvas);
|
||||
console.log('Screenshot captured:', file.name);
|
||||
}
|
||||
};
|
||||
|
||||
return <button onClick={handleCapture}>Take Screenshot</button>;
|
||||
}
|
||||
```
|
||||
|
||||
### With Form Submission
|
||||
|
||||
```javascript
|
||||
import { captureScreenshot, canvasToFile } from './tools/screen-capture/index.js';
|
||||
|
||||
const canvas = await captureScreenshot();
|
||||
if (canvas) {
|
||||
const file = await canvasToFile(canvas);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('screenshot', file);
|
||||
|
||||
await fetch('/api/upload', { method: 'POST', body: formData });
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT - Use freely in your projects
|
||||
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* Screen Capture Tool
|
||||
* Captures a screenshot from the user's screen using the Screen Capture API
|
||||
*
|
||||
* @module ScreenCapture
|
||||
*/
|
||||
|
||||
(function() {
|
||||
console.log('Starting Screen Capture Tool initialization...');
|
||||
|
||||
window.captureScreenshot = async function() {
|
||||
console.log('captureScreenshot called');
|
||||
try {
|
||||
// Request screen capture from user
|
||||
const mediaStream = await navigator.mediaDevices.getDisplayMedia({
|
||||
video: { mediaSource: 'screen' }
|
||||
});
|
||||
|
||||
// Create video element to capture frame
|
||||
const video = document.createElement('video');
|
||||
video.srcObject = mediaStream;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
video.onloadedmetadata = () => {
|
||||
// Create canvas and draw video frame
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = video.videoWidth;
|
||||
canvas.height = video.videoHeight;
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(video, 0, 0);
|
||||
|
||||
// Stop all media tracks
|
||||
mediaStream.getTracks().forEach(track => track.stop());
|
||||
|
||||
// Return canvas for further processing
|
||||
resolve(canvas);
|
||||
};
|
||||
|
||||
video.play();
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Screenshot capture failed:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
window.captureSnip = async function() {
|
||||
console.log('captureSnip called');
|
||||
try {
|
||||
// First, get the full screen capture
|
||||
const mediaStream = await navigator.mediaDevices.getDisplayMedia({
|
||||
video: { mediaSource: 'screen' }
|
||||
});
|
||||
|
||||
// Create video element to capture frame
|
||||
const video = document.createElement('video');
|
||||
video.srcObject = mediaStream;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
video.onloadedmetadata = () => {
|
||||
// Capture full screen to canvas
|
||||
const fullCanvas = document.createElement('canvas');
|
||||
fullCanvas.width = video.videoWidth;
|
||||
fullCanvas.height = video.videoHeight;
|
||||
const fullCtx = fullCanvas.getContext('2d');
|
||||
fullCtx.drawImage(video, 0, 0);
|
||||
|
||||
// Stop video tracks
|
||||
mediaStream.getTracks().forEach(track => track.stop());
|
||||
|
||||
// Show selection overlay
|
||||
createSelectionOverlay(fullCanvas, resolve);
|
||||
};
|
||||
|
||||
video.play();
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Snip capture failed:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
function createSelectionOverlay(fullCanvas, resolve) {
|
||||
console.log('createSelectionOverlay called');
|
||||
// Create overlay container
|
||||
const overlay = document.createElement('div');
|
||||
overlay.style.cssText = `
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
cursor: crosshair;
|
||||
z-index: 99999;
|
||||
user-select: none;
|
||||
`;
|
||||
|
||||
// Create canvas for drawing selection box
|
||||
const selectionCanvas = document.createElement('canvas');
|
||||
selectionCanvas.style.cssText = `
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: crosshair;
|
||||
z-index: 100000;
|
||||
`;
|
||||
selectionCanvas.width = window.innerWidth;
|
||||
selectionCanvas.height = window.innerHeight;
|
||||
|
||||
// Scale factor for mapping screen pixels to window pixels
|
||||
const scaleX = fullCanvas.width / window.innerWidth;
|
||||
const scaleY = fullCanvas.height / window.innerHeight;
|
||||
|
||||
let isDrawing = false;
|
||||
let startX = 0;
|
||||
let startY = 0;
|
||||
let endX = 0;
|
||||
let endY = 0;
|
||||
|
||||
const ctx = selectionCanvas.getContext('2d');
|
||||
|
||||
function drawSelection() {
|
||||
ctx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height);
|
||||
|
||||
if (!isDrawing && (startX === endX && startY === endY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const x = Math.min(startX, endX);
|
||||
const y = Math.min(startY, endY);
|
||||
const width = Math.abs(endX - startX);
|
||||
const height = Math.abs(endY - startY);
|
||||
|
||||
// Draw selection rectangle
|
||||
ctx.strokeStyle = '#0EA5E9';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeRect(x, y, width, height);
|
||||
|
||||
// Fill with semi-transparent color
|
||||
ctx.fillStyle = 'rgba(14, 165, 233, 0.1)';
|
||||
ctx.fillRect(x, y, width, height);
|
||||
|
||||
// Draw corner handles
|
||||
const handleSize = 8;
|
||||
ctx.fillStyle = '#0EA5E9';
|
||||
ctx.fillRect(x - handleSize / 2, y - handleSize / 2, handleSize, handleSize);
|
||||
ctx.fillRect(x + width - handleSize / 2, y - handleSize / 2, handleSize, handleSize);
|
||||
ctx.fillRect(x - handleSize / 2, y + height - handleSize / 2, handleSize, handleSize);
|
||||
ctx.fillRect(x + width - handleSize / 2, y + height - handleSize / 2, handleSize, handleSize);
|
||||
}
|
||||
|
||||
selectionCanvas.addEventListener('mousedown', (e) => {
|
||||
isDrawing = true;
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
endX = startX;
|
||||
endY = startY;
|
||||
});
|
||||
|
||||
selectionCanvas.addEventListener('mousemove', (e) => {
|
||||
if (isDrawing) {
|
||||
endX = e.clientX;
|
||||
endY = e.clientY;
|
||||
drawSelection();
|
||||
}
|
||||
});
|
||||
|
||||
selectionCanvas.addEventListener('mouseup', () => {
|
||||
if (isDrawing) {
|
||||
isDrawing = false;
|
||||
|
||||
const x = Math.min(startX, endX);
|
||||
const y = Math.min(startY, endY);
|
||||
const width = Math.abs(endX - startX);
|
||||
const height = Math.abs(endY - startY);
|
||||
|
||||
// Validate selection
|
||||
if (width < 10 || height < 10) {
|
||||
console.warn('Selection too small');
|
||||
cleanup();
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create cropped canvas from full screenshot
|
||||
const croppedCanvas = document.createElement('canvas');
|
||||
croppedCanvas.width = width * scaleX;
|
||||
croppedCanvas.height = height * scaleY;
|
||||
const croppedCtx = croppedCanvas.getContext('2d');
|
||||
|
||||
// Draw cropped section from full canvas
|
||||
croppedCtx.drawImage(
|
||||
fullCanvas,
|
||||
x * scaleX,
|
||||
y * scaleY,
|
||||
width * scaleX,
|
||||
height * scaleY,
|
||||
0,
|
||||
0,
|
||||
width * scaleX,
|
||||
height * scaleY
|
||||
);
|
||||
|
||||
cleanup();
|
||||
resolve(croppedCanvas);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle escape key
|
||||
const handleKeydown = (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
cleanup();
|
||||
resolve(null);
|
||||
}
|
||||
};
|
||||
|
||||
function cleanup() {
|
||||
document.removeEventListener('keydown', handleKeydown);
|
||||
overlay.remove();
|
||||
selectionCanvas.remove();
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', handleKeydown);
|
||||
document.body.appendChild(overlay);
|
||||
document.body.appendChild(selectionCanvas);
|
||||
|
||||
console.log('Snipping tool active: Draw a rectangle to select area. Press ESC to cancel.');
|
||||
}
|
||||
|
||||
window.canvasToFile = async function(canvas, filename = null) {
|
||||
console.log('canvasToFile called');
|
||||
return new Promise((resolve) => {
|
||||
const name = filename || `screenshot-${Date.now()}.png`;
|
||||
canvas.toBlob((blob) => {
|
||||
const file = new File([blob], name, { type: 'image/png' });
|
||||
resolve(file);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
console.log('✓ Screen Capture Tool loaded successfully');
|
||||
console.log('Functions available: window.captureScreenshot, window.captureSnip, window.canvasToFile');
|
||||
})();
|
||||
@@ -0,0 +1,219 @@
|
||||
# Screen Record Tool
|
||||
|
||||
A standalone utility for recording the user's screen using the native Browser Screen Capture API and MediaRecorder API.
|
||||
|
||||
## Features
|
||||
|
||||
- 🎬 Record user-selected screen/window
|
||||
- ⏱️ Configurable duration limits (default 5 minutes)
|
||||
- 🎯 No external dependencies
|
||||
- ⚡ Fine-grained control with start/stop callbacks
|
||||
- 🛡️ Graceful error handling
|
||||
- ♿ Respects user permissions
|
||||
|
||||
## Installation
|
||||
|
||||
Copy the `screen-record` folder to your project:
|
||||
|
||||
```
|
||||
your-project/
|
||||
├── tools/
|
||||
│ └── screen-record/
|
||||
│ ├── index.js
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Screen Recording
|
||||
|
||||
```javascript
|
||||
import { recordScreen } from './tools/screen-record/index.js';
|
||||
|
||||
const recorder = await recordScreen();
|
||||
if (recorder) {
|
||||
// User is recording...
|
||||
|
||||
// Stop after 10 seconds
|
||||
setTimeout(async () => {
|
||||
const file = await recorder.stop();
|
||||
console.log('Recording saved:', file.name);
|
||||
}, 10000);
|
||||
}
|
||||
```
|
||||
|
||||
### With Duration Limit
|
||||
|
||||
```javascript
|
||||
const recorder = await recordScreen({
|
||||
maxDuration: 60000 // 1 minute instead of default 5 minutes
|
||||
});
|
||||
```
|
||||
|
||||
### With Callbacks
|
||||
|
||||
```javascript
|
||||
const recorder = await recordScreen({
|
||||
onStart: () => console.log('Recording started'),
|
||||
onStop: () => console.log('Recording stopped')
|
||||
});
|
||||
```
|
||||
|
||||
### Quick Recording (Auto-stop)
|
||||
|
||||
```javascript
|
||||
import { recordScreenFor } from './tools/screen-record/index.js';
|
||||
|
||||
const file = await recordScreenFor(10000); // Record for 10 seconds
|
||||
console.log('Recording saved:', file.name);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `recordScreen(options?)`
|
||||
|
||||
**Parameters:**
|
||||
- `options` (Object, optional):
|
||||
- `maxDuration` (number): Max recording time in ms. Default: 300000 (5 min)
|
||||
- `mimeType` (string): MIME type. Default: 'video/webm'
|
||||
- `onStart` (Function): Called when recording starts
|
||||
- `onStop` (Function): Called when recording stops
|
||||
|
||||
**Returns:** `Promise<RecorderObject | null>`
|
||||
|
||||
Opens native browser dialog for user to select screen/window to record. Returns a recorder controller object with methods to stop and manage the recording.
|
||||
|
||||
**Recorder Object Methods:**
|
||||
- `stop()` - Stops recording and returns File object
|
||||
- `isRecording()` - Returns boolean for current status
|
||||
- `getDuration()` - Returns duration in milliseconds
|
||||
- `mediaStream` - Reference to underlying MediaStream
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
const recorder = await recordScreen();
|
||||
const file = await recorder.stop();
|
||||
```
|
||||
|
||||
### `recordScreenFor(duration)`
|
||||
|
||||
**Parameters:**
|
||||
- `duration` (number): Recording duration in milliseconds
|
||||
|
||||
**Returns:** `Promise<File>`
|
||||
|
||||
Convenience function that automatically stops recording after specified duration.
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
const file = await recordScreenFor(30000); // 30 second recording
|
||||
```
|
||||
|
||||
## Browser Support
|
||||
|
||||
Requires browsers supporting Screen Capture and MediaRecorder APIs:
|
||||
- Chrome 72+
|
||||
- Edge 79+
|
||||
- Firefox 66+
|
||||
- Safari 13+
|
||||
|
||||
Note: User must grant permission for each recording request.
|
||||
|
||||
## Error Handling
|
||||
|
||||
The tool gracefully handles:
|
||||
- User cancellation of the capture dialog
|
||||
- Browser permission denial
|
||||
- Browser incompatibility
|
||||
- Recording stream interruption
|
||||
- Max duration timeout
|
||||
|
||||
All errors are logged to console and return null.
|
||||
|
||||
## Examples
|
||||
|
||||
### React Component with UI
|
||||
|
||||
```jsx
|
||||
import { recordScreen } from './tools/screen-record/index.js';
|
||||
import { useState } from 'react';
|
||||
|
||||
export function ScreenRecorderButton() {
|
||||
const [isRecording, setIsRecording] = useState(false);
|
||||
const [recorder, setRecorder] = useState(null);
|
||||
|
||||
const startRecording = async () => {
|
||||
const rec = await recordScreen({
|
||||
onStart: () => setIsRecording(true),
|
||||
onStop: () => setIsRecording(false)
|
||||
});
|
||||
setRecorder(rec);
|
||||
};
|
||||
|
||||
const stopRecording = async () => {
|
||||
if (recorder) {
|
||||
const file = await recorder.stop();
|
||||
console.log('Recording saved:', file.name);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!isRecording ? (
|
||||
<button onClick={startRecording}>Start Recording</button>
|
||||
) : (
|
||||
<button onClick={stopRecording}>Stop Recording</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### With File Upload
|
||||
|
||||
```javascript
|
||||
import { recordScreen } from './tools/screen-record/index.js';
|
||||
|
||||
const recorder = await recordScreen();
|
||||
if (recorder) {
|
||||
// Wait 15 seconds then stop
|
||||
setTimeout(async () => {
|
||||
const file = await recorder.stop();
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('video', file);
|
||||
|
||||
await fetch('/api/upload-video', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
}, 15000);
|
||||
}
|
||||
```
|
||||
|
||||
### Auto-stop after Duration
|
||||
|
||||
```javascript
|
||||
import { recordScreenFor } from './tools/screen-record/index.js';
|
||||
|
||||
// Record for exactly 5 seconds
|
||||
const file = await recordScreenFor(5000);
|
||||
const formData = new FormData();
|
||||
formData.append('video', file);
|
||||
|
||||
await fetch('/api/save-recording', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
```
|
||||
|
||||
## File Output
|
||||
|
||||
Both functions return WebM video files with standardized naming:
|
||||
- Filename format: `screen-recording-{timestamp}.webm`
|
||||
- MIME type: `video/webm`
|
||||
- Compatible with most video players and uploads
|
||||
|
||||
## License
|
||||
|
||||
MIT - Use freely in your projects
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* Screen Record Tool
|
||||
* Records the user's screen using the Screen Capture API and MediaRecorder API
|
||||
*
|
||||
* @module ScreenRecord
|
||||
*/
|
||||
|
||||
(function() {
|
||||
console.log('Loading Screen Record Tool...');
|
||||
|
||||
/**
|
||||
* Starts recording the user's selected screen/window
|
||||
* Opens native browser dialog for user to select what to record
|
||||
*
|
||||
* @async
|
||||
* @param {Object} [options={}] - Recording options
|
||||
* @param {number} [options.maxDuration=300000] - Maximum recording duration in milliseconds (default: 5 minutes)
|
||||
* @param {string} [options.mimeType='video/webm'] - MIME type for recording
|
||||
* @param {Function} [options.onStart] - Callback when recording starts
|
||||
* @param {Function} [options.onStop] - Callback when recording stops
|
||||
* @returns {Promise<Object>} Recording controller object with stop() method and events
|
||||
*
|
||||
* @example
|
||||
* const recorder = await window.recordScreen();
|
||||
* // User is recording...
|
||||
*
|
||||
* setTimeout(() => {
|
||||
* const file = await recorder.stop();
|
||||
* console.log('Recording saved:', file.name);
|
||||
* }, 10000);
|
||||
*/
|
||||
window.recordScreen = async function(options = {}) {
|
||||
const {
|
||||
maxDuration = 5 * 60 * 1000, // 5 minutes
|
||||
mimeType = 'video/webm',
|
||||
onStart = null,
|
||||
onStop = null
|
||||
} = options;
|
||||
|
||||
try {
|
||||
// Request screen capture from user
|
||||
const mediaStream = await navigator.mediaDevices.getDisplayMedia({
|
||||
video: { mediaSource: 'screen' },
|
||||
audio: false
|
||||
});
|
||||
|
||||
// Create MediaRecorder
|
||||
const mediaRecorder = new MediaRecorder(mediaStream, { mimeType });
|
||||
const chunks = [];
|
||||
let isRecording = true;
|
||||
let timeoutId = null;
|
||||
|
||||
// Collect recording data
|
||||
mediaRecorder.ondataavailable = (event) => {
|
||||
if (event.data.size > 0) {
|
||||
chunks.push(event.data);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle recording stop
|
||||
mediaRecorder.onstop = () => {
|
||||
isRecording = false;
|
||||
clearTimeout(timeoutId);
|
||||
mediaStream.getTracks().forEach(track => track.stop());
|
||||
if (onStop) onStop();
|
||||
};
|
||||
|
||||
// Start recording
|
||||
mediaRecorder.start();
|
||||
if (onStart) onStart();
|
||||
|
||||
// Set max duration timeout
|
||||
timeoutId = setTimeout(() => {
|
||||
if (isRecording) {
|
||||
mediaRecorder.stop();
|
||||
}
|
||||
}, maxDuration);
|
||||
|
||||
// Stop if user stops screen share
|
||||
mediaStream.getVideoTracks()[0].onended = () => {
|
||||
if (isRecording) {
|
||||
mediaRecorder.stop();
|
||||
}
|
||||
};
|
||||
|
||||
// Return controller object
|
||||
return {
|
||||
/**
|
||||
* Stops the recording and returns the recorded file
|
||||
* @returns {Promise<File>} WebM File object with recorded video
|
||||
*/
|
||||
stop: async () => {
|
||||
return new Promise((resolve) => {
|
||||
if (!isRecording) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const stopHandler = () => {
|
||||
mediaRecorder.removeEventListener('stop', stopHandler);
|
||||
const blob = new Blob(chunks, { type: mimeType });
|
||||
const file = new File(
|
||||
[blob],
|
||||
`screen-recording-${Date.now()}.webm`,
|
||||
{ type: mimeType }
|
||||
);
|
||||
resolve(file);
|
||||
};
|
||||
|
||||
mediaRecorder.addEventListener('stop', stopHandler);
|
||||
mediaRecorder.stop();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if recording is currently active
|
||||
* @returns {boolean} True if recording is in progress
|
||||
*/
|
||||
isRecording: () => isRecording,
|
||||
|
||||
/**
|
||||
* Gets the current recording duration in milliseconds
|
||||
* @returns {number} Duration since recording started
|
||||
*/
|
||||
getDuration: () => mediaRecorder.state === 'recording' ? mediaRecorder.state : 0,
|
||||
|
||||
/**
|
||||
* The underlying MediaStream object
|
||||
* @type {MediaStream}
|
||||
*/
|
||||
mediaStream
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Screen recording failed:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple helper to start recording and stop after specified duration
|
||||
* Useful for quick recordings with automatic stop
|
||||
*
|
||||
* @async
|
||||
* @param {number} duration - Recording duration in milliseconds
|
||||
* @returns {Promise<File>} WebM File object with recorded video
|
||||
*
|
||||
* @example
|
||||
* const file = await window.recordScreenFor(10000); // Record for 10 seconds
|
||||
* console.log('Recording saved:', file.name);
|
||||
*/
|
||||
window.recordScreenFor = async function(duration) {
|
||||
const recorder = await window.recordScreen();
|
||||
if (!recorder) return null;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(async () => {
|
||||
const file = await recorder.stop();
|
||||
resolve(file);
|
||||
}, duration);
|
||||
});
|
||||
};
|
||||
|
||||
console.log('Screen Record Tool loaded successfully');
|
||||
})();
|
||||
Reference in New Issue
Block a user