Moviepy set ImageClip duration not working and duplicate clips beeing removed? - python

I am setting the duration of a imageClip, but it doesnt seem to care.
I am setting the duration of a imageClip, but it doesnt seem to care. When i try to add duplicate clips it doesnt register. Any help would be appreciated!
img = os.listdir(picDir)
rawClips = [ImageClip(str(picDir)+m).set_duration(2) for m in img]
clips = []
for i in rawClips:
for x in range(imageDuration):
clips.append(i)
print(len(clips))
music = AudioFileClip("music.mp3")
video = concatenate_videoclips(clips, method="compose")
#video.set_audio(music.set_duration(video.duration))
video.write_videofile('result.mp4', fps=120)
return send_file("result.mp4")
It should make every clip duration to 5, but i sets it to 1

It was a flask error, i have no idea how though

Related

Moviepy doubles the speed of the video without affecting audio. I suspect a framerate issue but I havent been able to fix it

Right now here is all I'm having moviepy do:
full_video = VideoFileClip(input_video_path)
full_video.write_videofile("output.mp4")
quit()
It just takes the video and writes it to another file with no changes. But when the input video looks like this the output ends up looking like this with the video speed doubled but the audio just the same. I could take the audio and video separately, halve the speed of the video then put them back together but is there a way I can correct for whatever problem is causing this?
edit 2: It is the VideoFileClip method causing the speedup most likely, not the write_videofile method. When I try
full_video = VideoFileClip(input_video_path)
print( full_video.fps )
full_video.preview(fps = full_video.fps)
quit()
it is still double speed in the preview.
edit 3: The problem only happens with videos captured with Windows game bar. I tried a different video and it worked just fine with no speedup. I'll probably just find a different way to capture the screen recordings to fix it but I dont know what the root problem was
edit 1: the full code
from moviepy.editor import *
# get all dash times
times_path = "times.txt"
input_video_path = "input.mp4"
offset_time = 0
clip_length = float( input("Enter clip length: ") )
def get_times(path, offset):
dash_times_str = []
with open(path, "r") as file:
dash_times_str = file.readlines()
count = 0
# Strips the newline character
# also add offset time
temp = []
for line in dash_times_str:
count += 1
temp.append ("{}".format(line.strip()))
dash_times_str = temp
dash_times = []
for time in dash_times_str:
dash_times.append( float(time) + offset )
return dash_times
dash_times = get_times(times_path, offset_time)
def get_offset_time():
a = float(input("Enter time for first dash in video"))
b = dash_times[0]
return a-b
offset_time = get_offset_time()
full_video = VideoFileClip(input_video_path)
counter = 0
times_count = len(dash_times)
clips = []
for dash_time in dash_times:
clip = full_video.subclip(dash_time,dash_time+clip_length)
clips.append(clip)
counter+=1
print("Clip " + str(counter) + " out of " + str(times_count))
final_clip = concatenate_videoclips(clips)
final_clip.write_videofile("output.mp4")
I haven't been able to go deep down in the source code to figure out why this is, but I could indeed duplicate your bug with videos recorded with the Windows game bar.
I also agree with you that it seems to be tied directly to the VideoFileClip method.
I got my code to work by writing it like this:
full_video = VideoFileClip(input_video_path, fps_source="fps")
with the key detail being the (fps_source = "fps") bit.

How to extract all the frames from a video?

Hey so I wanted to know how I can extract all frames from a vide using MoviePy
Currently I am doing it in open-cv which is really really slow. My current code :-
vidObj = cv2.VideoCapture("./video.mp4")
count = 0
flag = 1
while flag:
flag, image = vidObj.read()
try:
cv2.imwrite(f"./images/frame{count}.jpg", image)
except:
break
count += 1
Can someone tell me how to achieve the same in MoviePy please?
You can use the write_images_sequence() method.
%05d represents a 5 digit frame index.
from moviepy.editor import VideoFileClip
video = VideoFileClip('video.mp4')
video.write_images_sequence('frame%05d.png', logger='bar')

open each image from a list of images (python)

Very similar questions out already but I haven't been able to find one that really matches what I have going on.
This is a facial recognition app with about 200 lines of code so I will just post the part that is relevant.
The app does face recognition and then displays a the target photo next to the best matched mugshot. In case of false positives it also shows a list of the best 5 matches.
I would like for the images in this list to open upon running the code, however only one image in the list is opening for whatever reason.
Relevant piece of code:
# set distance between known faces and target face. The lower the distance between them the lower the match. Higher dist = more error.
if face_distances[best_match_index] < 0.60:
name = known_face_names[best_match_index]
resulttolog = "Match found within default tolerance level. " + "\n" "Match identified as: " + name + "\n"
log(resulttolog) # logging result
# save and display mugshot of best match
mugshot = cv2.imread(os.getcwd() + "/datasets/" + name + ".jpg")
mugshotresized = cv2.resize(mugshot, (500, 500), fx=0.5, fy=0.5)
cv2.imwrite(os.getcwd() + "/mugshot.jpg", mugshotresized)
# listing other closest maches
best_5_matches = n_known_face_names[top_3_matches]
matchestolist = list(best_5_matches)
log("Best matches in order:")
# sort list by number
for index, mugshot in enumerate(matchestolist, 1):
log("{}. {}".format(index, mugshot)) # log the numbered list
# pop up relevant matches
for filename in matchestolist:
path = os.getcwd() + "/datasets/"
file = path + filename + ".jpg"
img = cv2.imread(file)
cv2.imshow("image", img)
So in this last part, the images are supposed to all open. (i assume one pop up window for each image since its a for loop, but only one window is popping up with the first image).
Seems like an easy solution but I cant figure it out..
Any ideas?
You seem to be showing all images without waiting in the same named window 'image'.
Try
cv2.imshow(filename, img)
so they're opened in different windows?

