> clip = VideoFileClip(str(video_path))
> clip.duration * clip.fps
252723.60000000003
> clip.get_frame(10000) # Should return 10000th frame
> clip = VideoFileClip(str(video_path))
> frame = clip.get_frame(0) # works
> clip.duration * clip.fps
63229.799999999996 # The duration is '17min 34sec'
> clip.get_frame(63220) # Throws OSError even though the given frame
# number is before the end of the video.
> clip.get_frame(6322) # Throws OSError
> clip.get_frame(632) # Works.
Here's the error message:
OSError: MoviePy error: failed to read the first frame of video file /app/data/streams/unravel1/unravel1_cropped.mp4. That might mean that the file is corrupted. That may also mean that you are using a deprecated version of FFMPEG. On Ubuntu/Debian for instance the version in the repos is deprecated. Please update to a recent version from the website.
Run the above code with the video: https://www.dropbox.com/s/27mie3v8kvo30fz/unravel16_cropped.mp4?dl=0
get_frame(i) in loop does not read frames in orderimport math
import numpy as np
clip = VideoFileClip(str(video_path))
num_frames = math.floor(clip.duration * clip.fps)
clip_array = np.zeros([num_frames, *clip.get_frame(0).shape], dtype=np.uint8)
print(f"clip_array is {np.prod(clip_array.shape)} bytes")
for i in range(math.floor(clip.duration * clip.fps)):
clip_array[i,:,:,:] += clip.get_frame(i)
# Plot frames
j = 0
while True:
plt.imshow(clip_array[j,:,:,:])
print(j); j += 1
plt.pause(0.05)
The frames should be plotted in order.
The frames are random. The array actually does not contain the same data as the frames. It lacks a lot of frames and in the latter part of the array, it contains just pitch black images.
.get_frame's input is seconds, not frame no.
I use this:
vid.get_frame((n / (vid.duration * vid.fps)) * vid.duration)
vid.get_frame(n / vid.fps)
@SuperShinyEyes Did the above info help you resolve your problem?
@keikoro Let me try tonight. Have to dig my old Ubuntu laptop.
I think that this is probably fixed in #1220, released in v2.0.0.dev2 (install with pip using --pre).
@billop was correct:
.get_frame's input is seconds, not frame no.I use this:
vid.get_frame((n / (vid.duration * vid.fps)) * vid.duration) vid.get_frame(n / vid.fps)
Tested on
@tburrows13 v2.0.0.dev2 has the same behaviour as v1.0.3.