v0 release

This commit is contained in:
Ruidy Nemausat 2020-04-11 18:51:19 +02:00
commit 812a542dfe
7 changed files with 4915 additions and 0 deletions

89
.gitignore vendored Normal file
View file

@ -0,0 +1,89 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
.DS_Store
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# Webpack
.webpack/
# Electron-Forge
out/

4588
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

58
package.json Normal file
View file

@ -0,0 +1,58 @@
{
"name": "screenrecorder",
"productName": "screenrecorder",
"version": "1.0.0",
"description": "My Electron application description",
"main": "src/index.js",
"scripts": {
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish",
"lint": "echo \"No linting configured\""
},
"keywords": [],
"author": {
"name": "Ruidy Nemausat",
"email": "ruidy.nemausat@gmail.com"
},
"license": "MIT",
"config": {
"forge": {
"packagerConfig": {},
"makers": [
{
"name": "@electron-forge/maker-squirrel",
"config": {
"name": "screenrecorder"
}
},
{
"name": "@electron-forge/maker-zip",
"platforms": [
"darwin"
]
},
{
"name": "@electron-forge/maker-deb",
"config": {}
},
{
"name": "@electron-forge/maker-rpm",
"config": {}
}
]
}
},
"dependencies": {
"electron-squirrel-startup": "^1.0.0"
},
"devDependencies": {
"@electron-forge/cli": "^6.0.0-beta.50",
"@electron-forge/maker-deb": "^6.0.0-beta.50",
"@electron-forge/maker-rpm": "^6.0.0-beta.50",
"@electron-forge/maker-squirrel": "^6.0.0-beta.50",
"@electron-forge/maker-zip": "^6.0.0-beta.50",
"electron": "8.2.1"
}
}

30
src/index.css Normal file
View file

@ -0,0 +1,30 @@
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
Arial, sans-serif;
display: flex;
flex-direction: column;
background-color: aliceblue;
}
h1 {
align-items: center;
margin: auto;
margin-top: 20px;
margin-bottom: 20px;
}
video {
background-color: black;
width: 100%;
margin: auto;
}
div {
display: flex;
justify-content: space-between;
position: relative;
bottom: -10px;
margin: auto;
width: 60%;
padding-top: 10px;
padding-bottom: 10px;
}

27
src/index.html Normal file
View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>📹 Screen Recorder</title>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<h1>📹 Screen Recorder</h1>
<video src=""></video>
<div>
<button id="startBtn" class="btn btn-primary">Start</button>
<button id="stopBtn" class="btn btn-warning">Stop</button>
<button id="videoSelectBtn" class="btn btn-outline-primary">
Video source
</button>
</div>
<script defer src="render.js"></script>
</body>
</html>

35
src/index.js Normal file
View file

@ -0,0 +1,35 @@
const { app, BrowserWindow } = require("electron");
const { join } = require("path");
if (require("electron-squirrel-startup")) {
app.quit();
}
const createWindow = () => {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
});
mainWindow.loadFile(join(__dirname, "index.html"));
// Open the DevTools.
// mainWindow.webContents.openDevTools();
};
app.on("ready", createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});

88
src/render.js Normal file
View file

@ -0,0 +1,88 @@
const { desktopCapturer, remote } = require("electron");
const { writeFile } = require("fs");
const { dialog, Menu } = remote;
let mediaRecorder;
const recordedChunks = [];
const startBtn = document.getElementById("startBtn");
startBtn.onclick = (e) => {
mediaRecorder.start();
startBtn.classList.add("btn-danger");
startBtn.innerText = "Recording";
};
const stopBtn = document.getElementById("stopBtn");
stopBtn.onclick = (e) => {
mediaRecorder.stop();
startBtn.classList.remove("btn-danger");
startBtn.innerText = "Start";
};
const handleDataAvailable = (e) => {
recordedChunks.push(e.data);
};
const handleStop = async (e) => {
const blob = new Blob(recordedChunks, {
type: "video/webm; codecs=vp9",
});
const buffer = Buffer.from(await blob.arrayBuffer());
const { filePath } = await dialog.showSaveDialog({
buttonLabel: "Save",
defaultPath: `capture-${Date.now()}.webm`,
});
writeFile(filePath, buffer, () => alert("Video saved successfully"));
};
const videoPlayer = document.querySelector("video");
const videoSelectBtn = document.getElementById("videoSelectBtn");
// selectsource changes the videoSource to record.
const selectSource = async (src) => {
videoSelectBtn.innerText = `Source: ${src.name}`;
const constraints = {
audio: false,
video: {
mandatory: {
chromeMediaSource: "desktop",
chromeMediaSourceId: src.id,
},
},
};
const stream = await navigator.mediaDevices.getUserMedia(constraints);
// Preview the source in videoPlayer
videoPlayer.srcObject = stream;
videoPlayer.play();
const options = { mimeType: "video/webm; codecs=vp9" };
mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.onstop = handleStop;
};
// videoSources gets the available video sources.
const videoSources = async () => {
const inputSources = await desktopCapturer.getSources({
types: ["window", "screen"],
});
const optionsMenu = Menu.buildFromTemplate(
inputSources.map((src) => {
return {
label: src.name,
click: () => selectSource(src),
};
})
);
optionsMenu.popup();
};
videoSelectBtn.onclick = videoSources;