suppress the end of a midi file

I want to remove the end of a midi file in order to have a file of 30 seconds for example.
I tried to compute on each track the total time value and to delete messages each time it is over 30 seconds. However, when I listen to it, it is still the same duration, the only difference is that there is a gap without sound in the middle of the file.
Does any one have an idea of how I can do it ?
Thank you!
Most likely, you forgot to remove some MetaMessages.
Try this:
import mido
midifile = mido.MidiFile('old.mid')
lasttick = # last tick you want to keep
for track in midifile.tracks:
tick = 0
keep = []
for msg in track:
if tick > lasttick:
break
keep.append(msg)
tick += msg.time
track.clear()
track.extend(keep)
midifile.save('new.mid')

Video record from an IP camera with variable frame rate with opencv and python

First of all, I want to comment on what I'm trying to do.
I have an IP camera connected to my network(FOSCAM 9800p) through a router with ethernet cable and from it I am trying to record a video with the RTSP protocol. My intention in the future is to add a small video processing in the middle with opencv but at the moment I want to do the tests to simply record it.
The main problem is that the camera is delivering a variable rate of frames per second, that is, sometimes it does it to 18, others to 22 and so on. When recording the video with a fixed rate of frames per second what ends up happening is that the video plays faster than it should
Something weird that when I run with opencv get (CAP_PROP_FPS) it is returning a big value like 180000.0
To try to solve this problem, what we do is read the frames and place them in a queue. From another process commanded by a timer.Event () we read them and try to write in our video at regular intervals of time in order to obtain a fixed frame rate.
The code is the following:
video_capture = cv2.VideoCapture("rtsp://"+user+":"+password+"#"+ip+":"+str(port)+"/videoMain")
if (video_capture.isOpened() == False):
print("Unable to read camera feed")
sys.exit()
frame_width = int(video_capture.get(3))
frame_height = int(video_capture.get(4))
video_writer =cv2.VideoWriter(output_filename,cv2.VideoWriter_fourcc(*'MP4V'), fps_to_save, (frame_width,frame_height))
input_buffer = queue.Queue(20)
finished = False
read_frames = 0
def readFile():
global finished
global read_frames
while not finished:
ret, frame = video_capture.read()
if not ret:
finished = True
while not finished:
try:
input_buffer.put_nowait(frame)
read_frames+=1
break
except queue.Full:
print("queue.Full")
pass
def processingFile():
global finished
written_frames = 0
repeated_frames = 0
time_per_frame_elapsed = 0.0
start_time=time.time()
ticker = threading.Event()
while True:
ticker.wait(time_per_frame-time_per_frame_elapsed)
time_per_frame_start=time.time()
try:
frame = input_buffer.get_nowait()
video_writer.write(frame)
writing_time = time.time()
if written_frames is 0:
start_time = writing_time
written_frames += 1
except queue.Empty:
if written_frames is not 0:
video_writer.write(frame)
writing_time = time.time()
written_frames += 1
repeated_frames += 1
except:
pass
total_elapsed_time = time.time() - start_time
print("total_elapsed_time:{:f}".format(total_elapsed_time))
if total_elapsed_time>time_to_save_seconds:
finished = True
ticker.clear()
print ("Playback terminated.")
break
time_per_frame_elapsed=time.time()-time_per_frame_start
print("Total readed frames:{:f}".format(read_frames))
print("Total frames repated:{:f}".format(repeated_frames))
print("Total frames writed:{:f}".format(written_frames))
tReadFile = threading.Thread(target=readFile)
tProcessingFile = threading.Thread(target=processingFile)
tReadFile.start()
tProcessingFile.start()
tProcessingFile.join()
tReadFile.join()
The result is close to what we want, but sometimes we have significant differences in the times. We are doing tests with short videos of about 10 seconds and we get 9.8 seconds of recording.
At first it would not seem a serious problem but the error is cumulative, that is if we increase the time increases so that to record videos of a longer time we have more serious problems.
We would like to know how to solve this type of video recording problems with cameras that deliver frames at variable rates. Is it a good idea to do so?
What can be generating the cumulative error in the times?
From already thank you very much!
Greetings to all!
I can say only one thing. In my own experience OpenCV VideoCapture class works with FFMPEG (OpenCV uses it to decode video) in on-line mode very badly. There was a lot of image artifacts and ffmpeg internal errors. But VideoCapture perfectly works with USB cameras. I solved problem with on-line capture from IP-camera with XSplit Broadcaster. This package is able to emulate a USB-camera via physical IP-camera. The only limitation is resizing of camera frame to 640*480 size. Basic license of XSplit Broadcaster is absolutely free

Categories

Resources