# Video delay effect, adjustable delay time

**URL:** <https://discourse.processing.org/t/video-delay-effect-adjustable-delay-time/43067>\
**Category:** Libraries\
**Created:** [October 26, 2023, 4:35pm UTC](https://discourse.processing.org/t/video-delay-effect-adjustable-delay-time/43067 "2023-10-26T16:35:17Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ilya.z](https://avatars.discourse-cdn.com/v4/letter/i/e95f7d/32.png) [@ilya.z](https://discourse.processing.org/u/ilya.z)\
**Post date:** [October 26, 2023, 4:35pm UTC](https://discourse.processing.org/t/video-delay-effect-adjustable-delay-time/43067/1 "2023-10-26T16:35:17Z")

</div>

I want to create a (live) video delay effect with adjustable delay time.  
(tweaking delay time with mouseX).

_ **Works ok at start, but then delayed image suddenly disappears.** _

Two video images: one without delay, and on top a delayed one.  
For the latter I use a buffer, playhead continuously running between frame[0] and a middle point (adjustable), and then looping back to frame[0]:

```auto
import processing.video.*;

Capture cam;
PImage[] buffer;

int nFrames = 60; // 2" max buffer length (at 30 fps)
int iWrite = 0, iRead = 1;
int adjust_buf;
int bufSize;

void setup() {
  size(640, 480);
  cam = new Capture(this, 640, 480);
  cam.start(); // start reading from camera
  buffer = new PImage[nFrames];
}

void draw() {

  if (cam.available()) { // check if a new image is available
    cam.read(); // reads the current frame of the device

    // 1.CURRENT IMAGE (no delay)
    tint(255, 255, 255, 255);
    image(cam, 0, 0);

    // map mouseX between left <>right screen edges:
    // longest possible delay (60 frames) <> no delay (1 frame)
    adjust_buf = round(map(mouseX, 0, width, 0, nFrames-1));

    // how far into buffer playhead can read:
    bufSize = nFrames - adjust_buf;

    // (print values)
    println("bufSize: ", bufSize);
    println("iRead: ", iRead); // playhead position

    buffer[iWrite] = cam.get();
    if (buffer[iRead] != null) {

      // 2.DELAYED IMAGE, displayed on top of current image
      tint(255, 120);
      image(buffer[iRead], 0, 0);
    }

    // playhead progress
    iWrite++;
    iRead++;

    // loop playhead to beginning of buffer
    if (iRead >= bufSize) {
      iRead = 0;
    }
    if (iWrite >= bufSize) {
      iWrite = 0;
    }
  }
}

```

**It seems that sudden delay-time adjustment (fast mouseX movement) causes the delayed image to ‘quit’. Or maybe when delay time becomes too short? Not entirely sure.**

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [October 28, 2023, 11:34am UTC](https://discourse.processing.org/t/video-delay-effect-adjustable-delay-time/43067/2 "2023-10-28T11:34:02Z")

</div>

Hello @ilya.z,

Consider using an _ArrayList_ of _PImages_:

```auto
ArrayList<PImage> buffer = new ArrayList<PImage>();

// You can do things like this:
buffer.add(cam.get(0)) ;
image(buffer.get(0), 0, 0);
buffer.remove(0);

```

You can sort out the flow and logic in your code. That is the fun part!

Reference:

> **[ArrayList / Reference](https://processing.org/reference/ArrayList.html)**
>
> An ArrayList stores a variable number of objects. This is similar to making an array of objects, but with an ArrayList, items can be easily added and removed from the ArrayList and it is…

`:)`

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [October 28, 2023, 3:28pm UTC](https://discourse.processing.org/t/video-delay-effect-adjustable-delay-time/43067/3 "2023-10-28T15:28:17Z")

</div>

> [@ilya.z](#):
>
> causes the delayed image to ‘quit’

What do you mean by quit? Do you mean that the two image become the same? as glv says you need to find the logic - it seems the buffering part is working properly, though.

My guess is that

```java
    if (iRead >= bufSize) {
      iRead = 0;
    }
    if (iWrite >= bufSize) {
      iWrite = 0;
    }

```

This happens at the same time when bufSize suddenly becomes small. Then iRead and iWrite are the same value. Perhaps, instead of incrementing iRead every frame, you want to calculate it from iWrite value - but I know this is tricky!

---

<div class="post-metadata">

**Author:** ![ilya.z](https://avatars.discourse-cdn.com/v4/letter/i/e95f7d/32.png) [@ilya.z](https://discourse.processing.org/u/ilya.z)\
**Post date:** [October 29, 2023, 4:32pm UTC](https://discourse.processing.org/t/video-delay-effect-adjustable-delay-time/43067/4 "2023-10-29T16:32:24Z")

</div>

Thanks @glv , _ArrayList_ indeed seems to be the proper way to deal with a buffer!

---

<div class="post-metadata">

**Author:** ![ilya.z](https://avatars.discourse-cdn.com/v4/letter/i/e95f7d/32.png) [@ilya.z](https://discourse.processing.org/u/ilya.z)\
**Post date:** [October 29, 2023, 4:42pm UTC](https://discourse.processing.org/t/video-delay-effect-adjustable-delay-time/43067/5 "2023-10-29T16:42:50Z")

</div>

Thanks @micuat ,

Really helpful insight!

My assumption that the delayed image ‘quits’ was of course wrong. It was only playing together with current image, without delay, so ‘invisible’.

Solution is pretty simple:

```auto
if (iRead >= bufSize) {
      iRead = 1;
    }
    if (iWrite >= bufSize) {
      iWrite = 0;
    }

```

🙂
