I try to get duration of movie create with new GSMovie in setup section but it returns me 0.0. In Draw section no problem but I want to assign duration value to a controlP5.Slider max value in aim to make a seeking video slider from setup section.
Is it a bug or there is a good manner to get duration before draw loop ?
ex :
movie = new GSMovie(this, "movie.mov");
println (movie.duration());
Thanks for GSMovie
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The problem is that the duration of the video stream doesn't get updated until the first frame is read. This is a behaviour of gstremaer and not of gsvideo. I'll check if the latest release of the gstreamer libs changes this.
In the meantime, I suggest you add a boolean variable so you get the duration of the clip when the first read takes place, and set your slide bars accordingly. Look at this code:
During this time I succed in a dirty workaround placing some setup stuff in draw() loop because I figure out reading video in a setup() section doesnt work…strange…I'm a newbie after all ;)
In fact, I try to make a little videoprojection app with videos (in a first step) this is my code (yet ugly, no cool class object by now) :
// workaround of the gstreamer bug
// to get videos durations
notReady = true;
println(movie1.width);
println(movie1.height);
println(movie1.duration());
tex = new GLTexture(this);
tex2 = new GLTexture(this);
// render the sketch using the
// keystoned surface
background(0);
surface.render(offscreen.getTexture());
surface2.render(offscreen2.getTexture());
time();
}
void time() {
int s = second();
int m = minute();
int h = hour();
// The nf() function spaces the numbers nicely
String t = nf(h,2) + ":" + nf(m,2) + ":" + nf(s,2);
textFont(fontTimer);
text(t, 10, 55);
}
// Controls for the Keystone object
void seeking(float thePosition) {
//movie1.jump(thePosition);
}
// Controls Behaviors
class updatePosition extends ControlBehavior {
public void update() {
setValue(movie1.time());
}
}
void keyPressed() {
switch(key) {
case 'c':
// entrer / quitter le mode de calibration, les surfaces peuvent y être
// manipulées.
ks.toggleCalibration();
break;
case 'l':
// loads the saved layout
ks.load();
break;
case 's':
// saves the layout
ks.save();
break;
case 'j':
// jump to 220s in movie1 for testing
movie1.jump(220.0);
break;
}
}
//class MyControlListener implements ControlListener {
// int col;
// public void controlEvent(ControlEvent theEvent) {
// movie1.jump(theEvent.controller().value());
// }
//}
Another question : It is possible to seek in video with GSPipeline ? Because I want this app synced with midi time. Jump() is ok but too slow with HD video (video samples in my sketch were found on apple hd gallery). I try to seek in video with the slider with listener but my code "bites itself" because update slider for each frame make an event…I think..maybe I dont understand.
Voilà. Bye
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for posting your code. I'm glad to know that glgraphics is also useful for your project
In regards to seeking in GSPipeline, unfortunately the functionality is not available, although it does exists inside the gstreamer object wrapped by GSPipeline. I'll include this in the next release of gsvideo.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
I try to get duration of movie create with new GSMovie in setup section but it returns me 0.0. In Draw section no problem but I want to assign duration value to a controlP5.Slider max value in aim to make a seeking video slider from setup section.
Is it a bug or there is a good manner to get duration before draw loop ?
ex :
movie = new GSMovie(this, "movie.mov");
println (movie.duration());
Thanks for GSMovie
The problem is that the duration of the video stream doesn't get updated until the first frame is read. This is a behaviour of gstremaer and not of gsvideo. I'll check if the latest release of the gstreamer libs changes this.
In the meantime, I suggest you add a boolean variable so you get the duration of the clip when the first read takes place, and set your slide bars accordingly. Look at this code:
import codeanticode.gsvideo.*;
GSMovie myMovie;
boolean firstRead = true;
void setup() {
size(640, 480, P3D);
background(0);
myMovie = new GSMovie(this, "station.mov");
myMovie.loop();
}
void movieEvent(GSMovie myMovie) {
if (firstRead) println(myMovie.duration());
firstRead = false;
myMovie.read();
}
void draw() {
tint(255, 20);
image(myMovie, mouseX-myMovie.width/2, mouseY-myMovie.height/2);
}
I hope this helps.
ac
Thank for reply ac,
Ok no pb. I'll try your method.
During this time I succed in a dirty workaround placing some setup stuff in draw() loop because I figure out reading video in a setup() section doesnt work…strange…I'm a newbie after all ;)
In fact, I try to make a little videoprojection app with videos (in a first step) this is my code (yet ugly, no cool class object by now) :
//import promidi.*;
import controlP5.*;
import processing.opengl.*;
import codeanticode.gsvideo.*;
import codeanticode.glgraphics.*;
import deadpixel.keystone.*;
ControlP5 controlP5;
//MyControlListener myListener;
GSMovie movie1, movie2;
GLTexture tex, tex2;
// this object is key! you can use it to render fully accelerated
// OpenGL scenes directly to a texture
GLGraphicsOffScreen offscreen, offscreen2;
Keystone ks, k2;
CornerPinSurface surface, surface2;
// fonts
PFont fontReperage, fontTimer;
boolean notReady;
void setup() {
size(1280, 690, GLConstants.GLGRAPHICS);
// Movies
movie1 = new GSMovie(this, "ac_my_girls_m720p.mov");
movie2 = new GSMovie(this, "ac_summertimeclothes_m720p.mov");
movie1.play();
movie1.loop();
movie2.play();
movie2.loop();
movie2.volume(0);
// workaround of the gstreamer bug
// to get videos durations
notReady = true;
println(movie1.width);
println(movie1.height);
println(movie1.duration());
tex = new GLTexture(this);
tex2 = new GLTexture(this);
// Fonts
fontReperage = loadFont("Ziggurat-32.vlw");
fontTimer = loadFont("Pro-20.vlw");
// GUI
controlP5 = new ControlP5(this);
controlP5.addKnob("volume",0 ,255 ,200, 100, 80, 40) ;
controlP5.addToggle("mute",false,170,100,20,20);
// myListener = new MyControlListener();
// controlP5.controller("seeking").addListener(myListener);
}
void draw() {
// Waiting for reading videos properties
while (notReady == true){
println("please wait…");
if (movie1.available() && movie2.available()){
// set some GUI elements and surface dimensions
if ((1 < movie1.width) && (1 < movie1.height) && (0.0 < movie1.duration())) {
println("OK");
controlP5.addSlider("seeking",0,movie1.duration(),0,100,20,300,9);
controlP5.controller("seeking").setBehavior(new updatePosition());
// Offscreen buffers
offscreen = new GLGraphicsOffScreen(this, movie1.width, movie1.height);
offscreen2 = new GLGraphicsOffScreen(this, movie2.width, movie2.height);
// Surfaces
ks = new Keystone(this);
surface = ks.createCornerPinSurface(movie1.width ,movie1.height, 8);
surface2 = ks.createCornerPinSurface(movie2.width ,movie2.height, 8);
// can exit
notReady = false;
}
movie1.read();
movie2.read();
}
}
// convert
PVector mouse = surface.getTransformedMouse();
if (movie1.available() && movie2.available()){
movie1.read();
movie2.read();
tex.putPixelsIntoTexture(movie1);
tex2.putPixelsIntoTexture(movie2);
offscreen.beginDraw();
offscreen.beginShape();
offscreen.texture(tex);
offscreen.vertex(0, 0, -10, 0, 0);
offscreen.vertex(movie1.width, 0, -10, 1280, 0);
offscreen.vertex(movie1.width, movie1.height, -10, 1280, 690);
offscreen.vertex(0, movie1.height, -10, 0, 690);
offscreen.endShape();
offscreen.fill(250);
offscreen.textFont(fontReperage);
offscreen.textSize(128);
offscreen.text("1", width / 2, height / 2);
offscreen.endDraw();
offscreen2.beginDraw();
offscreen2.beginShape();
offscreen2.texture(tex2);
offscreen2.vertex(0, 0, -10, 0, 0);
offscreen2.vertex(movie2.width, 0, -10, 1280, 0);
offscreen2.vertex(movie2.width, movie2.height, -10, 1280, 690);
offscreen2.vertex(0, movie2.height, -10, 0, 690);
offscreen2.endShape();
offscreen2.fill(250);
offscreen2.textFont(fontReperage);
offscreen2.textSize(128);
offscreen2.text("2", width / 2, height / 2);
offscreen2.endDraw();
}
// render the sketch using the
// keystoned surface
background(0);
surface.render(offscreen.getTexture());
surface2.render(offscreen2.getTexture());
time();
}
void time() {
int s = second();
int m = minute();
int h = hour();
// The nf() function spaces the numbers nicely
String t = nf(h,2) + ":" + nf(m,2) + ":" + nf(s,2);
textFont(fontTimer);
text(t, 10, 55);
}
// Controls for the Keystone object
void seeking(float thePosition) {
//movie1.jump(thePosition);
}
void mute(boolean theFlag) {
if(theFlag==true) {
movie1.volume(0);
} else {
movie1.volume(1);
}
}
void volume(float theVolume) {
movie1.volume(map(theVolume, 0 ,255 ,0.0 ,1.0));
}
// Controls Behaviors
class updatePosition extends ControlBehavior {
public void update() {
setValue(movie1.time());
}
}
void keyPressed() {
switch(key) {
case 'c':
// entrer / quitter le mode de calibration, les surfaces peuvent y être
// manipulées.
ks.toggleCalibration();
break;
case 'l':
// loads the saved layout
ks.load();
break;
case 's':
// saves the layout
ks.save();
break;
case 'j':
// jump to 220s in movie1 for testing
movie1.jump(220.0);
break;
}
}
//class MyControlListener implements ControlListener {
// int col;
// public void controlEvent(ControlEvent theEvent) {
// movie1.jump(theEvent.controller().value());
// }
//}
Another question : It is possible to seek in video with GSPipeline ? Because I want this app synced with midi time. Jump() is ok but too slow with HD video (video samples in my sketch were found on apple hd gallery). I try to seek in video with the slider with listener but my code "bites itself" because update slider for each frame make an event…I think..maybe I dont understand.
Voilà. Bye
Thanks for posting your code. I'm glad to know that glgraphics is also useful for your project
In regards to seeking in GSPipeline, unfortunately the functionality is not available, although it does exists inside the gstreamer object wrapped by GSPipeline. I'll include this in the next release of gsvideo.