playing 2 videos at the same time

edited August 2015 in Library Questions

Hello, I'm trying to work on a sketch that plays 2 videos at the same time. Before diving deeper into this project I've already found an issue. (well, I should've seen that coming)

When I try to play 2 videos at the same time, they start to jitter a lot So I was wondering if there are any workarounds to this, keeping in mind that 2 videos still need to be played at the same time.

thanks!

import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;

import processing.video.*;

int play_clip;

//Movie clip_a;
Movie[] clip = new Movie[5];

void setup()
{
  size(720, 480);
  frameRate(24);
  imageMode(CENTER);

  play_clip = 1;

  //clip_a = new Movie(this, "clip_a.mp4");
  for ( int i = 1; i < 5; i++)
  {
    String clip_name = "clip" + (i) + ".mp4";
    clip[i] = new Movie(this, clip_name);
  }
}

void draw()
{
  //clip_a.width

  clip[1].play();
  clip[1].read();
  image(clip[1], width/4, height/4);

  clip[3].play();
  clip[3].read();
  image(clip[3], width/2 + width/4, height/2);

  if (keyPressed)
  {
    if (key == '1')
    {
      play_clip = 1;
    } else if (key == '2')
    {
      play_clip = 2;
    } else if (key == '3')
    {
      play_clip = 3;
    } else if (key == '4')
    {
      play_clip = 4;
    }
  }
}

Answers

  • I don't really think that this is a processing issue. It could be your own computer and its "Virtualization" feature. Make sure that is turned on, it could help. Look online for your specific computer to see how to check if that is on.

  • @TechWiz777 yeah, I've checked but it's on.

    @GoToLoop woah thanks for this sketch. I'm having a bit of a hard to trying to understand what exactly is happening on the sketch so I can go on to adapt it to my own code. Could you give me just a run through of what is happening on your logic there?

    specially when it gets to "loadClip" functions and after, I'm still a bit confused on how gstream handles the data.

    /**
     * Preloaded Clips (v3.13)
     * by GoToLoop (2014/Nov/18)
     *
     * forum.processing.org/two/discussion/8109/
     * prepare-a-second-video-to-play-
     * without-slowing-down-the-first-video
     */
    
    import processing.video.Movie;
    
    import org.gstreamer.Bus.EOS;
    import org.gstreamer.GstObject;
    
    final EOS finished = new EOS() {
      @ Override void endOfStream(GstObject gst) {
        transferLoadedToActive(int(gst.get("name").toString()));
      }
    };
    
    static final String EXT = ".mp4";
    static final int FPS = 30, MARGIN = 8, PAUSE = 1000/FPS;
    static final int NUM = 2, QTY = 5, A = 0, B = 1;
    
    final Movie[] clips = new Movie[NUM], loads = new Movie[NUM];
    final int[] x = new int[NUM], y = new int[NUM];
    
    boolean isPlaying = true;
    
    void setup() {
      size(1280, 800, JAVA2D);
    
      noSmooth();
      noLoop();
      frameRate(FPS);
    
      transferLoadedToActive(A);
      transferLoadedToActive(B);
    }
    
    void draw() {
      set(x[A], y[A], clips[A]);
      set(x[B], y[B], clips[B]);
    }
    
    void keyTyped() {
      if (isPlaying ^= true) {
        clips[A].play();
        clips[B].play();
      } else {
        clips[A].pause();
        clips[B].pause();
      }
    }
    
    void mousePressed() {
      keyTyped();
    }
    
    void movieEvent(Movie m) {
      m.read();
      redraw();
    }
    
    static final int toIdx(int id) {
      return (short) id;
    }
    
    static final int toNum(int id) {
      return id>>>020;
    }
    
    Movie loadClip(int id, String name) {
      Movie m = new Movie(this, name);
      m.playbin.set("name", id);
      m.playbin.getBus().connect(finished);
      println(name, "loaded  for index", toIdx(id));
      return m;
    }
    
    Movie preloadRandomClip(int id) {
      int rnd, idx = toIdx(id), num = QTY>1? toNum(id) : -1;
      while  (num == (rnd = (int)random(QTY) + 1));
      return loads[idx] = loadClip(idx | rnd<<020, rnd + EXT);
    }
    
    Movie transferLoadedToActive(int id) {
      int idx = toIdx(id);
      if (loads[idx] == null)  preloadRandomClip(id);
    
      Movie old = clips[idx], now = clips[idx] = loads[idx];
      if (isPlaying)    now.play();
      if (old == null)  while (now.width == 0)  delay(PAUSE);
    
      centralizeClip(idx);
      println(now.filename, "started for index", idx);
    
      id = int(now.playbin.get("name").toString());
      preloadRandomClip(id);
    
      if (old != null)  old.dispose();
      return now;
    }
    
    Movie centralizeClip(int id) {
      int idx = toIdx(id);
      Movie m = clips[idx];
      x[idx] = idx == A? MARGIN : width - m.width - MARGIN;
      y[idx] = height - m.height >> 1;
      clear();
      return m;
    }
    
  • Could you give me just a run through of what is happening on your logic there?

    • Yikes! That was some hackish thing I did half year ago.
    • And can't remember very well how I did it! :(|)
    • But I don't even know whether you were able to successfully run it btW. :-@
    • Constant QTY represents how many Movie files are present in the dataPath("").
    • W/ QTY = 5 & EXT = ".mp4", they should be named from "0.mp4" up to "4.mp4".
    • NUM is how many Movie files play() at the same time.
    • clips[] is current displayed Movie streams. While loads[] is pre-loaded 1s.
  • edited May 2015
  • edited May 2015
    • Most complicated part is the id of a Movie I've made up. :-\"
    • Even though it's 1 parameter, it actually stores 2 values:
    • The idx for clips[] & loads[] and the num for the Movie file itself.
    • Since we only got 2 Movie streams playing at the same time, idx is either 0 or 1.
    • While num varies between 0 & QTY-1.
    • The "welding" of idx & num happens inside preloadRandomClip() as:
      loadClip(idx | rnd<<020, rnd + EXT); -> idx | rnd<<020.
    • And finally transferred into a new Movie inside loadClip() as:
      m.playbin.set("name", id);
    • The id is recovered later on inside the callback in finished:
      transferLoadedToActive(int(gst.get("name").toString())); -> gst.get("name").
    • And there are 2 util functions which split the id back to either idx or num: toIdx() & toNum().

    For now that's it. Any doubts, specifically ask for them again. Take care! B-)

  • edited May 2015

    I'll thank you (again) beforehand since I think it's best for me to get a better grasp of those functions first instead of just asking everything blindly.

    But I don't even know whether you were able to successfully run it btW.

    hehe, apologies for my lack of information, I haven't been able to run it yet. Actually, it says I don't have a library for the gstreamer stuff and I'm struggling to find it (I know, it's dumb, and I actually downloaded many things already, none of them were actually a processing library)

    But working or not, the thing is that now I have to read a little more about those things, that way I can adapt it to my own logic (instead of just copying your work).

    Finally, a bit more info about my sketch: my objective with this(part) is to create a basic vj software.. kinda. If I'm able to have two video slots always available to play, I can have better transitions between videos (instead of just having dry cuts with a single .read video slot). Also, this is all manual, meaning that I choose which video is playing, when to fade etc etc. If you go back to the first sketch in this post you can see a raw logic of selecting videos from an array of files.

    Hope this makes everything clear and thanks again :)

Sign In or Register to comment.