Help with text and video

Hello everyone, I need to solve this and I’ve been trying for several hours now. I’m learning how to code. This is the code that I’m working on that starts of with one of the coding train challenges. What I want to do is that as soon as the video finishes another starts playing but it seems that it is playing all at once after the first one. The other issue seems to be that I can’t get the video to fill the entire screen. I could do it with image() function, but what I want is the color data from the video, not the image. Finally I would like to stop the whole thing for a moment and put some white text on a black screen, then keep on going. Sorry for my bad english. I really hope you can help me
Here is the code:

import processing.video.*;

String[] datos ;
IntDict numpalabras ;



int numMovies = 6;//total number of movies
Movie[] playlist = new Movie[numMovies];//a list of all the movie objects, currently not initialized
int currentMovieIndex = 0;//index of the movie currently playing

float movieEndDuration = 0.029719;//a 'magic number' helpful to find out when a movie finishes playing

void setup() {

  //size(600, 600);
  fullScreen();
  background(0);
  String[] libro = loadStrings("1.txt"); //carga el libro
  //printArray(libro);
  String completo = join(libro, " ");//lo convierte en solo una línea
  //println(completo);
  datos = splitTokens(completo, ",.!?:)( "); // lo devuelve a un array por palabras
  //printArray(palabras);
  frameRate(16);

  numpalabras = new IntDict();//emparejar datos del array con strings

  for (int i= 0; i<datos.length; i++) {
    String bla = datos[i].toLowerCase();
    if (numpalabras.hasKey(bla)) {
      numpalabras.increment(bla); //sumatoria por cada palabra repetida
    } else {
      numpalabras.set(bla, 1);//palabra nueva
    }
  }
  //myMovie = new Movie(this, "video/1.MOV");
  //myMovie.play();
  //myMovie.volume(0);
  for(int i = 0 ; i < numMovies; i++){
    //initialize each movie object in the list
    playlist[i] = new Movie(this,"video/"+(i+1)+".MOV");//new Movie(this, "ch"+(i+1)+".mp4");
  }
  //start playback
  playlist[currentMovieIndex].play();
  playlist[currentMovieIndex].volume(0);
}

void movieEvent(Movie m) {
  m.read();
  //handy for debugging and figuring out the 'magic number'
  println(m.time() + " / " + m.duration() + " / " + (m.time() + movieEndDuration));
  //hacky check movie end 
  if((m.time() + movieEndDuration) >= m.duration()){
      println("movie at index " + currentMovieIndex + " finished playback");
      //go to the next movie index
      currentMovieIndex = (currentMovieIndex+1) % numMovies;//increment by one buy use % to loop back to index 0 when the end of the movie array is reached
      //use this to tell the next movie in the list to play
      playlist[currentMovieIndex].play();
      println("movie at index " + currentMovieIndex + " started");
  }
  //m.read();
  //if (myMovie.time() == myMovie.duration()) { //movie must be finished
  //}
}


