spite / ccapture.js

A library to capture canvas-based animations at a fixed framerate
MIT License
3.58k stars 410 forks source link

Does it work with p5.js? #69

Open Kubi1992 opened 6 years ago

Kubi1992 commented 6 years ago

Hi! When I try to capture my little p5.js project, the animation doesn't work. Did I set up everything correctly or does it just not work in p5.js? Thanks!

let t = 0;
let n = 20;
let canvas;
let buttonStartRec;
let buttonStopRec;

let capturer = new CCapture({
  format: 'webm',
  name: 'test'
});

function setup() {

  canvas = createCanvas(500, 500);

  buttonStartRec = createButton('start');
  buttonStartRec.mousePressed(capturer.start);

  buttonStopRec = createButton('stop');
  buttonStopRec.mousePressed(capturer.stop);
  buttonStopRec.mousePressed(capturer.save);

}

function draw() {
  requestAnimationFrame(draw);
  background(10, 30, 35, 150);
  translate(width / 2, height / 2);

  stroke(255);
  strokeWeight(7);

  stroke(255, 100);
  strokeWeight(4);
  for (i = 0; i < n; i++) {
    stroke(255, 10 + 15 * i);
    line(x11(t + i), y11(t + i), x12(t + i), y12(t + i));
  }

  t = t + 0.28;

  capturer.capture(canvas);
}

function x11(t) {
  return cos(t / 15) * 220;
}

function y11(t) {
  return sin(t / 15) * 100;
}

function x12(t) {
  return sin(t / 10) * 200;
}

function y12(t) {
  return cos(t / 10) * 250 + sin(t / 10) * 150;
}
spite commented 6 years ago

I'm not familiar with p5.js, a working online example would help. The fist thing i see is "frameRate(45);", what does that do? It feels like it could be also handling the animation frame timing, as CCapture does...

Kubi1992 commented 6 years ago

You are right, "frameRate(45)" shouldn't be there, I forgot to delete this line. Deleting the line doesn't change the behaviour however. The thing is, the instructions tell me to put code in my "render()" method, which I don't have. In p5.js there is a "draw()" method by default, is this the same thing? Also I don't know how to refer to the canvas, since I create the canvas without giving it a variable name...

spite commented 6 years ago

yes, render method is where you draw, where you update the canvas, so draw() should be fine. If you can´t refer the canvas, then that´s a problem, because CCapture needs access to the canvas to get the frame contents. So I guess the first thing would be to find how to get the reference to the canvas from p5js...

Kubi1992 commented 6 years ago

Ok so apparently you can easily reference the canvas. I also added buttons to start/stop the recording. Now the animation freezes when I press the start-button. I also noticed that "requestAnimationFrame(draw);" speeds up the animation a lot. Did I put "requestAnimationFrame(draw);" and "capturer.capture(canvas);" at the right place in the code??

piebro commented 6 years ago

I had the same problem, but if I set the framerate in p5.js to something high like 120 it worked for me. I dont know if that is practical for you but this way it worked for me. For everyone else reading this, you can reference the p5.js canvas with document.getElementById("defaultCanvas0")

dasilvacontin commented 6 years ago

@Kubi1992 Did you try without requestAnimationFrame? I believe p5.js is already calling that function for you behind the scenes.

AntoineBath commented 6 years ago

Hi Kubi1992, most likely you have it working by now, but for reference. I'm using Chrome. first to have the capturer.start working without freezing your drawing I had to separate them into 2 different functions: //launch the render function function scene(){ ready = true; render(); capturer.start(); } function render(){ animation(); } To add to piebro comment you need to do var container = select('#defaultCanvas0'); capturer.capture(container.elt); otherwise I was getting t.toBlob is not a function Finally I can only use capturer.save() once I did capturer.stop() here is my code, it is still under construction but it took me 1 week to be able to get the ccapture working :laughing:

//program variables var howto; //text explaining how to use the tool //font var fontName; //name of the font file var changeFont; //button to validate the name of the file var userFont = false; //control to see if a font file was loaded var fontSize = 45; //color var subPaint; //color of the subtitles var choosePaint; //button to validate the color //subtitle location var startX; //where the text start on x axis var startY; //where the text start on y axis var local; //button to validate x and y var rightMarge; var bottomMarge; var xline; var yline; var interCharacterGap = 35;

//subtitle frame //TBD

//fps and wpm for the video that will be subbed var fps; //video frame per second var fpm; //frame per minute var wpm; //word per minute var fpw; //frame per word var fpl; //frame per letter var writeLetter = 0; //used to count frame to write a new letter var vspeed; //button video speed validation

//subtitles var subs; //subtitles var w = []; //array of words var l = []; //array of letters var lw; //avg of letters per word
var submit; //button to submit the subtitles var written = []; //array receiving letters of the subtitle 1 by 1 var lValue; var letterNumber = 0; //increased by 1 after each draw loop

//animation var preview; //to preview on the canvas var ready = false; //used to lauch the subtitle rendering var duration; // video duration in secondes var timing = 0; //time in seconde

//CCapture variables var canvas; //used to create the canvas and child it var containing; //select the canvas var capturer = null; // used to generate the png of the animation

//user settings functions

//font file need to be placed in the same folder as project function userFontName() { userFont = true; fontName = document.getElementById("fontName"); fontRegular = loadFont(fontName.value); console.log(fontName.value); }

//user can choose the color of the subtitles text function paint() { var col = document.getElementById('paint'); subPaint = "'#" + col.value + "'"; console.log("Font Color: " + subPaint); }

//user can select where the subtitles appear in the canvas (canvas top left = 0 pixel X, 0 pixel Y) function localization(){ var idx = document.getElementById('startX'); startX = Number(idx.value); var idy = document.getElementById('startY'); startY = Number(idy.value); console.log("location x: " + startX,"location y: " + startY); }

