imageio / imageio-ffmpeg

FFMPEG wrapper for Python
BSD 2-Clause "Simplified" License
237 stars 52 forks source link

Why do you suggest to seed the generator when writing a video #72

Closed hmaarrfk closed 2 years ago

hmaarrfk commented 2 years ago

In the example you suggest to do:

# Read a video file
reader = read_frames(path)
meta = reader.__next__()  # meta data, e.g. meta["size"] -> (width, height)
for frame in reader:
    ... # each frame is a bytes object
# Write a video file
writer = write_frames(path, size)  # size is (width, height)
writer.send(None)  # seed the generator
for frame in frames:
    writer.send(frame)
writer.close()  # don't forget this

However, it is unclear why one should "seed" the generator. Is this in the case that there are no frames?

almarklein commented 2 years ago

This is how Python's generators work. A send is needed to bring the generator to the first yield. See e.g. this example.

def gen():

    while True:
        bb = yield
        print(bb)

g = gen()
g.send(None)
g.send(1)
g.send(2)
g.send(3)

Produces:

1
2
3

If you comment the g.send(None) it gives: "TypeError: can't send non-None value to a just-started generator".

AFAIK this cannot be avoided, but if it is, I'd love to learn!

hmaarrfk commented 2 years ago

are you saying that i:

  1. Write 3 frame directly

I will get 2 frames written to my file.

But if i i

  1. Write None,
  2. Then 3 frames

I will get 3 frames written to my file?

hmaarrfk commented 2 years ago

I think i understand my confusion. THere is the imageio API which uses append_data. That API transparently calls send(None) to avoid this confusion.

The imageio-ffmpeg API requires the user to call send(None) to initialize things.

almarklein commented 2 years ago

Late reaction - holidays - @hmaarrfk yes indeed. imageio-ffmpeg provides a raw generator, and these must be initialized, which seems to be a Python quirk.