void draw() {

  fill(0, 100);
  rect(0, 0, width, height);

  String[] llaves = numpalabras.keyArray(); //copia de las palabras
  for (String llavero : llaves) { //iteración arrays entre "palabra : cant palabra"

    int cont = numpalabras.get(llavero); //asignar cantidad de palabra repetida a variable
    float tam = map (cont, 1, 2171, 7, 200);
    textSize(tam);
    float x=random(width);
    float y = random(height);
    color c= playlist[currentMovieIndex].get(int(x), int(y));
    fill(c);
    text(llavero, x, y);
  }
}```

If you see any huge mistakes please let me know :slight_smile:

Am I missing something @gohai or does the video library not expose either the EoS event or the playing flag?

It does look from the source code as if you can access the PlayBin element though. So possibly -

boolean playing = m.playbin.isPlaying();

will tell you if the video has finished or not. You also probably want to move that logic to draw() as you’ll stop getting movie events when the playing stops.

1 Like

@neilcsmith The Movie class has a member playing which is gets set to false in endOfStream (source). Hth!

90% of those fields are protected! :zipper_mouth_face:

1 Like

I see. Perhaps there is then really no way of getting this information directly. Guessing one could make use of .time() to repeatedly query the playback position…

@gohai You think it would be possible to add isPlaying() to access that field? This would be a simple PR that anybody could do in github but not sure if there are other considerations when introducing changes to this library. For instance, is the field working?

Kf

/**
 * Hacked Movie isPlaying() (v1.0)
 * GoToLoop (2018/Jul/28)
 * Discourse.Processing.org/t/help-with-text-and-video/2104/9
 */

import processing.video.Movie;
Movie vid;

void setup() {
  frameRate(30);
  textSize(050);
  textAlign(CENTER, BASELINE);
  fill(#FFFF00);

  vid = new Movie(this, "transit.mov") {
    @Override public boolean hasBufferSink() {
      return playing;
    }
  };

  vid.play();
  while (vid.width == 0 | vid.height == 0)  delay(10);

  getSurface().setSize(vid.width, vid.height); // P3
  //size(vid.width, vid.height); // P2
}

void draw() {
  if (vid.hasBufferSink())  background(vid);
  else {
    background((color) random(#000000));
    text("Playback has finished!", width>>1, height>>1);
  }
}

void movieEvent(final Movie m) {
  m.read();
}
2 Likes

@kfrajer I’ve only contributed a few patches (mainly trying to convert it to the modern version of GStreamer), but I did not originally write the code, or maintain it.

I don’t think it would hurt to send a PR that made the field public, or introduced a playing() method. Please always consider sending patches when coming across minor omissions like this. I think the less intrusive the change, and the more obvious it is, the higher the chances that it will get pulled in. (Worst case it isn’t, but even then it would still be the strongest, and nicest signaling to the developer to implement something to the same effect. Because clearly you cared enough to at least give it a try…)

But it could also be that the library is bound to be rewritten from the ground up eventually. The Processing Foundation offered this as a possible subject of a GSoC fellowship this year, but ultimately no project came out of it.

@gohai I am just surprise this was not proposed before. I mean, I imagine making this change would make things easier to many developer and specially for beginners. I am thinking to myself there must be something big underneath that is stopping this change. That is why I ask. I am not familiar with the Movie library. I will have a look at it and proceed with the PR.

Kf

Thanks @gohai wondered if I’d missed something. Yes the problem is it’s all protected. Although the PlayBin is public (oddly) and already has this method. In terms of a rewrite, if the plan is sticking with GStreamer I’m happy to work on that.

@kfrajer if you do a PR make it a method. It really needs to be read only.

I have created an issue in GH here. However, I noticed this request was already mentioned few years ago. There is even a PR in the Processing-Video repo that didn’t get merged. I decided not to create a PR to avoid clutter and confusion. The github ticket should be enough for now.

Kf

2 Likes

@kfrajer Thanks for digging this PR up. I am going to close your issue in the Processing repo, though, as we try to keep the issues local to each repository (i.e. issues related to documentation or examples go to processing-docs, Video to processing-video, Android to processing-android, and so on). Cause otherwise everything just ends up in Ben’s inbox.

@gohai My apologies… I just realized that there was another repo holding the video src. It was too late when I submitted the tix. Thxs for taking care of it.

I hear that the lib is gonna be written again. Do you think you could comment about it? My understanding from prev posts, there is a new gstreamer? You just need to build the wrapper? Tagging also @neilcsmith

Would the new library also support the old library? Or would that be part of the plan?

Kf

Depends what you mean by wrapper? The Java bindings for GStreamer 1.x exist, and have done since 2015 when I took them over as part of work on PraxisLIVE. They’re in use in a lot of other things too now, and are semi-official. I’m aiming to get a stable version 1 of them released before the GStreamer conference in October, although they’re in better condition than the old bindings for GStreamer 0.10 already.

The video library needs updating to use them - @gohai started that work and there’s a beta version in master. However, it might be better to rewrite from scratch.

I’m considering how easy it would be to convert the GStreamer components of PraxisLIVE v4 into a Processing library (eg. this player) These are obviously rendering into Processing, but I’d need to remove the PraxisLIVE extensions. I’d consider it a good base, though, as it’s getting a fair bit of testing and doesn’t have some major issues that the video library has.

GStreamer 0.10 and GStreamer 1.x are parallel installable, and I specifically made the bindings parallel installable too. However, GStreamer 0.10 is dead! The better plan would be to rewrite the library and update the API. eg. I find it really odd conceptually that a Movie is a PImage, rather than has a sequence of PImages (frames) - the whole m.read() thing forces a situation where the library is not as efficient as it could be, and likewise the movieEvent callback as currently used is problematic (the player linked above actually queues all control of GStreamer into the library so you don’t block the rendering thread, and also queues all callbacks back into the rendering thread so you don’t have race conditions).

That’s probably more info than belongs in this thread! :smile: Maybe we should discuss elsewhere?