//user indicate the speed of the video, and how many word are said per minute (English avg is 140 wpm) function videoSpeed(){ var frame = document.getElementById('fps'); fps = Number(frame.value); frameRate(fps); var word = document.getElementById('wpm'); wpm = Number(word.value); console.log("FPS: " + fps,", Word per minute: " + wpm); //transform fps to fpm fpm = fps * 60; //calculate frame per word fpw = Math.floor(Number(fpm / wpm)); console.log("frame per word: " + fpw);
}

//User can set 2 subtitles bacground to do a frame, if none then set value to 0,0,0,0 for transparent //TBD

//User subtitles, divided into letters and set to canvas size !!!! need to be modified to fit subtitle backgrounds function newText() { rightMarge = width - fontSize2.5; bottomMarge = height - (fontSize + 10); background('rgba(255,255,255,0)'); fill('#ff8800');//color of background 1 noStroke(); rect(670,830,1200,240); //orange rectangle subtittle background 1 fill('#2f2e2e');//color of background 2 noStroke(); rect(680,840,1180,220); //grey rectangle subtittle background 2 l = []; written = []; w = subs.value.split(' '); l = subs.value.split(''); lw = Number(Math.ceil(l.length/w.length)); fpl = Math.ceil(fpm/(wpmlw)); duration = Math.ceil(Number(l.length*fpl)); xline = startX; yline = startY; for (var i=0; i<=l.length; i++){
if (l[i] == "\n"){ // check if the character is cariage return yline = yline + fontSize; xline = startX + interCharacterGap; lValue = l[i]; written[i] = new Typing(lValue, xline, yline); }else if (xline >= rightMarge) { //check if the letters are reaching right side of the page yline = yline + fontSize; xline = startX + interCharacterGap; lValue = l[i]; written[i] = new Typing(lValue, xline, yline); }else if (yline >= bottomMarge) { //check if the letters are reaching the bottom of the page yline = startY; xline = xline + interCharacterGap; lValue = l[i]; console.log("y back to start"); written[i] = new Typing(lValue, xline, yline); }else {
xline = xline + interCharacterGap; yline = yline; lValue = l[i]; written[i] = new Typing(lValue, xline, yline); } //console.log(written.length); } }

//function to have the characters positions function Typing(symbol, x, y) { this.sym = symbol; this.x = x; this.y = y; }

//launch the render function function scene(){ ready = true; render(); capturer.start(); }

function render(){ animation(); }

function animation() { if(ready){ if (timing < duration+3) { if(writeLetter >= fpl) { writeLetter = 0; console.log("reset writeLetter"); var j=letterNumber; letterNumber ++; timing = letterNumber*fpl; console.log(timing,duration); if(letterNumber > l.length) { console.log('false'); ready = false; capturer.stop(); console.log('stp'); capturer.save(); console.log('save'); clear();
} else { if(written[j+1].y - written[j].y < 0) { fill('#ff8800');//color of background 1 noStroke(); rect(670,830,1200,240); //orange rectangle subtittle background 1 fill('#2f2e2e');//color of background 2 noStroke(); rect(680,840,1180,220); //grey rectangle subtittle background 2 console.log("clean square"); fill(subPaint); textFont(fontRegular, fontSize); text(written[j].sym, written[j].x, written[j].y); console.log(written[j]); } else { fill(subPaint); textFont(fontRegular, fontSize); text(written[j].sym, written[j].x, written[j].y); console.log(written[j]); } } } else { writeLetter ++; } containing = select('#defaultCanvas0'); capturer.capture(containing.elt); requestAnimationFrame(animation); } else { capturer.stop(); console.log('stp'); capturer.save(); console.log('save'); clear(); } }

}

//initial situation function setup() { canvas = createCanvas(1920,1080); canvas.parent('canvas');

capturer = new CCapture({
    framerate: fps,
    format: 'png',
    autoSaveTime: 30
}  );

frameRate(fps);

//User settings
howto = document.getElementById("howto");

howto.innerHTML += How to: First paste your subtitles in the text box, 1 line = 1 subtitle line then click on "Submit"; howto.innerHTML += Place the font file in the same folder than SubGen.html on your computer, and write the name of the file in the text box and click on "Change Font"; howto.innerHTML += Choose a color in hex value, click on "Choose Color" to validate; howto.innerHTML += Enter the x and y location, where the subtitles should start and click on "Location";

changeFont = select('#changeFont'); changeFont.mousePressed(userFontName);

choosePaint = select('#col'); choosePaint.mousePressed(paint);

local = select('#local'); local.mousePressed(localization);

vspeed = select('#vspeed'); vspeed.mousePressed(videoSpeed);

subs = document.getElementById("subtitles"); subs.style.height = "200px"; subs.style.width = "400px";

submit = select("#submit"); submit.mousePressed(newText);

preview = select("#preview"); preview.mousePressed(scene); }

okliis commented 6 years ago

Hello @Kubi1992 , did you figure it out in the end? My sketch is also freezing after pressing the start button. Then, when I press save it says: 'Width and height must be set prior to rendering.' Any help is appreciated. Thanks.

pbeshai commented 5 years ago

I just put together a brief blog on how I used CCapture.js with p5.js.

Hope this helps!

sametcodes commented 5 years ago

I've created a class for p5.js, you can try it. https://github.com/selmansamet/p5-recorder

GoToLoop commented 5 years ago

https://github.com/spite/ccapture.js/issues/91#issuecomment-455809578

hugocpolos commented 4 years ago

I had the same problem. What i did to solve was running my p5 application from a local web server instead of opening the files directly at the browser.

aevin-io commented 3 years ago

i had the same issue and commenting out frameRate(30); seem to do the trick