Write to list of VideoWriter objects

Hi,

I have a recording setup with several different webcams (the number of which may change from day to day). I am trying to write a program in Python that allows me passing a list of input videos from a txt file, open all videos and process the video feeds SIMULTANEOUSLY, but save them SEPARATELY into different video files.

The code I have works great so far, but I am getting stuck in one particular question:
Is there a way of creating a list of VideoWriter objects and write to them in turns, calling them via an index?

Opening several videos via iteration works like a charm (‘cam_name’ is the list of my camera IDs, i.e. 0, 1, 2, … ):

cap = [cv2.VideoCapture(i) for i in cam_name]

Even creating a list of VideoWriter objects works without problems (and all videos start appearing under the file paths passed by the list ‘outnames’):

outfile = [cv2.VideoWriter(i,cv2.VideoWriter_fourcc(‘M’, ‘J’, ‘P’, ‘G’),30,(640, 480)) for i in [item for item in outnames]]

However, within my while loop, I seem to not be able to call the ‘.write’ function of these VideoWriter objects from my list using an iterator (here, ‘i’ is an integer indicating the position in ‘outfile’ I want to address, and ‘frame’ is the image I’d like to stich to the video):

outfile[i].write(frame)

I double-checked each step in the code and the problem definitely appears in ‘outfile[i].write’. Notably, the code runs through without error! It just seems like ‘write’ isn’t doing anything. The video files created with ‘cv2.VideoWriter’ remain unmodified while my loop is running through.
If I use an ‘imwrite’ workaround, I manage to save the single frames and later stich them together into videos with e.g. ffmpeg, but I’d like to avoid that and call the VideoWriter objects in my loop.

Hope someone can help me! Thanks!

PS: If someone knows the solution in C++, it would also help :slight_smile:

UPDATE: I also tried now solving this with the “exec()” function of Python, passing the command as string. Again, this works when creating the videos, but not when trying to write to them.

strexe = str(“vid” + str(i) + " = cv2.VideoWriter(‘" + str([item for item in outnames][i]) + "’, cv2.VideoWriter_fourcc(‘M’, ‘J’, ‘P’, ‘G’), " + 30 + “, (” + str(640) + ", " + str(height) + “))”)
exec(strexe)

strexe = str(“vid” + str(i) + “.write(crop_img)”)
eval(strexe)

It also seems that “write” is not supporting the “exec” function.

exec(‘print(dir())’)

Can I somehow add ‘write’ to the exec dictionary?

Otherwise I’ll have to use many if-clauses to make the code stable for potentially creating tens of output videos :stuck_out_tongue:

welcome!

post your error message and the lines of code around where the exception is thrown.

actually, reduce your code to the bare minimum that reproduces the issue, but is still runnable. then post that.

do not do that. don’t just try things. you have to figure out why something failed. then you can decide if you can fix it, or try something else. and do not use exec(). please don’t.

It was a stupid mistake I made!! I found it. In my code, I am cutting out rectangular areas from the videos and saving them to new video files.
When setting up the video writer, I calculated width and height for VideoWriter as

width = x_max - x_min + 1
height = y_max - y_min + 1

… (where x_min, x_max, y_min and y_max are the corner of the rectangle), but to my surprise the ‘+1’ messes things up here. It’s still not entirely clear to me why e.g. following image:
x x x x
x x x x
x x x x
Should have a width of 3 and a height of 2? But maybe my understanding of the maths behind picture manipulation is not good enough.

Anyway, my whole question concerning VideoWriter is hence obsolete. The code works now flawlessly (with the iteration solution from the main question, but also the exec() solution from my comment above - however, I agree, exec() is suboptimal). Do you want me to delete my question or clarify in the main text what the solution was??

I would suggest to the developers that ‘.write’ should throw an error if the height and width of the frame one wants to append is different from the settings in VideoWriter! My code never threw an error, the produced video files were just empty. I read in other forums that people had similar problems: Their code would run without error, but in fact some settings in VideoWriter were not matching with frames they wanted to append.

Thanks again for the help and sorry for the confusion!

it shouldn’t? your calculations are wrong.

width = xmax - xmin
height = ymax - ymin
subregion = big_picture[ymin:ymax, xmin:xmax]

that’s all there is to it. that is just numpy.

yes, if argument to write() has different size from what was initialized, throwing an error would be a good idea. you should open an issue on github about that.

Oh yes, my bad. Always running into the same problem with indexing in Python (being used to R). Managed to get my head around indices starting at 0, but it’s still super weird to me that ‘0:3’ means 0,1,2.

I have a list of pixels I want to extract, e.g.

x_from_to = [0,3]
y_from_to = [0,2]

So to get cropped area of 4x3 I have to do:

frame_small = frame[y_from_to[0]:(y_from_to[1]+1), x_from_to[0]:(x_from_to[1]+1)]

Concerning VideoWriter.write() I created an issue on Github: