1

I'm trying to play one of two videos based on sensor from Arduino (for a University project)

The issue is that I can't see any of the videos in Processing but I only hear the audio.

I rendered the videos using the H264 codec and they are in Full HD. I am using Processing 4.1.1.

This is my attempt at playing back video based on sensor values:


import processing.serial.*;
import processing.video.*;

Movie movie1, movie2;
boolean playing = false;
char previousIn;




Serial mySerial;

String myString = null;
int nl = 10;
float myVal;

void setup() {

  size(1000, 1000);
  frameRate(25);



  String myPort =Serial.list()[2];
  mySerial = new Serial(this, myPort, 9600);
  movie1 = new Movie(this, "Final_Clips_HD.mp4");
  movie2 = new Movie(this, "Final_Clips_HD_2.mp4");
}




void movieEvent(Movie movie) {
  movie.read();
}

void draw() {


  while (mySerial.available() > 0) {
    myString = mySerial.readStringUntil(nl);

    if (myString != null) {

      myVal = float(myString);
      println(myVal);




      if (myVal > 10 && myVal < 20) {
        movie1.play();
        movie2.stop();
        myVal = previousIn;
        if (myVal == previousIn) {
          movie1.jump(0);
        }
      }
      image(movie1, 0, 0, width, height);


      //fill(0,255,0);
      if (myVal < 10 && myVal > 0) {
        movie2.play();
        movie1.stop();
        myVal = previousIn;
        if (myVal == previousIn) {
          movie2.jump(0);
        }
      }
      image(movie2, 0, 0, width, height);
    }
  }
}

George Profenza
  • 50,687
  • 19
  • 144
  • 218

1 Answers1

2

You've got all the "ingredients" right, you might just need to shuffle them a bit. Well done on using H264 with Processing (I've seen previous errors with other video codecs) (and checking for null, etc.)

Currenty the movies are played only if there is a serial connection, a formatted string (sensor value) is sent and that value is within a range.

I would re-organise the code slightly so it can display a movie frame anytime (whatever that movie may be), then simply change the reference to the movie which is currently updated (based on the float value from serial).

(Additionally I'd also check for errors just in case the arduino isn't connected, is busy open in Serial Monitor, etc. Another minor tip is that yuo can use bufferUntil() once in setup and after that, just readString() from serialEvent()).

Here's a revised version of your code (with comments):

import processing.serial.*;
import processing.video.*;

Movie movie1, movie2;
Movie currentMovie;
boolean playing = false;

Serial mySerial;

// sensor values (current and previous)
float myVal;
float previousIn;

void setup() {

  size(1000, 1000);
  frameRate(25);

  String myPort = Serial.list()[2];
  // try to open the serial connection, but print error message if it fails
  try{
    mySerial = new Serial(this, myPort, 9600);
    // tell arduino once to buffer until new line character is found
    mySerial.bufferUntil('\n');
  }catch(Exception e){
    println("error opening serial connection to " + myPort);
    e.printStackTrace();
  }

  // load movies
  movie1 = new Movie(this, "Final_Clips_HD.mp4");
  movie2 = new Movie(this, "Final_Clips_HD_2.mp4");
  // reference one of the movies for updating
  currentMovie = movie1;
}




void movieEvent(Movie movie) {
  movie.read();
}

void draw() {
  // render the current movie
  image(currentMovie, 0, 0);
}

void serialEvent(Serial mySerial){
  String myString = mySerial.readString();
  if (myString != null) {
    myVal = float(myString);
    println(myVal);
    
    if (myVal > 10 && myVal < 20) {
      movie1.play();
      movie2.stop();
      myVal = previousIn;
      if (myVal == previousIn) {
        movie1.jump(0);
      }
      // update reference to the currently playing movie
      currentMovie = movie1;
    }
    
    if (myVal < 10 && myVal > 0) {
      movie2.play();
      movie1.stop();
      myVal = previousIn;
      if (myVal == previousIn) {
        movie2.jump(0);
      }
      // update reference to the currently playing movie
      currentMovie = movie2;
    }
    
  }
}

Note that the above code isn't tested, so may not be 100% accurate: hopefully it illustrates the logic.

George Profenza
  • 50,687
  • 19
  • 144
  • 218
  • Thanks for your help, now I can see the video when ( myVal < 10 && myVal > 0 ). but when (myVal > 10 && myVal < 20) then I get this error: "Seek operation failed" in the processing console and I can't see the other video and I can't hear it. Do you have a suggestion for me – Mirey Asaous Jan 06 '23 at 11:08
  • Interesting error: I don't recall bumping into that one. I suggest doing using a separate sketch to isolate the issue: is it a video codec/playback issue with the video library or is it related to the sketch for some reason (unlikely as far as I can read the code). Can you try opening *Processing > Examples > Libraries > Video Library for Processing > Movie > Frames * (or Loop and add the `jump(0);` call in `setup()`) ? If that works with the existing sample video, then tweak the sketch to use the video that fails in your sketch: if the sample video works, but your video fails could be codec. – George Profenza Jan 09 '23 at 10:41