화면 캡처 — desktopCapturer와 스크린샷
"데스크톱 캡처는 화면 녹화, 스크린샷, 화상 회의 앱의 핵심 기능" — Electron의 desktopCapturer는 Chromium의 미디어 캡처 기능을 활용합니다.
desktopCapturer 기본 사용
Electron 17+부터 desktopCapturer는 메인 프로세스에서만 사용합니다.
// main.js
const { desktopCapturer, ipcMain } = require('electron');
ipcMain.handle('capture:getSources', async () => {
const sources = await desktopCapturer.getSources({
types: ['window', 'screen'],
thumbnailSize: { width: 320, height: 180 },
});
return sources.map(source => ({
id: source.id,
name: source.name,
thumbnail: source.thumbnail.toDataURL(),
appIcon: source.appIcon?.toDataURL() || null,
}));
});
특정 윈도우/화면 캡처
// preload.js
contextBridge.exposeInMainWorld('electronAPI', {
getSources: () => ipcRenderer.invoke('capture:getSources'),
captureScreen: (sourceId) => ipcRenderer.invoke('capture:screen', sourceId),
});
// renderer.js — 소스 선택 후 캡처
async function startCapture() {
const sources = await window.electronAPI.getSources();
// 소스 선택 UI 표시
const sourceList = document.getElementById('source-list');
sources.forEach(source => {
const item = document.createElement('div');
item.innerHTML = `
<img src="${source.thumbnail}" />
<span>${source.name}</span>
`;
item.onclick = () => captureSource(source.id);
sourceList.appendChild(item);
});
}
async function captureSource(sourceId) {
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: sourceId,
},
},
});
// 비디오 스트림에서 프레임 캡처
const video = document.createElement('video');
video.srcObject = stream;
await video.play();
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
// 스트림 정리
stream.getTracks().forEach(track => track.stop());
// PNG로 저장
const dataUrl = canvas.toDataURL('image/png');
return dataUrl;
} catch (error) {
console.error('캡처 실패:', error);
}
}
webContents 캡처 (앱 자체 캡처)
// main.js — 현재 앱 윈도우의 스크린샷
ipcMain.handle('capture:window', async (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
const image = await win.webContents.capturePage();
return image.toPNG().toString('base64');
});
// 특정 영역만 캡처
ipcMain.handle('capture:region', async (event, rect) => {
const win = BrowserWindow.fromWebContents(event.sender);
const image = await win.webContents.capturePage({
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
});
return image.toPNG().toString('base64');
});
스크린샷 저장
ipcMain.handle('capture:save', async (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
const image = await win.webContents.capturePage();
const { filePath } = await dialog.showSaveDialog(win, {
defaultPath: `screenshot-${Date.now()}.png`,
filters: [{ name: 'PNG', extensions: ['png'] }],
});
if (filePath) {
await fs.promises.writeFile(filePath, image.toPNG());
return filePath;
}
return null;
});
면접 포인트 정리
desktopCapturer는 메인 프로세스 전용 (Electron 17+)webContents.capturePage()로 앱 자체 윈도우 캡처 가능- 미디어 스트림은 사용 후 반드시
track.stop()으로 정리 - 화면 캡처에는 OS별 권한 설정이 필요할 수 있음 (macOS: 화면 기록 권한)
화면 캡처를 다뤘으면, 다음은 네이티브 모듈 사용법을 살펴봅시다.
댓글 로딩 중...