在 p5.js 中导出视频
Exporting a video in p5.js
我正在 p5.js 中创建一个简单的动画程序。当用户点击保存按钮时,我想下载动画视频。
我有一个名为 frames
的对象,其中每个键都标记为 frame_1
、frame_2
等等。与每个键关联的值是构成该帧的 array
线段。
我正在想办法获取这些数据并创建 mp4 视频。 p5.js 有一个内置的 save function,我认为它可能会有帮助,但它本身并不是一个完整的解决方案。我可以将每一帧保存为单独的图像,然后在客户端以某种方式将这些图像拼接在一起,但我还没有找到解决方案。
任何其他方法也很好。唯一的要求是在客户端完成。
正如您在评论中指出的那样,gif 也可以,这是一个解决方案:
下面是一个示例 p5 草图,它使用 gif.js.
录制 canvas 动画并将其转换为 gif。
Works in browsers supporting: Web Workers, File API and Typed Arrays.
我提供了这段代码,这样您就可以了解如何使用这个库,因为没有为它提供太多文档,而且我自己也很难搞清楚。
var cnv;
var gif, recording = false;
function setup() {
cnv = createCanvas(400, 400);
var start_rec = createButton("Start Recording");
start_rec.mousePressed(saveVid);
var stop_rec = createButton("Stop Recording");
stop_rec.mousePressed(saveVid);
start_rec.position(500, 500);
stop_rec.position(650, 500);
setupGIF();
}
function saveVid() {
recording = !recording;
if (!recording) {
gif.render();
}
}
var x = 0;
var y = 0;
function draw() {
background(51);
fill(255);
ellipse(x, y, 20, 20);
x++;
y++;
if (recording) {
gif.addFrame(cnv.elt, {
delay: 1,
copy: true
});
}
}
function setupGIF() {
gif = new GIF({
workers: 5,
quality: 20
});
gif.on('finished', function(blob) {
window.open(URL.createObjectURL(blob));
});
}
更多信息:
此草图在您单击 start_rec
时开始记录帧,并在您单击 stop_rec
时停止,在您的草图中,您可能希望以不同方式控制内容,但请记住 addFrame
只添加一帧到gif所以你需要在draw
函数中调用它来添加多帧,你可以传入一个ImageElement
,一个CanvasElement
或一个CanvasContext
以及其他可选参数。
在 gif.on
函数中,您可以指定一个回调函数来对 gif 执行任何您喜欢的操作。
如果您想微调 gif 的设置,例如 quality
、repeat
、background
,您可以阅读更多内容 here。希望这对您有所帮助!
由于 p5.js 是建立在 Canvas API 之上的,在现代浏览器中,您可以使用 MediaRecorder 来完成这项工作。
const btn = document.querySelector('button'),
chunks = [];
function record() {
chunks.length = 0;
let stream = document.querySelector('canvas').captureStream(30),
recorder = new MediaRecorder(stream);
recorder.ondataavailable = e => {
if (e.data.size) {
chunks.push(e.data);
}
};
recorder.onstop = exportVideo;
btn.onclick = e => {
recorder.stop();
btn.textContent = 'start recording';
btn.onclick = record;
};
recorder.start();
btn.textContent = 'stop recording';
}
function exportVideo(e) {
var blob = new Blob(chunks);
var vid = document.createElement('video');
vid.id = 'recorded'
vid.controls = true;
vid.src = URL.createObjectURL(blob);
document.body.appendChild(vid);
vid.play();
}
btn.onclick = record;
// taken from pr.js docs
var x, y;
function setup() {
createCanvas(300, 200);
// Starts in the middle
x = width / 2;
y = height;
}
function draw() {
background(200);
// Draw a circle
stroke(50);
fill(100);
ellipse(x, y, 24, 24);
// Jiggling randomly on the horizontal axis
x = x + random(-1, 1);
// Moving up at a constant speed
y = y - 1;
// Reset to the bottom
if (y < 0) {
y = height;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.min.js"></script>
<button>start recording</button><br>
ccapture 与 p5.js 配合使用可以很好地实现记录 canvas.
上显示的内容的目标
这是 demo 与 p5.js 一起使用的 ccapture。 demo自带源码
此方法不会输出延迟的视频,因为它没有记录您在屏幕上看到的内容,这可能会延迟。相反,它将每一帧写入视频并告诉视频以固定帧速率播放。所以即使只计算一帧需要几秒钟,输出的视频也会流畅播放,不会出现帧与帧之间的任何延迟。
但是,有一点需要注意。此方法仅适用于 Chrome.
我正在 p5.js 中创建一个简单的动画程序。当用户点击保存按钮时,我想下载动画视频。
我有一个名为 frames
的对象,其中每个键都标记为 frame_1
、frame_2
等等。与每个键关联的值是构成该帧的 array
线段。
我正在想办法获取这些数据并创建 mp4 视频。 p5.js 有一个内置的 save function,我认为它可能会有帮助,但它本身并不是一个完整的解决方案。我可以将每一帧保存为单独的图像,然后在客户端以某种方式将这些图像拼接在一起,但我还没有找到解决方案。
任何其他方法也很好。唯一的要求是在客户端完成。
正如您在评论中指出的那样,gif 也可以,这是一个解决方案:
下面是一个示例 p5 草图,它使用 gif.js.
录制 canvas 动画并将其转换为 gif。Works in browsers supporting: Web Workers, File API and Typed Arrays.
我提供了这段代码,这样您就可以了解如何使用这个库,因为没有为它提供太多文档,而且我自己也很难搞清楚。
var cnv;
var gif, recording = false;
function setup() {
cnv = createCanvas(400, 400);
var start_rec = createButton("Start Recording");
start_rec.mousePressed(saveVid);
var stop_rec = createButton("Stop Recording");
stop_rec.mousePressed(saveVid);
start_rec.position(500, 500);
stop_rec.position(650, 500);
setupGIF();
}
function saveVid() {
recording = !recording;
if (!recording) {
gif.render();
}
}
var x = 0;
var y = 0;
function draw() {
background(51);
fill(255);
ellipse(x, y, 20, 20);
x++;
y++;
if (recording) {
gif.addFrame(cnv.elt, {
delay: 1,
copy: true
});
}
}
function setupGIF() {
gif = new GIF({
workers: 5,
quality: 20
});
gif.on('finished', function(blob) {
window.open(URL.createObjectURL(blob));
});
}
更多信息:
此草图在您单击 start_rec
时开始记录帧,并在您单击 stop_rec
时停止,在您的草图中,您可能希望以不同方式控制内容,但请记住 addFrame
只添加一帧到gif所以你需要在draw
函数中调用它来添加多帧,你可以传入一个ImageElement
,一个CanvasElement
或一个CanvasContext
以及其他可选参数。
在 gif.on
函数中,您可以指定一个回调函数来对 gif 执行任何您喜欢的操作。
如果您想微调 gif 的设置,例如 quality
、repeat
、background
,您可以阅读更多内容 here。希望这对您有所帮助!
由于 p5.js 是建立在 Canvas API 之上的,在现代浏览器中,您可以使用 MediaRecorder 来完成这项工作。
const btn = document.querySelector('button'),
chunks = [];
function record() {
chunks.length = 0;
let stream = document.querySelector('canvas').captureStream(30),
recorder = new MediaRecorder(stream);
recorder.ondataavailable = e => {
if (e.data.size) {
chunks.push(e.data);
}
};
recorder.onstop = exportVideo;
btn.onclick = e => {
recorder.stop();
btn.textContent = 'start recording';
btn.onclick = record;
};
recorder.start();
btn.textContent = 'stop recording';
}
function exportVideo(e) {
var blob = new Blob(chunks);
var vid = document.createElement('video');
vid.id = 'recorded'
vid.controls = true;
vid.src = URL.createObjectURL(blob);
document.body.appendChild(vid);
vid.play();
}
btn.onclick = record;
// taken from pr.js docs
var x, y;
function setup() {
createCanvas(300, 200);
// Starts in the middle
x = width / 2;
y = height;
}
function draw() {
background(200);
// Draw a circle
stroke(50);
fill(100);
ellipse(x, y, 24, 24);
// Jiggling randomly on the horizontal axis
x = x + random(-1, 1);
// Moving up at a constant speed
y = y - 1;
// Reset to the bottom
if (y < 0) {
y = height;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.min.js"></script>
<button>start recording</button><br>
ccapture 与 p5.js 配合使用可以很好地实现记录 canvas.
上显示的内容的目标这是 demo 与 p5.js 一起使用的 ccapture。 demo自带源码
此方法不会输出延迟的视频,因为它没有记录您在屏幕上看到的内容,这可能会延迟。相反,它将每一帧写入视频并告诉视频以固定帧速率播放。所以即使只计算一帧需要几秒钟,输出的视频也会流畅播放,不会出现帧与帧之间的任何延迟。
但是,有一点需要注意。此方法仅适用于 Chrome.