Найти в Дзене
Linux code

p5.js: Запись видео с помощью ccapture.js

p5.js - это библиотека JavaScript для создания трехмерной графики с акцентом на простоту.

Используя метафору эскиза, p5.js обладает полным набором функций рисования: можно рассматривать всю страницу браузера как эскиз, включая объекты HTML5 для текста, ввода, видео, веб-камеры и звука.

ccapture.js может записывать плавные видео с фиксированной частотой кадров, поскольку он не запускается в реальном времени, а заставляет анимацию работать с заданной фиксированной частотой кадров, которую можно указать. Можно записывать анимацию с плавной и последовательной скоростью 30 или 60 кадров в секунду, даже если для рендеринга каждого кадра требуются секунды, или даже с частотой 240 кадров в секунду и создать размытие в движении.

Для начала необходимо установить Google Chrome
Загрузить скрипты в каталог ./libs:

- CCapture.js
-
webm-writer-0.2.0.js
-
download.js
-
p5.js

Создать файл ./index.html:

<!DOCTYPE html>
<html>
<head>
<meta
charset="utf-8">
<title>P5.js</title>
<script
src="libs/CCapture.js"></script>
<script
src="libs/webm-writer-0.2.0.js"></script>
<script
src="libs/download.js"></script>
<script
src="libs/p5.js"></script>
<script
src="script/base.js"></script>
<script
src="script/video.js"></script>
<script
src="script/camera.js"></script>
<script
src="script/lights.js"></script>
<script
src="script/elements/box.js"></script>
<script
src="script/run.js"></script>
<style>
* {
padding: 0;
margin: 0;
}
button {
position: fixed;
top: 10px;
right: 10px;
width: 100px;
padding: 5px;
background-color:
rgba(0,0,0,0.5);
color: white;
border: 1px solid black;
text-transform: uppercase;
font-weight: 700;
}
button, button:active, button:focus {
outline: none;
}
</style>
</head>
<body></body>
</html>

В файле ./script/base.js:

let window_w = 1920;
let window_h = 1080;

let orbitRadiusMin = 200;
let orbitRadiusMax = 1000;

В файле ./script/video.js:

let capturer;
let button;

function
recordStart() {
capturer = new
CCapture({format: "webm", framerate: 60});
capturer.
start();
button.textContent = "стоп";
button.
onclick = e => {
recordStop();
};
}

function
recordStop() {
capturer.
stop();
capturer.
save();
capturer = null;
button.textContent = "старт";
button.onclick =
recordStart;
}

В файле ./script/camera.js:

let camera_x1 = 0;
let camera_y1 = 0;
let camera_z1 = 0;
let orbitRadiusMin = 200;
let orbitRadiusMax = 1000;
let orbitRadiusCamera = orbitRadiusMin;

function
moveCamera() {
if (orbitRadiusCamera <= orbitRadiusMin) {
orbitRadiusCamera++;
} else if (orbitRadiusCamera >= orbitRadiusMax) {
orbitRadiusCamera--;
}

camera_x1 = Math.
cos(date) * orbitRadiusCamera;
camera_y1 = Math.
sin(date) * orbitRadiusCamera;
camera_z1 = Math.
sin(date) * orbitRadiusCamera;

camera(camera_x1, camera_y1, camera_z1, 0, 0, 0, 0, 1, 0);
}

В файле ./script/lights.js:

let orbitRadiusLight1 = 500;
let orbitRadiusLight2 = 750;
let light1_x = 0;
let light1_y = 0;
let light1_z = 0;
let light2_x = 0;
let light2_y = 0;
let light2_z = 0;

function
moveLights() {
date =
Date.now() * 0.0001;

if (orbitRadiusLight1 <= orbitRadiusMin) {
orbitRadiusLight1++;
} else if (orbitRadiusLight1 >= orbitRadiusMax) {
orbitRadiusLight1--;
}

if (orbitRadiusLight2 <= orbitRadiusMin) {
orbitRadiusLight2++;
} else if (orbitRadiusLight2 >= orbitRadiusMax) {
orbitRadiusLight2--;
}

light1_x = Math.
cos(date) * orbitRadiusLight1;
light1_y = Math.
sin(date) * orbitRadiusLight1;
light1_z = Math.
sin(date) * orbitRadiusLight1;

light2_x = Math.
cos(date) * orbitRadiusLight2;
light2_y = Math.
sin(date) * orbitRadiusLight2;
light2_z = Math.
sin(date) * orbitRadiusLight2;

pointLight(255, 255, 255, light1_x, light1_y, light1_z);
pointLight(255, 255, 255, light2_x, light2_y, light2_z);
}

В файле ./script/elements/box.js:

let size = 30;
let step = size + 5;
let fg = null;
let bg = 100;

let pos_x = 0;
let pos_y = 0;
let pos_z = 0;

let new_x = 0;
let new_y = 0;
let new_z = 0;

let light_x = -500;
let light_y = -500;
let light_z = 250;

let camera_x = -125;
let camera_y = -125;
let camera_z = 200;

let RStep = 0.1;
function
drawBoxes() {
background(200);

push();
translate(pos_x, pos_y, pos_z);

moveLights();

RStep += 0.1;
rotateX(RStep);
rotateY(RStep);
rotateZ(RStep);
for (let x = -1; x < 2; x++) {
for (let y = -1; y < 2; y++) {
for (let z = -1; z < 2; z++) {
new_x = x * step;
new_y = y * step;
new_z = z * step;

translate(new_x, new_y, new_z);
if (fg == null) {
noStroke();
} else {
stroke(fg);
}

if (bg == null) {
noFill()
} else {
fill(bg);
}

box(size);
translate(-new_x, -new_y, -new_z);
}
}
}
pop();

camera(camera_x, camera_y, camera_z, 0, 0, 0, 0, 1, 0);
moveCamera();
}

В файле ./script/run.js:

function setup() {
createCanvas(window_w, window_h, WEBGL);

button = document.
createElement("button");
button.textContent = "старт";
document.body.
appendChild(button);
button.
onclick = recordStart;

block = document.
createElement("div");
block.id = "info"
block.textContent = counter;
document.body.
appendChild(block);
}

function
draw() {
angleMode(DEGREES);
clear();
drawBoxes();
if (capturer) {
capturer.
capture(document.getElementById("defaultCanvas0"));
}
}