안녕하세요!! 지금은 1시반, 아주 고요한 밤입니다.
드디어 스크린캡쳐 구현에 성공하여 아주*10 기쁜 마음으로 포스팅하게 되었습니다.
개발을 하며 항상 마주치는 난관이 있는 것 같습니다.
하라는대로 했는데 왜 안되지?
왜 나만 안되지?
하지만 언제나 해결책은 구글에 있고, 나만 사용하지 못하도록 만든 프로그램은 없을 것입니다.
나는 뭐든지 만들 수 있다. 겸손한 자신감을 기를 수 있었습니다.
[일렉트론 스크린 캡쳐 기능 보기]
www.youtube.com/watch?v=SPnfEXz4XIU
[코드 보기]
fireship.io/lessons/electron-screen-recorder-project-tutorial/
위 페이지의 도움을 아주아주 많이 받았습니다.
제가 구현한 코드는 렌더러 페이지에서 구현이 되었습니다.
원래의 강좌에서는 메인 페이지에서 구현을 하였는데, 일렉트론에서 제공하는 Screen Capture 툴이 렌더러 페이지에서는 잘 돌아가지 않는 문제가 있었습니다.
혹시,,,,, 일렉트론 개발을 하면서 Require .... is not defined라는 경고메시지를 보신적있지 않으신가요???
main.js에 다음과 같은 코드를 추가하여 렌더러 페이지의 JS에서도 Main에서 사용하는 것 처럼 일렉트론에서 제공하는 기능을 사용할 수 있습니다.
mainWindow = new BrowserWindow(
{
width:1000,
height: 900,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
},
center: true,
//frame: false,
icon: path.join(__dirname, 'img/daARA ICON.png')
});
nodeIntegreation과 enableRemoteModule을 true로 설정하여 렌더러 모듈에서도 일렉트론 기능을 사용할 수 있도록 개방해줍시다.
추가로, icon의 위치를 지정하여 메뉴바, 좌상단 등에서 보이는 아이콘을 설정할 수 있습니다.
아이콘은 1024*1024사이즈여야 합니다.
[HTML]
<!DOCTYPE html>
<html style="background-color: #F6F7CE;">
<head>
<meta charset="UTF-8" />
<title>🏴☠️ 다아라 강의 화면</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css"
/>
<link rel="stylesheet" href="styles/index.css" />
<script defer src="js/daARA_InLecture.js"></script>
</head>
<body class="content">
<h1>🏴☠️ 다아라 강의 화면</h1>
<video></video>
<button id="startBtn" class="button is-primary">강의 시작하기</button>
<button id="stopBtn" class="button is-warning">강의 종료하기</button>
<hr />
<progress id="saveProgressBar" class="progress is-small is-primary" max="100"></progress>
<button id="videoSelectBtn" class="button is-text">
강의화면 선택하기
</button>
</body>
</html>
[CSS]
* {
margin: 0;
padding: 0;
}
body {
text-align: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: auto;
max-width: 38rem;
padding: 2rem;
}
video {
width: 544px;
height: 306px;
background-color: #f0f5f5;
border-radius: 6px;
margin-bottom: 25px;
box-shadow: 2px 5px 10px #e8e8e8;
}
.is-text {
height: auto;
white-space: normal;
}
[JavaScript]
const { desktopCapturer, remote } = require('electron');
const { writeFile } = require('fs');
const { dialog, Menu } = remote;
const videoElement = document.querySelector('video');
const videoSelectBtn = document.getElementById('videoSelectBtn');
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
let mediaRecorder; // MediaRecorder instance to capture footage
const recordedChunks = [];
videoSelectBtn.onclick = getVideoSources;
async function getVideoSources() {
const inputSources = await desktopCapturer.getSources({
types: ['window', 'screen']
});
const videoOptionsMenu = Menu.buildFromTemplate(
inputSources.map(source => {
return {
label: source.name,
click: () => selectSource(source)
};
})
);
videoOptionsMenu.popup();
}
// Change the videoSource window to record
async function selectSource(source) {
videoSelectBtn.innerText = source.name;
const constraints = {
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: source.id
}
}
};
// Create a Stream
const stream = await navigator.mediaDevices
.getUserMedia(constraints);
// Preview the source in a video element
videoElement.srcObject = stream;
videoElement.play();
// Create the Media Recorder
const options = { mimeType: 'video/webm; codecs=vp9' };
mediaRecorder = new MediaRecorder(stream, options);
// Register Event Handlers
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.onstop = handleStop;
}
startBtn.onclick = e => {
mediaRecorder.start();
startBtn.classList.add('is-danger');
startBtn.innerText = '녹화중';
};
stopBtn.onclick = e => {
mediaRecorder.stop();
startBtn.classList.remove('is-danger');
startBtn.innerText = 'Start';
};
// Captures all recorded chunks
function handleDataAvailable(e) {
console.log('video data available');
recordedChunks.push(e.data);
}
// Saves the video file on stop
async function handleStop(e) {
const blob = new Blob(recordedChunks, {
type: 'video/webm; codecs=vp9'
});
const buffer = Buffer.from(await blob.arrayBuffer());
const { filePath } = await dialog.showSaveDialog({
buttonLabel: '비디오 저장',
defaultPath: `vid-${Date.now()}.avi`
});
console.log(filePath);
writeFile(filePath, buffer, () => console.log('video saved successfully!'));
}
'다아라 개발기' 카테고리의 다른 글
[다아라 개발기] 4. 일렉트론은 alert를 싫어해! (0) | 2021.04.11 |
---|---|
[다아라 개발기] 3. 파이큐티야 안녕..... (0) | 2021.04.07 |
[다아라 개발기] 2. PyQt에서 다중 레이아웃 넘나들기 (3) | 2021.03.21 |
[다아라 개발기] 1. 듀얼 모니터 자동 캡쳐 구현하기 (0) | 2021.03.21 |
[다아라 개발기] 0. 다아라 프로젝트 (0) | 2021.03.21 |