We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I got a sketch like below. I want to save every frame from the video but the framerate is dropping and processing only process every fourth frame from the videostream and saves it with saveFrame.
How can I process and save every frame? How can I halt the next frame from the videostream until the frame is processed and saved?
Below is a print of the videoFrame from the videostream and the frame that is saved. As you can see only about every fourth frame is processed and saved
VideoFrame: 0 FRAMERATE: 18.936382
savedFrame: 1
VideoFrame: 1 FRAMERATE: 22.489614
VideoFrame: 2 FRAMERATE: 22.489614
VideoFrame: 3 FRAMERATE: 22.489614
VideoFrame: 4 FRAMERATE: 22.489614
VideoFrame: 5 FRAMERATE: 22.489614
VideoFrame: 6 FRAMERATE: 22.489614
savedFrame: 7
VideoFrame: 7 FRAMERATE: 20.717686
VideoFrame: 8 FRAMERATE: 20.717686
VideoFrame: 9 FRAMERATE: 20.717686
VideoFrame: 10 FRAMERATE: 20.717686
savedFrame: 11
VideoFrame: 11 FRAMERATE: 19.62102
VideoFrame: 12 FRAMERATE: 19.62102
savedFrame: 13
VideoFrame: 13 FRAMERATE: 18.655874
VideoFrame: 14 FRAMERATE: 18.655874
VideoFrame: 15 FRAMERATE: 18.655874
savedFrame: 16
VideoFrame: 16 FRAMERATE: 17.817186
VideoFrame: 17 FRAMERATE: 17.817186
VideoFrame: 18 FRAMERATE: 17.817186
VideoFrame: 19 FRAMERATE: 17.817186
savedFrame: 20
VideoFrame: 20 FRAMERATE: 17.098238
VideoFrame: 21 FRAMERATE: 17.098238
savedFrame: 22
VideoFrame: 22 FRAMERATE: 16.579494
VideoFrame: 23 FRAMERATE: 16.579494
Heres my sketch:
import processing.video.*;
Movie m;
int res = 5;
PVector loc;
int frameCounter = 0;
boolean export = false;
int frame = 0;
void settings() {
size(960, 540);
}
void setup() {
m = new Movie(this, "video.mp4");
loc = new PVector(0, 0);
m.play();
m.loop();
background(255);
ellipseMode(LEFT);
}
void movieEvent(Movie m) {
if (m.available()) {
println("VideoFrame: " + frame + " FRAMERATE: " + frameRate);
frame++;
m.read();
}
}
void draw() {
println("savedFrame: " + frame);
run();
}
void run() {
for (int i = 0; i < m.width/res; i++) {
for (int j = 0; j < m.height/res; j++) {
loc.x = i*res;
loc.y = j*res;
color col = m.pixels[(int)loc.x + (int)loc.y * m.width];
noStroke();
fill(col);
ellipse(loc.x, loc.y, res, res);
}
}
if (export && frameCounter < 3600) {
saveFrame("frames/####.png");
frameCounter++;
}
if (frameCounter > 3598) {
println("EXPORT KLAR");
}
}
void keyReleased() {
println("export"+ export + " frameRate: " + frameRate + " frameCounter: " + frameCounter);
if (key == 'e') {
frameCounter = 0;
println("export"+ export + " frameRate: " + frameRate);
export = !export;
}
}
Answers
I solved it like this:
m.speed(frameRate/30); // 30 is the frameRate of the movie
still dropping a frame every now and then though but works until 95%
just don't call run() until you have a movieEvent. you just need to sync the writing with the reading, breaking the usual async nature of the movie stuff.
Hi!
Yes I tried to put the run() function in the movieEvent but this didnt display the processed image
Also tried before with a boolean in the drawmethod that became true when there was a movie event but still the same issue with that it doesnt save every videoframe.
Have you got another suggestion?
i think that last one has a chance of working except for line 5, which i don't think should be there.
but i've not tested this.
I used the following post to get the number of frames: https://superuser.com/questions/84631/how-do-i-get-the-number-of-frames-in-a-video-on-the-linux-command-line
This is what I get:
I run the following and I got all the 371 frames:
Notice that if I choose the speed even to be 0.2, I recorded 370 frames so it missed one.
Kf
This is an eternal common case in Processing when dealing w/ libraries which create their own Thread:
Function run() MUTATES the sketch's canvas. :-O
Only 1 Thread is "authorized" for mutating the canvas: The "Animation Thread"! :>
If we need to mutate the canvas under a foreign Thread, there are 3 options I know about:
boolean
variable, Set ittrue
under the foreign Thread. Then under the "Animation Thread", set it tofalse
& finally mutate the canvas.@koogs whoops, my mistake. forgot to take the run() away. :/ now its working! If Im setting the speed to very slow; m.speed(0.1);
@kfrajer thanks. redraw is doing the same as the boolean. thanks!
@GoToLoop yes, of course. thanks. the video library starts its own thread. I guess number 1., you mean like this:
Dont really get your third option?