def _load_video(full_path, size = None, resize_mode = 'resize_and_crop', cut_edges=False, cut_edges_thresh=0): """ Lead a video into a numpy array :param full_path: Full path to the video :param size: A 2-tuple of width-height, indicating the desired size of the ouput :param resize_mode: The mode with which to get the video to the desired size. Can be: 'squeeze', 'preserve_aspect', 'crop', 'scale_crop'. See resize_image in image_ops.py for more info. :param cut_edges: True if you want to cut the dark edges from the video :param cut_edges_thresh: If cut_edges, this is the threshold at which you'd like to cut them. :return: A (n_frames, height, width, 3) numpy array """ try: from moviepy.video.io.VideoFileClip import VideoFileClip except ImportError: raise ImportError("You need to install moviepy to read videos. In the virtualenv, go `pip install moviepy`") assert os.path.exists(full_path) video = VideoFileClip(full_path) images = [] edge_crops = None for frame in video.iter_frames(): if cut_edges: if edge_crops is None: edge_crops = get_dark_edge_slice(frame, cut_edges_thresh=cut_edges_thresh) else: frame = frame[edge_crops[0], edge_crops[1]] if size is not None: width, height = size frame = resize_image(frame, width=width, height=height, mode=resize_mode) images.append(frame) return images
def test_toimageclip(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0.2, 0.6) clip = clip.to_ImageClip(t=0.1, duration=0.4) location = os.path.join(TMP_DIR, "toimageclip.mp4") clip.write_videofile(location, fps=24) assert os.path.isfile(location) close_all_clips(locals())
def cut_video(recording_path, datapack_dir): # Read the start/end pattern sr1, pattern_wav = wav.read('pattern.wav') workingdir = tempfile.mkdtemp() # Open the video file clip = VideoFileClip(recording_path) # Save its audio track temporarily on disk clip.audio.write_audiofile(os.path.join(workingdir,"temp_audio.wav")) # Read the audio samples, mix down to mono (if necessary), and delete the temporary audio track sr2, recording_wav = wav.read(os.path.join(workingdir,"temp_audio.wav")) if recording_wav.shape[1]>1: recording_wav = numpy.mean(recording_wav,1) shutil.rmtree(workingdir) # Detect the start and end audio pattern start, end = detect_start_end_times(pattern_wav, recording_wav, sr2, 4) # Cut the video and write it into two separate video and audio files clip.subclip(start+0.4, end).write_videofile(os.path.join(datapack_dir, 'video.mp4'), codec='libx264') clip.subclip(start+0.4, end).audio.write_audiofile(os.path.join(datapack_dir,'audio.wav'))
def summarize(filepath, new_filename, hotclips): """ Inputs a filepath for a video and generates a new shorter video in that same filepath. """ # Only open the file once! video = VideoFileClip(filepath) chunks = [video.subclip(start, end) for (start, end) in hotclips] final_clip = concatenate(chunks) # txt_clip = ( TextClip("Generated by vSummarize", # fontsize=20, color='white') # .set_pos('bottom') # .set_duration(5)) # final_clip = CompositeVideoClip([summarized_video, txt_clip]) # Use the to_videofile default codec, libx264 # libx264 is much better than mpeg4, and still writes .mp4 # Use the fps of the original video. final_clip.to_videofile(new_filename, fps=video.fps, audio_codec='mp3')
def test_write_image_sequence(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0.2, 0.5) locations = clip.write_images_sequence( os.path.join(TMP_DIR, "frame%02d.png")) for location in locations: assert os.path.isfile(location) close_all_clips(locals())
class VideoStim(Stim, CollectionStimMixin): ''' A video. ''' def __init__(self, filename, onset=None): self.clip = VideoFileClip(filename) self.fps = self.clip.fps self.width = self.clip.w self.height = self.clip.h self.n_frames = int(self.fps * self.clip.duration) duration = self.clip.duration super(VideoStim, self).__init__(filename, onset, duration) def __iter__(self): """ Frame iteration. """ for i, f in enumerate(self.clip.iter_frames()): yield VideoFrameStim(self, i, data=f) @property def frames(self): return [f for f in self.clip.iter_frames()] def get_frame(self, index=None, onset=None): if index is not None: onset = float(index) / self.fps else: index = int(onset * self.fps) return VideoFrameStim(self, index, data=self.clip.get_frame(onset))
def test_subfx(): clip = VideoFileClip("media/big_buck_bunny_0_30.webm").subclip(0, 1) transform = lambda c: speedx(c, 0.5) new_clip = clip.subfx(transform, 0.5, 0.8) location = os.path.join(TMP_DIR, "subfx.mp4") new_clip.write_videofile(location) assert os.path.isfile(location) close_all_clips(locals())
def test_setopacity(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0.2, 0.6) clip = clip.set_opacity(0.5) clip = clip.on_color(size=(1000, 1000), color=(0, 0, 255), col_opacity=0.8) location = os.path.join(TMP_DIR, "setopacity.mp4") clip.write_videofile(location) assert os.path.isfile(location) close_all_clips(locals())
def test_failure_to_release_file(): """ This isn't really a test, because it is expected to fail. It demonstrates that there *is* a problem with not releasing resources when running on Windows. The real issue was that, as of movepy 0.2.3.2, there was no way around it. See test_resourcerelease.py to see how the close() methods provide a solution. """ # Get the name of a temporary file we can use. local_video_filename = join( TMP_DIR, "test_release_of_file_%s.mp4" % int(time.time())) # Repeat this so we can see that the problems escalate: for i in range(5): # Create a random video file. red = ColorClip((256, 200), color=(255, 0, 0)) green = ColorClip((256, 200), color=(0, 255, 0)) blue = ColorClip((256, 200), color=(0, 0, 255)) red.fps = green.fps = blue.fps = 30 video = clips_array([[red, green, blue]]).set_duration(1) try: video.write_videofile(local_video_filename) # Open it up with VideoFileClip. clip = VideoFileClip(local_video_filename) # Normally a client would do processing here. # All finished, so delete the clipS. clip.close() video.close() del clip del video except IOError: print( "On Windows, this succeeds the first few times around the loop" " but eventually fails.") print("Need to shut down the process now. No more tests in" "this file.") return try: # Now remove the temporary file. # This will fail on Windows if the file is still locked. # In particular, this raises an exception with PermissionError. # In there was no way to avoid it. remove(local_video_filename) print("You are not running Windows, because that worked.") except OSError: # More specifically, PermissionError in Python 3. print("Yes, on Windows this fails.")
def test_check_codec(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm") location = os.path.join(TMP_DIR, "not_a_video.mas") try: clip.write_videofile(location) except ValueError as e: assert "MoviePy couldn't find the codec associated with the filename." \ " Provide the 'codec' parameter in write_videofile." in str(e) close_all_clips(locals())
def test_loop(): #these do not work.. what am I doing wrong?? return clip = VideoFileClip("media/big_buck_bunny_432_433.webm") clip1 = clip.loop() #infinite looping clip1.write_videofile(os.path.join(TMP_DIR, "loop1.webm")) clip2 = clip.loop(duration=10) #loop for 10 seconds clip2.write_videofile(os.path.join(TMP_DIR, "loop2.webm")) clip3 = clip.loop(n=3) #loop 3 times clip3.write_videofile(os.path.join(TMP_DIR, "loop3.webm"))
def test_resize(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm") clip1=clip.resize( (460,720) ) # New resolution: (460,720) assert clip1.size == (460,720) clip1.write_videofile(os.path.join(TMP_DIR, "resize1.webm")) clip2=clip.resize(0.6) # width and heigth multiplied by 0.6 assert clip2.size == (clip.size[0]*0.6, clip.size[1]*0.6) clip2.write_videofile(os.path.join(TMP_DIR, "resize2.webm")) clip3=clip.resize(width=800) # height computed automatically. assert clip3.w == 800 #assert clip3.h == ?? clip3.write_videofile(os.path.join(TMP_DIR, "resize3.webm"))
def ffwd_video(path_in, path_out, checkpoint_dir, device_t='/gpu:0', batch_size=4): video_clip = VideoFileClip(path_in, audio=False) video_writer = ffmpeg_writer.FFMPEG_VideoWriter(path_out, video_clip.size, video_clip.fps, codec="libx264", preset="medium", bitrate="2000k", audiofile=path_in, threads=None, ffmpeg_params=None) g = tf.Graph() soft_config = tf.ConfigProto(allow_soft_placement=True) soft_config.gpu_options.allow_growth = True with g.as_default(), g.device(device_t), \ tf.Session(config=soft_config) as sess: batch_shape = (batch_size, video_clip.size[1], video_clip.size[0], 3) img_placeholder = tf.placeholder(tf.float32, shape=batch_shape, name='img_placeholder') preds = transform.net(img_placeholder) saver = tf.train.Saver() if os.path.isdir(checkpoint_dir): ckpt = tf.train.get_checkpoint_state(checkpoint_dir) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path) else: raise Exception("No checkpoint found...") else: saver.restore(sess, checkpoint_dir) X = np.zeros(batch_shape, dtype=np.float32) def style_and_write(count): for i in range(count, batch_size): X[i] = X[count - 1] # Use last frame to fill X _preds = sess.run(preds, feed_dict={img_placeholder: X}) for i in range(0, count): video_writer.write_frame(np.clip(_preds[i], 0, 255).astype(np.uint8)) frame_count = 0 # The frame count that written to X for frame in video_clip.iter_frames(): X[frame_count] = frame frame_count += 1 if frame_count == batch_size: style_and_write(frame_count) frame_count = 0 if frame_count != 0: style_and_write(frame_count) video_writer.close()
def loadMovie(self, filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ self.reset() #set status and timestamps etc # Create Video Stream stuff if os.path.isfile(filename): self._mov = VideoFileClip(filename, audio= (1-self.noAudio)) if (not self.noAudio) and (self._mov.audio is not None): self._audioStream = sound.Sound(self._mov.audio.to_soundarray(), sampleRate = self._mov.audio.fps) else: #make sure we set to None (in case prev clip did have auido) self._audioStream = None else: raise IOError("Movie file '%s' was not found" %filename) #mov has attributes: # size, duration, fps #mov.audio has attributes #duration, fps (aka sampleRate), to_soundarray() self._frameInterval = 1.0/self._mov.fps self.duration = self._mov.duration self.filename = filename self._updateFrameTexture() logAttrib(self, log, 'movie', filename)
def __init__(self, filename, onset=None): self.clip = VideoFileClip(filename) self.fps = self.clip.fps self.width = self.clip.w self.height = self.clip.h self.n_frames = int(self.fps * self.clip.duration) duration = self.clip.duration super(VideoStim, self).__init__(filename, onset, duration)
def download_and_convert(url): print("converting url " + url) source = pafy.new(url) best = source.getbest(preftype="mp4") ts = datetime.datetime.fromtimestamp(time.time()).strftime('%Y%m%d-%H%M%S') input_filename = "/tmp/" + ts + "." + best.extension best.download(filepath=input_filename) output = VideoFileClip(input_filename) duration = output.duration output_filename="/tmp/" + best.title + "." + best.extension output = output.set_audio(audio).fl_time(lambda t: t * accel, apply_to='mask').set_duration(duration / accel) output.write_videofile(output_filename) print("uploading to s3") s3 = boto.connect_s3() bucket = s3.get_bucket('bennyhill') key = Key(bucket) key.key = best.title + "-" + ts key.set_contents_from_filename(output_filename) output_url = key.generate_url(expires_in=3600) print("complete") # save the results try: result = Result( url=url, youtube_url=output_url ) db.session.add(result) db.session.commit() return result.id except: errors.append("Unable to add item to database.") return {"error": errors}
def loadMovie(self, filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ filename = pathToString(filename) self.reset() # set status and timestamps etc # Create Video Stream stuff if os.path.isfile(filename): self._mov = VideoFileClip(filename, audio=(1 - self.noAudio)) if (not self.noAudio) and (self._mov.audio is not None): sound = self.sound try: self._audioStream = sound.Sound( self._mov.audio.to_soundarray(), sampleRate=self._mov.audio.fps) except: # JWE added this as a patch for a moviepy oddity where the # duration is inflated in the saved file causes the # audioclip to be the wrong length, so round down and it # should work jwe_tmp = self._mov.subclip(0, round(self._mov.duration)) self._audioStream = sound.Sound( jwe_tmp.audio.to_soundarray(), sampleRate=self._mov.audio.fps) del(jwe_tmp) else: # make sure we set to None (in case prev clip had audio) self._audioStream = None else: raise IOError("Movie file '%s' was not found" % filename) # mov has attributes: # size, duration, fps # mov.audio has attributes # duration, fps (aka sampleRate), to_soundarray() self._frameInterval = 1.0/self._mov.fps self.duration = self._mov.duration self.filename = filename self._updateFrameTexture() logAttrib(self, log, 'movie', filename)
def test_ffmpeg_resizing(): """Test FFmpeg resizing, to include downscaling.""" video_file = 'media/big_buck_bunny_432_433.webm' target_resolution = (128, 128) video = VideoFileClip(video_file, target_resolution=target_resolution) frame = video.get_frame(0) assert frame.shape[0:2] == target_resolution target_resolution = (128, None) video = VideoFileClip(video_file, target_resolution=target_resolution) frame = video.get_frame(0) assert frame.shape[0] == target_resolution[0] target_resolution = (None, 128) video = VideoFileClip(video_file, target_resolution=target_resolution) frame = video.get_frame(0) assert frame.shape[1] == target_resolution[1] # Test upscaling target_resolution = (None, 2048) video = VideoFileClip(video_file, target_resolution=target_resolution) frame = video.get_frame(0) assert frame.shape[1] == target_resolution[1]
def convert(self, video_file, swap_model=False, duration=None, start_time=None, use_gan=False, face_filter=False, photos=True, crop_x=None, width=None, side_by_side=False, live=False): # Magic incantation to not have tensorflow blow up with an out of memory error. import tensorflow as tf import keras.backend.tensorflow_backend as K config = tf.ConfigProto() config.gpu_options.allow_growth = True config.gpu_options.visible_device_list = "0" K.set_session(tf.Session(config=config)) # Load model model_name = "Original" converter_name = "Masked" if use_gan: model_name = "GAN" converter_name = "GAN" # ----------------------------------------------------------- # FIXING THE BUG with Model loading: # model = PluginLoader.get_model(model_name)(Path(self._model_path(use_gan))) # TypeError: __init__() takes exactly 3 arguments (2 given) # ----------------------------------------------------------- # tmp_1 = PluginLoader.get_model(model_name) # tmp_1 = PluginLoader._import("Model_LIVE", "Model_LIVE") # that works (crutch however) # tmp_2 = Path(self._model_path(use_gan)) # models/emma_to_jade # print('\n\n\n{}\n{}\n{}\n{}\n\n\n'.format(tmp_1, type(tmp_1), tmp_2, type(tmp_2))) # sys.exit(0) # values in faceit_live module: # plugins.Model_Original.Model # <type 'classobj'> # models/emma_to_jade # <class 'pathlib.PosixPath'> # values here: # plugins.Model_Original.Model.Model # <type 'classobj'> # models/emma_to_jade # <class 'pathlib.PosixPath'> # ----------------------------------------------------------- # model = PluginLoader.get_model(model_name)(Path(self._model_path(use_gan))) # ==> crash model = PluginLoader._import("Model_LIVE", "Model_LIVE")(Path( self._model_path(use_gan))) # print('\n\n\n{}\n\n\n'.format(self._model_path(use_gan))) # e.g. models/test_2_faces # sys.exit(0) if not model.load(swap_model): print( 'model Not Found! A valid model must be provided to continue!') exit(1) print('Checkpoint_1 ... Model loaded') # ----------------------------------------------------------- # FIXING THE BUG with Converter loading: # ----------------------------------------------------------- # tmp_1 = PluginLoader.get_converter(converter_name) # tmp_1 = PluginLoader._import("Convert", "Convert_Masked_LIVE") # print('\n\n\n{}\n{}\n\n\n'.format(tmp_1, type(tmp_1))) # sys.exit(0) # faceit_live module: # plugins.Convert_Masked.Convert # <type 'classobj'> # here: # plugins.Convert_Masked.Convert # <type 'classobj'> # ----------------------------------------------------------- # Load converter # converter = PluginLoader.get_converter(converter_name) # ==> crash converter = PluginLoader._import("Convert", "Convert_Masked_LIVE") converter = converter(model.converter(False), blur_size=8, seamless_clone=True, mask_type="facehullandrect", erosion_kernel_size=None, smooth_mask=True, avg_color_adjust=True) print('Checkpoint_2 ... Converter loaded') # Load face filter filter_person = self._person_a if swap_model: filter_person = self._person_b filter = FaceFilter_LIVE(self._people[filter_person]['faces']) # Define conversion method per frame def _convert_frame(frame, convert_colors=True): # if convert_colors: # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Swap RGB to BGR to work with OpenCV DEBUG_MODE = 0 for face in detect_faces_LIVE(frame, "cnn"): if DEBUG_MODE: print('Got face!') # print(dir(face)) # image, x, y, w, h, landmarks print('Face geometry: ({},{},{},{})'.format( face.x, face.y, face.w, face.h)) print('Face landmarks: {}'.format(face.landmarks)) cv2.imshow('Face', face.image) continue if (not face_filter) or (face_filter and filter.check(face)): # if 1: # print(dir(face.landmarks)) # face.landmarks = [] frame = converter.patch_image(frame, face) if not live: frame = frame.astype(numpy.float32) # if convert_colors: # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Swap RGB to BGR to work with OpenCV return frame def _convert_helper(get_frame, t): return _convert_frame(get_frame(t)) # =================================================== if live: print('Staring live mode ...') print('Press "Q" to Quit') PATH_TO_VIDEO = './data/videos/emma_360_cut.mp4' if TEST_2_FACES_FLAG: # PATH_TO_VIDEO = './_data/videos/pair_360p_original.mp4' PATH_TO_VIDEO = './data/videos/pair_360p_cut.mp4' video_capture = cv2.VideoCapture(PATH_TO_VIDEO) width = video_capture.get(3) # float height = video_capture.get(4) # float print("video dimensions = {} x {}".format(width, height)) while 1: ret, frame = video_capture.read() # print(frame.shape, frame.dtype) # (360, 640, 3), uint8 # frame = cv2.resize(frame, (640, 480)) print('HANDLING NEW FRAME ...') if CROP_HALF_OF_FRAME == 'left': frame[:, 0:frame.shape[1] / 2] = 0 # ~ cropping left half of an image # elif CROP_HALF_OF_FRAME == 'right': # pass if not ret: print("RET IS NONE ... I'M QUIT") video_capture.release() break # block without try/except - to catch actual errors: frame = cv2.flip(frame, 1) image = _convert_frame(frame, convert_colors=False) print('GOT AN IMAGE!') frame = cv2.flip(frame, 1) image = cv2.flip(image, 1) try: # with flip: # flip image, because webcam inverts it and we trained the model the other way! frame = cv2.flip(frame, 1) image = _convert_frame(frame, convert_colors=False) print('GOT AN IMAGE!') # flip it back frame = cv2.flip(frame, 1) image = cv2.flip(image, 1) except: try: # without flip: image = _convert_frame(frame, convert_colors=False) print('GOT AN IMAGE!') except: print("HMM ... CONVERTATION FAILED ... I'M QUIT") continue # video_capture.release() # break cv2.imshow('Video', image) cv2.imshow('Original', frame) # Hit 'q' on the keyboard to quit! if cv2.waitKey(1) & 0xFF == ord('q'): print("KEYBOARD INTERRUPT ... I'M QUIT") video_capture.release() break cv2.destroyAllWindows() exit() # =================================================== media_path = self._video_path({'name': video_file}) if not photos: # Process video; start loading the video clip video = VideoFileClip(media_path) # If a duration is set, trim clip if duration: video = video.subclip(start_time, start_time + duration) # Resize clip before processing if width: video = video.resize(width=width) # Crop clip if desired if crop_x: video = video.fx(crop, x2=video.w / 2) # Kick off convert frames for each frame new_video = video.fl(_convert_helper) # Stack clips side by side if side_by_side: def add_caption(caption, clip): text = (TextClip(caption, font='Amiri-regular', color='white', fontsize=80).margin(40).set_duration( clip.duration).on_color( color=(0, 0, 0), col_opacity=0.6)) return CompositeVideoClip([clip, text]) video = add_caption("Original", video) new_video = add_caption("Swapped", new_video) final_video = clips_array([[video], [new_video]]) else: final_video = new_video # Resize clip after processing #final_video = final_video.resize(width = (480 * 2)) # Write video if not os.path.exists(os.path.join(self.OUTPUT_PATH)): os.makedirs(self.OUTPUT_PATH) output_path = os.path.join(self.OUTPUT_PATH, video_file) final_video.write_videofile(output_path, rewrite_audio=True) # Clean up del video del new_video del final_video else: # Process a directory of photos for face_file in os.listdir(media_path): face_path = os.path.join(media_path, face_file) image = cv2.imread(face_path) image = _convert_frame(image, convert_colors=False) cv2.imwrite(os.path.join(self.OUTPUT_PATH, face_file), image)
def test_withoutaudio(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0.2, 0.6) new_clip = clip.without_audio() assert new_clip.audio is None close_all_clips(locals())
def test_save_frame(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm") location = os.path.join(TMP_DIR, "save_frame.png") clip.save_frame(location, t=0.5) assert os.path.isfile(location) close_all_clips(locals())
def convert(self, video_file, swap_model=False, duration=None, start_time=None, use_gan=False, face_filter=False, photos=True, crop_x=None, width=None, side_by_side=False): # Magic incantation to not have tensorflow blow up with an out of memory error. import tensorflow as tf import keras.backend.tensorflow_backend as K config = tf.ConfigProto() config.gpu_options.allow_growth = True config.gpu_options.visible_device_list = "0" K.set_session(tf.Session(config=config)) # Load model model_name = "Original" converter_name = "Masked" if use_gan: model_name = "GAN" converter_name = "GAN" model = PluginLoader.get_model(model_name)(Path( self._model_path(use_gan))) if not model.load(swap_model): print( 'model Not Found! A valid model must be provided to continue!') exit(1) # Load converter converter = PluginLoader.get_converter(converter_name) converter = converter(model.converter(False), blur_size=8, seamless_clone=True, mask_type="facehullandrect", erosion_kernel_size=None, smooth_mask=True, avg_color_adjust=True) # Load face filter filter_person = self._person_a if swap_model: filter_person = self._person_b filter = FaceFilter(self._people[filter_person]['faces']) # Define conversion method per frame def _convert_frame(frame, convert_colors=True): if convert_colors: frame = cv2.cvtColor( frame, cv2.COLOR_BGR2RGB) # Swap RGB to BGR to work with OpenCV for face in detect_faces(frame, "cnn"): if (not face_filter) or (face_filter and filter.check(face)): frame = converter.patch_image(frame, face) frame = frame.astype(numpy.float32) if convert_colors: frame = cv2.cvtColor( frame, cv2.COLOR_BGR2RGB) # Swap RGB to BGR to work with OpenCV return frame def _convert_helper(get_frame, t): return _convert_frame(get_frame(t)) media_path = self._video_path({'name': video_file}) if not photos: # Process video; start loading the video clip video = VideoFileClip(media_path) # If a duration is set, trim clip if duration: video = video.subclip(start_time, start_time + duration) # Resize clip before processing if width: video = video.resize(width=width) # Crop clip if desired if crop_x: video = video.fx(crop, x2=video.w / 2) # Kick off convert frames for each frame new_video = video.fl(_convert_helper) # Stack clips side by side if side_by_side: def add_caption(caption, clip): text = (TextClip(caption, font='Amiri-regular', color='white', fontsize=80).margin(40).set_duration( clip.duration).on_color( color=(0, 0, 0), col_opacity=0.6)) return CompositeVideoClip([clip, text]) video = add_caption("Original", video) new_video = add_caption("Swapped", new_video) final_video = clips_array([[video], [new_video]]) else: final_video = new_video # Resize clip after processing #final_video = final_video.resize(width = (480 * 2)) # Write video output_path = os.path.join(self.OUTPUT_PATH, video_file) final_video.write_videofile(output_path, rewrite_audio=True) # Clean up del video del new_video del final_video else: # Process a directory of photos for face_file in os.listdir(media_path): face_path = os.path.join(media_path, face_file) image = cv2.imread(face_path) image = _convert_frame(image, convert_colors=False) cv2.imwrite(os.path.join(self.OUTPUT_PATH, face_file), image)
def test_write_gif_ffmpeg(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0.2, 0.4) location = os.path.join(TMP_DIR, "ffmpeg_gif.gif") clip.write_gif(location, program="ffmpeg") assert os.path.isfile(location) close_all_clips(locals())
def test_invert_colors(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm") clip1 = invert_colors(clip) clip1.write_videofile(os.path.join(TMP_DIR, "invert_colors1.webm"))
from moviepy.video.io.VideoFileClip import VideoFileClip from lane_finder import LaneFinder easy = "./videos/project_video.mp4" medium = "./videos/challenge_video.mp4" hard = "./videos/harder_challenge_video.mp4" input_video = hard debug = False # output a debugging version of the video if __name__ == '__main__': """ Process each frame of a video to detect lanes and render output video """ lane_finder = LaneFinder() video_clip = VideoFileClip(input_video) if debug: processed_clip = video_clip.fl_image(lane_finder.debug_frame) else: processed_clip = video_clip.fl_image(lane_finder.process_frame) # save video processed_clip.write_videofile(input_video[:-4] + '_processed.mp4', audio=False) print('Done')
def test_write_gif_ImageMagick_tmpfiles(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0.2, 0.5) location = os.path.join(TMP_DIR, "imagemagick_tmpfiles_gif.gif") clip.write_gif(location, program="ImageMagick", tempfiles=True) assert os.path.isfile(location) close_all_clips(locals())
class Decoder(object): """ This class loads a video file that can be played. It can be passed a callback function to which decoded video frames should be passed. """ def __init__(self, mediafile=None, videorenderfunc=None, play_audio=True): """ Constructor. Parameters ---------- mediafile : str, optional The path to the mediafile to be loaded (default: None) videorenderfunc : callable (default: None) Callback function that takes care of the actual Rendering of the videoframe.\ The specified renderfunc should be able to accept the following arguments: - frame (numpy.ndarray): the videoframe to be rendered play_audio : bool, optional Whether audio of the clip should be played. """ # Create an internal timer self.clock = Timer() # Load a video file if specified, but allow users to do this later # by initializing all variables to None if not self.load_media(mediafile, play_audio): self.reset() # Set callback function if set self.set_videoframerender_callback(videorenderfunc) # Store instance variables self.play_audio = play_audio @property def frame_interval(self): """ Duration in seconds of a single frame. """ return self.clock.frame_interval @property def current_frame_no(self): """ Current frame_no of video. """ return self.clock.current_frame @property def current_videoframe(self): """ Representation of current video frame as a numpy array. """ return self.__current_videoframe @property def current_playtime(self): """ Clocks current runtime in seconds. """ return self.clock.time @property def loop(self): """ Indicates whether the playback should loop. """ return self._loop @loop.setter def loop(self, value): """ Indicates whether the playback should loop. Parameters ---------- value : bool True if playback should loop, False if not. """ if not type(value) == bool: raise TypeError("can only be True or False") self._loop = value def reset(self): """ Resets the player and discards loaded data. """ self.clip = None self.loaded_file = None self.fps = None self.duration = None self.status = UNINITIALIZED self.clock.reset() def load_media(self, mediafile, play_audio=True): """ Loads a media file to decode. If an audiostream is detected, its parameters will be stored in a dictionary in the variable `audioformat`. This contains the fields :nbytes: the number of bytes in the stream (2 is 16-bit sound). :nchannels: the channels (2 for stereo, 1 for mono) :fps: the frames per sec/sampling rate of the sound (e.g. 44100 KhZ). :buffersize: the audioframes per buffer. If play_audio was set to False, or the video does not have an audiotrack, `audioformat` will be None. Parameters ---------- mediafile : str The path to the media file to load. play_audio : bool, optional Indicates whether the audio of a movie should be played. Raises ------ IOError When the file could not be found or loaded. """ if not mediafile is None: if os.path.isfile(mediafile): self.clip = VideoFileClip(mediafile, audio=play_audio) self.loaded_file = os.path.split(mediafile)[1] ## Timing variables # Clip duration self.duration = self.clip.duration self.clock.max_duration = self.clip.duration logger.debug("Video clip duration: {}s".format(self.duration)) # Frames per second of clip self.fps = self.clip.fps self.clock.fps = self.clip.fps logger.debug("Video clip FPS: {}".format(self.fps)) if play_audio and self.clip.audio: buffersize = int(self.frame_interval*self.clip.audio.fps) self.audioformat = { 'nbytes': 2, 'nchannels': self.clip.audio.nchannels, 'fps': self.clip.audio.fps, 'buffersize': buffersize } logger.debug("Audio loaded: \n{}".format(self.audioformat)) logger.debug("Creating audio buffer of length: " " {}".format(queue_length)) self.audioqueue = Queue(queue_length) else: self.audioformat = None logger.debug('Loaded {0}'.format(mediafile)) self.status = READY return True else: raise IOError("File not found: {0}".format(mediafile)) return False def set_videoframerender_callback(self, func): """ Sets the function to call when a new frame is available. This function is passed the frame (in the form of a numpy.ndarray) and should take care of the rendering. Parameters ---------- func : callable The function to pass the new frame to once it becomes available. """ # Check if renderfunc is indeed a function if not func is None and not callable(func): raise TypeError("The object passed for videorenderfunc is not a function") self.__videorenderfunc = func def set_audiorenderer(self, renderer): """ Sets the SoundRenderer object. This should take care of processing the audioframes set in audioqueue. Parameters ---------- renderer : soundrenderers.SoundRenderer A subclass of soundrenderers.SoundRenderer that takes care of the audio rendering. Raises ------ RuntimeError If no information about the audiostream is available. This could be because no video has been loaded yet, or because no embedded audiostream could be detected in the video, or play_sound was set to False. """ if not hasattr(self, 'audioqueue') or self.audioqueue is None: raise RuntimeError("No video has been loaded, or no audiostream " "was detected.") if not isinstance(renderer, SoundRenderer): raise TypeError("Invalid renderer object. Not a subclass of " "SoundRenderer") self.soundrenderer = renderer self.soundrenderer.queue = self.audioqueue def play(self): """ Start the playback of the video. The playback loop is run in a separate thread, so this function returns immediately. This allows one to implement things such as event handling loops (e.g. check for key presses) elsewhere. """ ### First do some status checks # Make sure a file is loaded if self.status == UNINITIALIZED or self.clip is None: raise RuntimeError("Player uninitialized or no file loaded") # Check if playback has already finished (rewind needs to be called first) if self.status == EOS: logger.debug("End of stream has already been reached") return # Check if playback hasn't already been started (and thus if play() # has not been called before from another thread for instance) if self.status in [PLAYING,PAUSED]: logger.warning("Video already started") return ### If all is in order start the general playing loop if self.status == READY: self.status = PLAYING self.last_frame_no = 0 if not hasattr(self,"renderloop") or not self.renderloop.isAlive(): if self.audioformat: # Chop the total stream into separate audio chunks that are the # lenght of a video frame (this way the index of each chunk # corresponds to the video frame it belongs to.) self.__calculate_audio_frames() # Start audio handling thread. This thread places audioframes # into a sound buffer, untill this buffer is full. self.audioframe_handler = threading.Thread( target=self.__audiorender_thread) self.audioframe_handler.start() # Start main rendering loop. self.renderloop = threading.Thread(target=self.__render) self.renderloop.start() else: logger.warning("Rendering thread already running!") def pause(self): """ Pauses or resumes the video and/or audio stream. """ # Change playback status only if current status is PLAYING or PAUSED # (and not READY). logger.debug("Pausing playback") if self.status == PAUSED: # Recalculate audio stream position to make sure it is not out of # sync with the video self.__calculate_audio_frames() self.status = PLAYING self.clock.pause() elif self.status == PLAYING: self.status = PAUSED self.clock.pause() def stop(self): """ Stops the video stream and resets the clock. """ logger.debug("Stopping playback") # Stop the clock self.clock.stop() # Set plauyer status to ready self.status = READY def seek(self, value): """ Seek to the specified time. Parameters ---------- value : str or int The time to seek to. Can be any of the following formats: >>> 15.4 -> 15.4 # seconds >>> (1,21.5) -> 81.5 # (min,sec) >>> (1,1,2) -> 3662 # (hr, min, sec) >>> '01:01:33.5' -> 3693.5 #(hr,min,sec) >>> '01:01:33.045' -> 3693.045 >>> '01:01:33,5' #comma works too """ # Pause the stream self.pause() self.clock.time = value logger.debug("Seeking to {} seconds; frame {}".format(self.clock.time, self.clock.current_frame)) if self.audioformat: self.__calculate_audio_frames() # Resume the stream self.pause() def rewind(self): """ Rewinds the video to the beginning. Convenience function simply calling seek(0). """ self.seek(0) def __calculate_audio_frames(self): """ Aligns audio with video. This should be called for instance after a seeking operation or resuming from a pause. """ if self.audioformat is None: return start_frame = self.clock.current_frame totalsize = int(self.clip.audio.fps*self.clip.audio.duration) self.audio_times = list(range(0, totalsize, self.audioformat['buffersize'])) + [totalsize] # Remove audio segments up to the starting frame del(self.audio_times[0:start_frame]) def __render(self): """ Main render loop. Checks clock if new video and audio frames need to be rendered. If so, it passes the frames to functions that take care of rendering these frames. """ # Render first frame self.__render_videoframe() # Start videoclock with start of this thread self.clock.start() logger.debug("Started rendering loop.") # Main rendering loop while self.status in [PLAYING,PAUSED]: current_frame_no = self.clock.current_frame # Check if end of clip has been reached if self.clock.time >= self.duration: logger.debug("End of stream reached at {}".format(self.clock.time)) if self.loop: logger.debug("Looping: restarting stream") # Seek to the start self.seek(0) else: # End of stream has been reached self.status = EOS break if self.last_frame_no != current_frame_no: # A new frame is available. Get it from te stream self.__render_videoframe() self.last_frame_no = current_frame_no # Sleeping is a good idea to give the other threads some breathing # space to do their work. time.sleep(0.005) # Stop the clock. self.clock.stop() logger.debug("Rendering stopped.") def __render_videoframe(self): """ Retrieves a new videoframe from the stream. Sets the frame as the __current_video_frame and passes it on to __videorenderfunc() if it is set. """ new_videoframe = self.clip.get_frame(self.clock.time) # Pass it to the callback function if this is set if callable(self.__videorenderfunc): self.__videorenderfunc(new_videoframe) # Set current_frame to current frame (...) self.__current_videoframe = new_videoframe def __audiorender_thread(self): """ Thread that takes care of the audio rendering. Do not call directly, but only as the target of a thread. """ new_audioframe = None logger.debug("Started audio rendering thread.") while self.status in [PLAYING,PAUSED]: # Retrieve audiochunk if self.status == PLAYING: if new_audioframe is None: # Get a new frame from the audiostream, skip to the next one # if the current one gives a problem try: start = self.audio_times.pop(0) stop = self.audio_times[0] except IndexError: logger.debug("Audio times could not be obtained") time.sleep(0.02) continue # Get the frame numbers to extract from the audio stream. chunk = (1.0/self.audioformat['fps'])*np.arange(start, stop) try: # Extract the frames from the audio stream. Does not always, # succeed (e.g. with bad streams missing frames), so make # sure this doesn't crash the whole program. new_audioframe = self.clip.audio.to_soundarray( tt = chunk, buffersize = self.frame_interval*self.clip.audio.fps, quantize=True ) except OSError as e: logger.warning("Sound decoding error: {}".format(e)) new_audioframe = None # Put audioframe in buffer/queue for soundrenderer to pick up. If # the queue is full, try again after a timeout (this allows to check # if the status is still PLAYING after a pause.) if not new_audioframe is None: try: self.audioqueue.put(new_audioframe, timeout=.05) new_audioframe = None except Full: pass time.sleep(0.005) logger.debug("Stopped audio rendering thread.") def __repr__(self): """ Create a string representation for when print() is called. """ return "Decoder [file loaded: {0}]".format(self.loaded_file)
def test_issue_636(): with VideoFileClip("media/big_buck_bunny_0_30.webm").subclip(0, 11) as video: with video.subclip(0, 1) as _: pass
def instaTV(url, firefox, button, bot, chat_id): bot.send_message(chat_id=chat_id, text='Isso pode demorar um pouco', timeout=60) temp_dir = tempfile.mkdtemp() if (auth(url, firefox, button, bot) == True): firefox.get(url) time.sleep(1) html = firefox.page_source time.sleep(1) encodedVideo = re.search(r'"video_url":"(.*?)",', html) if (encodedVideo == None): decoded = '' return decoded else: if (encodedVideo != None): path = temp_dir + '/IGTV.mp4' decoded = (encodedVideo.group(1).replace(r"\u0026", "&")) urllib.request.urlretrieve(decoded, path) size = os.path.getsize(path) / 1000000 if size <= 49.9999: bot.send_video(chat_id=chat_id, video=open(path, 'rb'), timeout=3600) shutil.rmtree(temp_dir) return path else: video = VideoFileClip(path) duration = int(video.duration) start_time = 0 end_time = 600 parts = int(duration / 600) videopart = int(duration / 600) + 1 end_custom = (600 * parts) + (duration % 600) igtvPath = [] if (parts > (video.duration / 600)): parts = parts - 1 if (duration <= 630): bot.send_message(chat_id=chat_id, text='Finalizando ' + runner, timeout=60) subvideo = video.subclip(0, duration) subvideo.write_videofile(temp_dir + '/IGTV' + '01' + '.mp4', threads=8, preset="veryfast", logger=None, audio_codec='aac', rewrite_audio=False, fps=30, bitrate='520k') time.sleep(1) bot.send_video(chat_id=chat_id, video=open( temp_dir + '/IGTV' + '01' + '.mp4', 'rb'), timeout=3600) igtvPath = temp_dir + '/IGTV01.mp4' shutil.rmtree(temp_dir) return igtvPath else: if (duration % 600 == 0): c = 1 for i in range(parts): if (end_time > duration): break subvideo = video.subclip(start_time, end_time) bot.send_message(chat_id=chat_id, text='Processando ' + 'parte ' + str(c) + '/' + str(videopart) + '' + load, timeout=60) subvideo.write_videofile(temp_dir + '/IGTV' + '0' + str(i + 1) + '.mp4', threads=8, preset="veryfast", logger=None, audio_codec='aac', rewrite_audio=False, fps=30, bitrate='550k') time.sleep(1) bot.send_video(chat_id=chat_id, video=open( temp_dir + '/IGTV' + '0' + str(i + 1) + '.mp4', 'rb'), timeout=3600) c += 1 start_time += 600.00 end_time += 600.00 elif (duration % 600 > 0): i = 0 c = 1 while i < parts: subvideo = video.subclip(start_time, end_time) bot.send_message(chat_id=chat_id, text='Processando ' + 'parte ' + str(c) + '/' + str(videopart) + '' + load, timeout=60) subvideo.write_videofile(temp_dir + '/IGTV' + '0' + str(i + 1) + '.mp4', threads=8, preset="veryfast", logger=None, audio_codec='aac', rewrite_audio=False, fps=30, bitrate='550k') time.sleep(1) bot.send_video(chat_id=chat_id, video=open( temp_dir + '/IGTV' + '0' + str(i + 1) + '.mp4', 'rb'), timeout=3600) c += 1 start_time += 600.00 end_time += 600.00 i += 1 if (i == parts): subvideo = video.subclip( start_time, end_custom) bot.send_message(chat_id=chat_id, text='Processando ' + 'parte ' + str(c) + '/' + str(videopart) + '' + load, timeout=60) subvideo.write_videofile(temp_dir + '/IGTV' + '0' + str(i + 1) + '.mp4', threads=8, preset="veryfast", logger=None, audio_codec='aac', rewrite_audio=False, fps=30, bitrate='550k') time.sleep(1) bot.send_video(chat_id=chat_id, video=open( temp_dir + '/IGTV' + '0' + str(i + 1) + '.mp4', 'rb'), timeout=3600) igtvPath = temp_dir shutil.rmtree(temp_dir) return igtvPath else: decoded = '' return decoded
def process_video_file(filepath, output_dir=None, suffix=None, audio_model=None, image_model=None, input_repr="mel256", content_type="music", audio_embedding_size=6144, audio_center=True, audio_hop_size=0.1, image_embedding_size=8192, audio_batch_size=32, image_batch_size=32, overwrite=False, verbose=True): """ Computes and saves L3 audio and video frame embeddings for a given video file Note that image embeddings are computed for every frame of the video. Also note that embeddings for the audio and images are not temporally aligned. Please refer to the timestamps in the output files for the corresponding timestamps for each set of embeddings. Parameters ---------- filepath : str or list[str] Path or list of paths to video file(s) to be processed. output_dir : str or None Path to directory for saving output files. If None, output files will be saved to the directory containing the input file. suffix : str or None String to be appended to the output filename, i.e. <base filename>_<modality>_<suffix>.npz. If None, then no suffix will be added, i.e. <base filename>_<modality>.npz. audio_model : keras.models.Model or None Loaded audio model object. If a model is provided, then `input_repr`, `content_type`, and `embedding_size` will be ignored. If None is provided, the model will be loaded using the provided values of `input_repr`, `content_type` and `embedding_size`. image_model : keras.models.Model or None Loaded audio model object. If a model is provided, then `input_repr`, `content_type`, and `embedding_size` will be ignored. If None is provided, the model will be loaded using the provided values of `input_repr`, `content_type` and `embedding_size`. input_repr : "linear", "mel128", or "mel256" Spectrogram representation used for audio model. Ignored if `model` is a valid Keras model. content_type : "music" or "env" Type of content used to train the embedding model. Ignored if `model` is a valid Keras model. audio_embedding_size : 6144 or 512 Audio embedding dimensionality. Ignored if `model` is a valid Keras model. audio_center : boolean If True, pads beginning of audio signal so timestamps correspond to center of window. audio_hop_size : float Hop size in seconds. image_embedding_size : 8192 or 512 Video frame embedding dimensionality. Ignored if `model` is a valid Keras model. audio_batch_size : int Batch size used for input to audio embedding model image_batch_size : int Batch size used for input to image embedding model overwrite : bool If True, overwrites existing output files verbose : bool If True, prints verbose messages. Returns ------- """ if isinstance(filepath, str): filepath_list = [filepath] elif isinstance(filepath, list): filepath_list = filepath else: err_msg = 'filepath should be type str or list[str], but got {}.' raise OpenL3Error(err_msg.format(filepath)) # Load models if not audio_model: audio_model = load_audio_embedding_model(input_repr, content_type, audio_embedding_size) if not image_model: image_model = load_image_embedding_model(input_repr, content_type, image_embedding_size) audio_suffix, image_suffix = "audio", "image" if suffix: audio_suffix += "_" + suffix image_suffix += "_" + suffix audio_list = [] sr_list = [] audio_batch_filepath_list = [] total_audio_batch_size = 0 image_list = [] frame_rate_list = [] image_batch_filepath_list = [] num_files = len(filepath_list) for file_idx, filepath in enumerate(filepath_list): if not os.path.exists(filepath): raise OpenL3Error('File "{}" could not be found.'.format(filepath)) if verbose: print("openl3: Processing {} ({}/{})".format( filepath, file_idx + 1, num_files)) # Skip if overwriting isn't enabled and output file exists audio_output_path = get_output_path(filepath, audio_suffix + ".npz", output_dir=output_dir) image_output_path = get_output_path(filepath, image_suffix + ".npz", output_dir=output_dir) skip_audio = os.path.exists(audio_output_path) and not overwrite skip_image = os.path.exists(image_output_path) and not overwrite if skip_audio and skip_image: err_msg = "openl3: {} and {} exist, skipping." print(err_msg.format(audio_output_path, image_output_path)) continue try: clip = VideoFileClip(filepath, target_resolution=(256, 256), audio_fps=TARGET_SR) audio = clip.audio.to_soundarray(fps=TARGET_SR) images = np.array([frame for frame in clip.iter_frames()]) except Exception: err_msg = 'Could not open file "{}":\n{}' raise OpenL3Error(err_msg.format(filepath, traceback.format_exc())) if not skip_audio: audio_list.append(audio) sr_list.append(TARGET_SR) audio_batch_filepath_list.append(filepath) audio_len = audio.shape[0] audio_hop_length = int(audio_hop_size * TARGET_SR) num_windows = 1 + max( ceil((audio_len - TARGET_SR) / float(audio_hop_length)), 0) total_audio_batch_size += num_windows else: err_msg = "openl3: {} exists, skipping audio embedding extraction." print(err_msg.format(audio_output_path)) if not skip_image: image_list.append(images) frame_rate_list.append(int(clip.fps)) image_batch_filepath_list.append(filepath) else: err_msg = "openl3: {} exists, skipping image embedding extraction." print(err_msg.format(image_output_path)) if (total_audio_batch_size >= audio_batch_size or file_idx == (num_files - 1)) and len(audio_list) > 0: embedding_list, ts_list \ = get_audio_embedding(audio_list, sr_list, model=audio_model, input_repr=input_repr, content_type=content_type, embedding_size=audio_embedding_size, center=audio_center, hop_size=audio_hop_size, batch_size=audio_batch_size, verbose=verbose) for fpath, embedding, ts in zip(audio_batch_filepath_list, embedding_list, ts_list): output_path = get_output_path(fpath, audio_suffix + ".npz", output_dir=output_dir) np.savez(output_path, embedding=embedding, timestamps=ts) assert os.path.exists(output_path) if verbose: print("openl3: Saved {}".format(output_path)) audio_list = [] sr_list = [] audio_batch_filepath_list = [] total_audio_batch_size = 0 if (len(image_list) >= image_batch_size or file_idx == (num_files - 1)) and len(image_list) > 0: embedding_list, ts_list \ = get_image_embedding(image_list, frame_rate_list, model=image_model, input_repr=input_repr, content_type=content_type, embedding_size=image_embedding_size, batch_size=image_batch_size, verbose=verbose) for fpath, embedding, ts in zip(image_batch_filepath_list, embedding_list, ts_list): output_path = get_output_path(fpath, image_suffix + ".npz", output_dir=output_dir) np.savez(output_path, embedding=embedding, timestamps=ts) assert os.path.exists(output_path) if verbose: print("openl3: Saved {}".format(output_path)) image_list = [] frame_rate_list = [] image_batch_filepath_list = []
def load_media(self, mediafile, play_audio=True): """ Loads a media file to decode. If an audiostream is detected, its parameters will be stored in a dictionary in the variable `audioformat`. This contains the fields :nbytes: the number of bytes in the stream (2 is 16-bit sound). :nchannels: the channels (2 for stereo, 1 for mono) :fps: the frames per sec/sampling rate of the sound (e.g. 44100 KhZ). :buffersize: the audioframes per buffer. If play_audio was set to False, or the video does not have an audiotrack, `audioformat` will be None. Parameters ---------- mediafile : str The path to the media file to load. play_audio : bool, optional Indicates whether the audio of a movie should be played. Raises ------ IOError When the file could not be found or loaded. """ if not mediafile is None: if os.path.isfile(mediafile): self.clip = VideoFileClip(mediafile, audio=play_audio) self.loaded_file = os.path.split(mediafile)[1] ## Timing variables # Clip duration self.duration = self.clip.duration self.clock.max_duration = self.clip.duration logger.debug("Video clip duration: {}s".format(self.duration)) # Frames per second of clip self.fps = self.clip.fps self.clock.fps = self.clip.fps logger.debug("Video clip FPS: {}".format(self.fps)) if play_audio and self.clip.audio: buffersize = int(self.frame_interval*self.clip.audio.fps) self.audioformat = { 'nbytes': 2, 'nchannels': self.clip.audio.nchannels, 'fps': self.clip.audio.fps, 'buffersize': buffersize } logger.debug("Audio loaded: \n{}".format(self.audioformat)) logger.debug("Creating audio buffer of length: " " {}".format(queue_length)) self.audioqueue = Queue(queue_length) else: self.audioformat = None logger.debug('Loaded {0}'.format(mediafile)) self.status = READY return True else: raise IOError("File not found: {0}".format(mediafile)) return False
hough_img = list(map(linedetect, canny_img)) def weightSum(input_set): img = list(input_set) return cv2.addWeighted(img[0], 1, img[1], 0.8, 0) result_img = list(map(weightSum, zip(hough_img, imageList))) # display_images(result_img) def processImage(image): interest = roi(image) filterimg = color_filter(interest) canny = cv2.Canny(grayscale(filterimg), 50, 120) myline = hough_lines(canny, 1, np.pi / 180, 10, 20, 5) weighted_img = cv2.addWeighted(myline, 1, image, 0.8, 0) return weighted_img # we can use camera instead of video clip(port 1 open for usb camera so we can make use of that) output1 = 'test_videos_output/challenge.mp4' clip1 = VideoFileClip("test_videos/challenge.mp4") pclip1 = clip1.fl_image( processImage) # NOTE: this function expects color images!! pclip1.write_videofile(output1, audio=False)
# # undist = undistort(image, calib_params) # # # Warp # warped, M = bird_view(undist) # # # Threshold # binary_image = threshold_image(warped) # Plot the result # result = binary_image # f, (ax1, ax2) = plt.subplots(1, 2, figsize=(24, 9)) # f.tight_layout() # # ax1.imshow(image) # ax1.set_title('Original Image', fontsize=40) # # ax2.imshow(result, cmap='gray') # ax2.set_title('Pipeline Result', fontsize=40) # plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.) # plt.savefig('result.jpg') # plt.show() # Process video Left = Line("left") Right = Line("right") video_output = 'result.mp4' clip1 = VideoFileClip("project_video.mp4") #.subclip(40, 43) white_clip = clip1.fl_image(process) white_clip.write_videofile(video_output, audio=False)
def test_lum_contrast(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm") clip1 = lum_contrast(clip) clip1.write_videofile(os.path.join(TMP_DIR, "lum_contrast1.webm"))
else: cv2.imshow('Video', image) #print("writing to screen") # Hit 'q' on the keyboard to quit! if cv2.waitKey(1) & 0xFF == ord('q'): video_capture.release() break cv2.destroyAllWindows() exit() media_path = self._video_path({ 'name' : video_file }) if not photos: # Process video; start loading the video clip video = VideoFileClip(media_path) # If a duration is set, trim clip if duration: video = video.subclip(start_time, start_time + duration) # Resize clip before processing if width: video = video.resize(width = width) # Crop clip if desired if crop_x: video = video.fx(crop, x2 = video.w / 2) # Kick off convert frames for each frame new_video = video.fl(_convert_helper)
def test_make_loopable(): clip = VideoFileClip("media/big_buck_bunny_0_30.webm").subclip(0, 10) clip1 = make_loopable(clip, 1) clip1.write_videofile(os.path.join(TMP_DIR, "make_loopable1.webm"))
def mp3(mp3_file_name, mp4_file): if alsoAudioFile: videofile = VideoFileClip(mp4_file) if not os.path.exists(audioDir): os.mkdir(audioDir) videofile.audio.write_audiofile(audioDir + mp3_file_name + MP3)
def test_mirror_y(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm") clip1 = mirror_y(clip) clip1.write_videofile(os.path.join(TMP_DIR, "mirror_y1.webm"))
def test_issue_334(): # NOTE: this is horrible. Any simpler version ? last_move = None last_move1 = None lis = [ (0.0, 113, 167, 47), (0.32, 138, 159, 47), (0.44, 152, 144, 47), (0.48, 193, 148, 47), (0.6, 193, 148, 47), (0.76, 205, 138, 55), (0.88, 204, 121, 63), (0.92, 190, 31, 127), (1.2, 183, 59, 127), (1.4, 137, 22, 127), (1.52, 137, 22, 127), (1.72, 129, 67, 127), (1.88, 123, 69, 127), (2.04, 131, 123, 63), (2.24, 130, 148, 63), (2.48, 130, 148, 63), (2.8, 138, 180, 63), (3.0, 138, 180, 63), (3.2, 146, 192, 63), (3.28, 105, 91, 151), (3.44, 105, 91, 151), (3.72, 11, 48, 151), (3.96, 5, 78, 151), (4.32, 4, 134, 1), (4.6, 149, 184, 48), (4.8, 145, 188, 48), (5.0, 154, 217, 48), (5.08, 163, 199, 48), (5.2, 163, 199, 48), (5.32, 164, 187, 48), (5.48, 163, 200, 48), (5.76, 163, 200, 48), (5.96, 173, 199, 48), (6.0, 133, 172, 48), (6.04, 128, 165, 48), (6.28, 128, 165, 48), (6.4, 129, 180, 48), (6.52, 133, 166, 48), (6.64, 133, 166, 48), (6.88, 144, 183, 48), (7.0, 153, 174, 48), (7.16, 153, 174, 48), (7.24, 153, 174, 48), (7.28, 253, 65, 104), (7.64, 253, 65, 104), (7.8, 279, 116, 80), (8.0, 290, 105, 80), (8.24, 288, 124, 80), (8.44, 243, 102, 80), (8.56, 243, 102, 80), (8.8, 202, 107, 80), (8.84, 164, 27, 104), (9.0, 164, 27, 104), (9.12, 121, 9, 104), (9.28, 77, 33, 104), (9.32, 52, 23, 104), (9.48, 52, 23, 104), (9.64, 33, 46, 104), (9.8, 93, 49, 104), (9.92, 93, 49, 104), (10.16, 173, 19, 104), (10.2, 226, 173, 48), (10.36, 226, 173, 48), (10.48, 211, 172, 48), (10.64, 208, 162, 48), (10.92, 220, 171, 48), ] lis1 = [ (0.0, 113, 167, 47), (0.32, 138, 159, 47), (0.44, 152, 144, 47), (0.48, 193, 148, 47), (0.6, 193, 148, 47), (0.76, 205, 138, 55), (0.88, 204, 121, 63), (0.92, 190, 31, 127), (1.2, 183, 59, 127), (1.4, 137, 22, 127), (1.52, 137, 22, 127), (1.72, 129, 67, 127), (1.88, 123, 69, 127), (2.04, 131, 123, 63), (2.24, 130, 148, 63), (2.48, 130, 148, 63), (2.8, 138, 180, 63), (3.0, 138, 180, 63), (3.2, 146, 192, 63), (3.28, 105, 91, 151), (3.44, 105, 91, 151), (3.72, 11, 48, 151), (3.96, 5, 78, 151), (4.32, 4, 134, 1), (4.6, 149, 184, 48), (4.8, 145, 188, 48), (5.0, 154, 217, 48), (5.08, 163, 199, 48), (5.2, 163, 199, 48), (5.32, 164, 187, 48), (5.48, 163, 200, 48), (5.76, 163, 200, 48), (5.96, 173, 199, 48), (6.0, 133, 172, 48), (6.04, 128, 165, 48), (6.28, 128, 165, 48), (6.4, 129, 180, 48), (6.52, 133, 166, 48), (6.64, 133, 166, 48), (6.88, 144, 183, 48), (7.0, 153, 174, 48), (7.16, 153, 174, 48), (7.24, 153, 174, 48), (7.28, 253, 65, 104), (7.64, 253, 65, 104), (7.8, 279, 116, 80), (8.0, 290, 105, 80), (8.24, 288, 124, 80), (8.44, 243, 102, 80), (8.56, 243, 102, 80), (8.8, 202, 107, 80), (8.84, 164, 27, 104), (9.0, 164, 27, 104), (9.12, 121, 9, 104), (9.28, 77, 33, 104), (9.32, 52, 23, 104), (9.48, 52, 23, 104), (9.64, 33, 46, 104), (9.8, 93, 49, 104), (9.92, 93, 49, 104), (10.16, 173, 19, 104), (10.2, 226, 173, 48), (10.36, 226, 173, 48), (10.48, 211, 172, 48), (10.64, 208, 162, 48), (10.92, 220, 171, 48), ] def posi(t): global last_move if len(lis) == 0: return (last_move[1], last_move[2]) if t >= lis[0][0]: last_move = item = lis.pop(0) return (item[1], item[2]) else: if len(lis) > 0: dura = lis[0][0] - last_move[0] now = t - last_move[0] w = (lis[0][1] - last_move[1]) * (now / dura) h = (lis[0][2] - last_move[2]) * (now / dura) # print t, last_move[1] + w, last_move[2] + h return (last_move[1] + w, last_move[2] + h) return (last_move[1], last_move[2]) def size(t): global last_move1 if len(lis1) == 0: return (last_move1[3], last_move1[3] * 1.33) if t >= lis1[0][0]: last_move1 = item = lis1.pop(0) return (item[3], item[3] * 1.33) else: if len(lis) > 0: dura = lis1[0][0] - last_move1[0] now = t - last_move1[0] s = (lis1[0][3] - last_move1[3]) * (now / dura) nsw = last_move1[3] + s nsh = nsw * 1.33 # print t, nsw, nsh return (nsw, nsh) return (last_move1[3], last_move1[3] * 1.33) avatar = VideoFileClip("media/big_buck_bunny_432_433.webm", has_mask=True) avatar.audio = None maskclip = ImageClip("media/afterimage.png", is_mask=True, transparent=True) avatar.with_mask(maskclip) # must set maskclip here.. concatenated = concatenate_videoclips([avatar] * 3) tt = VideoFileClip("media/big_buck_bunny_0_30.webm").subclip(0, 3) # TODO: Setting mask here does not work: # .with_mask(maskclip).resize(size)]) final = CompositeVideoClip( [tt, concatenated.with_position(posi).fx(resize, size)]) final.duration = tt.duration final.write_videofile(os.path.join(TMP_DIR, "issue_334.mp4"), fps=10)
def test_time_mirror(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm") clip1 = time_mirror(clip) assert clip1.duration == clip.duration clip1.write_videofile(os.path.join(TMP_DIR, "time_mirror1.webm"))
def main(): # Load parameters parser = argparse.ArgumentParser( description= 'Locates cars in video and places bounding boxes around them.', usage='%(prog)s [ -vi & -vo | -img ]? [extra_options]') parser.add_argument('-vi', '--video_in', type=str, default='./data/test_videos/test_video.mp4', help='Video to find cars in.') parser.add_argument('-vo', '--video_out', type=str, help='Where to save video to.') parser.add_argument( '-img', '--images_in', type=str, help= 'Search path (glob style) to test images. Cars will be found in images rather than video.' ) parser.add_argument( '-clf', '--clf_savefile', type=str, default='./data/trained_classifier.pkl', help="File path to pickled trained classifier made by 'train.py'") parser.add_argument( '-sc', '--scaler_savefile', type=str, default='./data/Xy_scaler.pkl', help="File path to pickled StandardScalar made by 'train.py'") parser.add_argument( '-viz', '--visualization', type=str, default='cars', help= "'cars' to draw bounding box around cars or 'windows' to show all the detected windows." ) parser.add_argument('-st', '--start', type=int, default=0, help="Timestamp (seconds) to start video.") parser.add_argument('-nd', '--end', type=int, default=None, help="Timestamp (seconds) to end video.") args = parser.parse_args() name, ext = args.video_in.split('/')[-1].rsplit('.', 1) args.video_out = './output/{}_{}.{}'.format(name, args.visualization, ext) # Set up car finder print("Loading classifier from '{}'.".format(args.clf_savefile)) clf = joblib.load(args.clf_savefile) print("Loading scaler from '{}'.".format(args.scaler_savefile)) scaler = joblib.load(args.scaler_savefile) fvb = CarFeatureVectorBuilder(feature_scaler=scaler) car_finder = CarFinder(clf, fvb, args.visualization) # Find cars in... if args.images_in is not None: # run on images print('\nSearching for cars in images...') imgs = [] files = sorted(glob(args.images_in)) for imgf in files: # Find cars image = plt.imread(imgf) display_img = car_finder.find_cars(image, single=True) imgs.append(display_img) n_col = 3 fig, axes = plt.subplots(len(files) // n_col + 1, n_col) for ax, f, img in zip(axes.flatten(), files, imgs): ax.imshow(img) ax.set_title(f) ax.axis('off') plt.show() else: # run on video print("\nFinding cars in '{}',\nthen saving to '{}'...".format( args.video_in, args.video_out)) input_video = VideoFileClip(args.video_in) output_video = input_video.fl_image(car_finder.find_cars).subclip( args.start, args.end) output_video.write_videofile(args.video_out, audio=False)
def process_video(self, in_filename, out_filename, face_filename, keep_audio=True): # extract audio clip from src if keep_audio == True: clip = VideoFileClip(in_filename) clip.audio.write_audiofile("./temp/src_audio.mp3", verbose=False) predictor_path = "./models/shape_predictor_68_face_landmarks.dat" # predictor_path = "./models/shape_predictor_81_face_landmarks.dat" # the smaller this value gets the faster the detection will work # if it is too small, the user's face might not be detected maxImageSizeForDetection = 320 detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor(predictor_path) mean3DShape, blendshapes, mesh, idxs3D, idxs2D = utils.load3DFaceModel( "./models/candide.npz") projectionModel = models.OrthographicProjectionBlendshapes( blendshapes.shape[0]) # open source video vidcap = cv2.VideoCapture(in_filename) # get some parameters from input video width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = int(vidcap.get(cv2.CAP_PROP_FPS)) frames_count = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT)) # create a video writer for output res_filename = "./output/" + out_filename vidwriter = cv2.VideoWriter(res_filename, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), fps, (width, height)) cameraImg = vidcap.read()[1] textureImg = cv2.imread(face_filename) textureCoords = utils.getFaceTextureCoords(textureImg, mean3DShape, blendshapes, idxs2D, idxs3D, detector, predictor) renderer = FaceRendering.FaceRenderer(cameraImg, textureImg, textureCoords, mesh) destShapes2D = utils.getFaceKeypoints(cameraImg, detector, predictor, maxImageSizeForDetection) destShape = destShapes2D[0] modelParams = projectionModel.getInitialParameters( mean3DShape[:, idxs3D], destShape[:, idxs2D]) # 3D model parameter optimization modelParams = NonLinearLeastSquares.GaussNewton( modelParams, projectionModel.residual, projectionModel.jacobian, ([mean3DShape[:, idxs3D], blendshapes[:, :, idxs3D] ], destShape[:, idxs2D]), verbose=0) # rendering the model to an image destShape3D = utils.getShape3D(mean3DShape, blendshapes, modelParams) destRenderedImg = renderer.render(destShape3D) self.progressBar.setRange(0, frames_count - 1) # iterate over the frames and apply the face swap for i in tqdm(range(frames_count - 1)): success, cameraImg = vidcap.read() self.progressBar.setValue(i + 1) if success != True: # no frames left => break break shapes2D = utils.getFaceKeypoints(cameraImg, detector, predictor, maxImageSizeForDetection) newImg = cameraImg try: if shapes2D is not None: for shape2D in shapes2D: # 3D model parameter initialization modelParams = projectionModel.getInitialParameters( mean3DShape[:, idxs3D], shape2D[:, idxs2D]) # 3D model parameter optimization modelParams = NonLinearLeastSquares.GaussNewton( modelParams, projectionModel.residual, projectionModel.jacobian, ([ mean3DShape[:, idxs3D], blendshapes[:, :, idxs3D] ], shape2D[:, idxs2D]), verbose=0) # rendering the model to an image shape3D = utils.getShape3D(mean3DShape, blendshapes, modelParams) renderedImg = renderer.render(shape3D) # blending of the rendered face with the image mask = np.copy(renderedImg[:, :, 0]) mask1 = np.copy(destRenderedImg[:, :, 0]) renderedImg = ImageProcessing.colorTransfer( cameraImg, renderedImg, mask) # newImg = ImageProcessing.blendImages(renderedImg, cameraImg, mask) newImg = ImageProcessing.blendImages0( renderedImg, cameraImg, mask, mask1) except: pass vidwriter.write(newImg) # releas video capture and writer vidcap.release() vidwriter.release() renderer.release() # apply audio clip to generated video if keep_audio == True: video = VideoFileClip("./output/proc_video.avi") video.write_videofile(out_filename, audio="./output/src_audio.mp3", progress_bar=False, verbose=False)
def generate_sequence(self): Utils.log(" - Generating pattern") seq = [] resolution = MixerUtils.new_clip_resolution(-1, -1) is_res_custom = self.config.stitch_strategy() == Config.ST_STRAT_CUSTOM if is_res_custom: resolution.w, resolution.h = self.config.stitch_res_custom() total_duration = 0 max_st_duration = self.config.max_stitch_duration() for each_subject in self.subjects: seq_body = {"name": each_subject} start_at = 0 end_at = 0 min_duration = 0 max_duration = 0 passes = True video_clip = VideoFileClip(each_subject) duration = int(video_clip.duration) seq_body["duration"] = duration # Only if we are in clipping mode, we need to set appropriate bounds if self.config.clipping_mode() == Config.C_CLIP: start_at = self.config.start_at( ) if self.config.start_at() != Config.START_DEF else 0 end_at = self.config.end_at( ) if self.config.end_at() != Config.END_DEF else duration min_duration = duration if self.config.min_duration( ) != Config.DUR_MIN_DEF else self.config.min_duration() max_duration = duration if self.config.max_duration( ) != Config.DUR_MAX_DEF else min(duration, self.config.max_duration()) passes = passes and min_duration <= duration passes = passes and (end_at - start_at) <= min_duration else: start_at = 0 end_at = duration min_duration = duration max_duration = duration if not passes: Utils.log( " [i] Skipping (%s) since its duration checks have failed: Start: (%d), End: (%d), Duration: (%d), Min Duration: (%d), Max Duration: (%d)" % (each_subject, start_at, end_at, duration, min_duration, max_duration)) seq_body["skip"] = True else: final_duration = randint(min_duration, max_duration) start_at = randint(start_at, end_at - final_duration) end_at = start_at + final_duration seq_body["start_at"] = start_at seq_body["end_at"] = end_at seq_body["duration"] = final_duration # Keep track of a rough estimate of the vid length total_duration = total_duration + final_duration # Update resolution final data based on strategy if not is_res_custom: resolution.w, resolution.h = MixerUtils.strategy_select( self.config.stitch_strategy(), resolution, video_clip) seq.append(seq_body) if max_st_duration != Config.ST_MAX_DEF and total_duration > max_st_duration: break # Check the stitch & fill behavior stitch_check = self.config.min_stitch_duration() != Config.ST_MIN_DEF min_stitch_violation = total_duration < self.config.min_stitch_duration( ) min_stitch_filler_non_complaint = self.config.filler( ) != Config.FILL_LOOP if stitch_check and min_stitch_violation and min_stitch_filler_non_complaint: raise "[x] Minimum stitch duration violation: Filler policy non complaint! Expected duration: (%d), Min Stitch duration: (%d), Filler: (%s)" % ( total_duration, self.config.min_stitch_duration(), self.config.filler()) return seq, total_duration, resolution
def test_PR_529(): with VideoFileClip("media/fire2.mp4") as video_clip: assert video_clip.rotation == 180
def test_time_symmetrize(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm") clip1 = time_symmetrize(clip) clip1.write_videofile(os.path.join(TMP_DIR, "time_symmetrize1.webm"))
def test_PR_515(): # Won't actually work until video is in download_media with VideoFileClip("media/fire2.mp4", fps_source="tbr") as clip: assert clip.fps == 90000 with VideoFileClip("media/fire2.mp4", fps_source="fps") as clip: assert clip.fps == 10.51
def test_blackwhite(): with VideoFileClip("media/big_buck_bunny_432_433.webm") as clip: clip1 = blackwhite(clip) clip1.write_videofile(os.path.join(TMP_DIR, "blackwhite1.webm"))
def transform_video(path_in, path_out, checkpoint_dir, device_t='/device:gpu:0', batch_size=8): """ Style transfering for video. Arguments: 'path_in' - input video file, 'path_out' - output video file, 'checkpoint_dir' - path to existing checkpoint with pretrained model 'device_t' - processing device type 'batch_size' - one processing data unit size """ video_clip = VideoFileClip(path_in, audio=False) video_writer = ffmpeg_writer.FFMPEG_VideoWriter(path_out, video_clip.size, video_clip.fps, codec="libx264", preset="medium", bitrate="2000k", audiofile=path_in, threads=None, ffmpeg_params=None) g = tf.Graph() soft_config = tf.ConfigProto(allow_soft_placement=True) soft_config.gpu_options.allow_growth = True with g.as_default(), g.device(device_t), \ tf.Session(config=soft_config) as sess: batch_shape = (batch_size, video_clip.size[1], video_clip.size[0], 3) img_placeholder = tf.placeholder(tf.float32, shape=batch_shape, name='img_placeholder') preds = transform_cnn.net(img_placeholder) saver = tf.train.Saver() if os.path.isdir(checkpoint_dir): ckpt = tf.train.get_checkpoint_state(checkpoint_dir) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path) else: raise Exception("No checkpoint found...") else: saver.restore(sess, checkpoint_dir) X = np.zeros(batch_shape, dtype=np.float32) def style_and_write(count): for i in range(count, batch_size): X[i] = X[count - 1] # Use last frame to fill X _preds = sess.run(preds, feed_dict={img_placeholder: X}) for i in range(0, count): video_writer.write_frame( np.clip(_preds[i], 0, 255).astype(np.uint8)) frame_count = 0 # The frame count that written to X for frame in video_clip.iter_frames(): X[frame_count] = frame frame_count += 1 if frame_count == batch_size: style_and_write(frame_count) frame_count = 0 if frame_count != 0: style_and_write(frame_count) video_writer.close()
def test_colorx(): with VideoFileClip("media/big_buck_bunny_432_433.webm") as clip: clip1 = colorx(clip, 2) clip1.write_videofile(os.path.join(TMP_DIR, "colorx1.webm"))
class MovieStim3(BaseVisualStim, ContainerMixin): """A stimulus class for playing movies (mpeg, avi, etc...) in PsychoPy that does not require avbin. Instead it requires the cv2 python package for OpenCV. The VLC media player also needs to be installed on the psychopy computer. **Example**:: See Movie2Stim.py for demo. """ def __init__(self, win, filename="", units='pix', size=None, pos=(0.0,0.0), ori=0.0, flipVert=False, flipHoriz=False, color=(1.0,1.0,1.0), colorSpace='rgb', opacity=1.0, volume=1.0, name='', loop=False, autoLog=True, depth=0.0, noAudio=False, vframe_callback=None, fps=None, interpolate = True, ): """ :Parameters: filename : a string giving the relative or absolute path to the movie. flipVert : True or *False* If True then the movie will be top-bottom flipped flipHoriz : True or *False* If True then the movie will be right-left flipped volume : The nominal level is 100, and 0 is silence. loop : bool, optional Whether to start the movie over from the beginning if draw is called and the movie is done. """ # what local vars are defined (these are the init params) for use # by __repr__ self._initParams = dir() self._initParams.remove('self') super(MovieStim3, self).__init__(win, units=units, name=name, autoLog=False) retraceRate = win._monitorFrameRate if retraceRate is None: retraceRate = win.getActualFrameRate() if retraceRate is None: logging.warning("FrameRate could not be supplied by psychopy; defaulting to 60.0") retraceRate = 60.0 self._retraceInterval = 1.0/retraceRate self.filename = filename self.loop = loop self.flipVert = flipVert self.flipHoriz = flipHoriz self.pos = numpy.asarray(pos, float) self.depth = depth self.opacity = float(opacity) self.interpolate = interpolate self.noAudio = noAudio self._audioStream = None self.useTexSubImage2D = True self._videoClock = Clock() self.loadMovie(self.filename) self.setVolume(volume) self.nDroppedFrames = 0 #size if size is None: self.size = numpy.array([self._mov.w, self._mov.h], float) else: self.size = val2array(size) self.ori = ori self._updateVertices() #set autoLog (now that params have been initialised) self.autoLog = autoLog if autoLog: logging.exp("Created %s = %s" %(self.name, str(self))) def reset(self): self._numpyFrame = None self._nextFrameT = None self._texID = None self.status = NOT_STARTED def setMovie(self, filename, log=True): """See `~MovieStim.loadMovie` (the functions are identical). This form is provided for syntactic consistency with other visual stimuli. """ self.loadMovie(filename, log=log) def loadMovie(self, filename, log=True): """Load a movie from file :Parameters: filename: string The name of the file, including path if necessary After the file is loaded MovieStim.duration is updated with the movie duration (in seconds). """ self.reset() #set status and timestamps etc # Create Video Stream stuff if os.path.isfile(filename): self._mov = VideoFileClip(filename, audio= (1-self.noAudio)) if (not self.noAudio) and (self._mov.audio is not None): self._audioStream = sound.Sound(self._mov.audio.to_soundarray(), sampleRate = self._mov.audio.fps) else: #make sure we set to None (in case prev clip did have auido) self._audioStream = None else: raise IOError("Movie file '%s' was not found" %filename) #mov has attributes: # size, duration, fps #mov.audio has attributes #duration, fps (aka sampleRate), to_soundarray() self._frameInterval = 1.0/self._mov.fps self.duration = self._mov.duration self.filename = filename self._updateFrameTexture() logAttrib(self, log, 'movie', filename) def play(self, log=True): """Continue a paused movie from current position. """ status = self.status if self._audioStream is not None: self._audioStream.play() if status != PLAYING: self.status = PLAYING self._videoClock.reset(-self.getCurrentFrameTime()) if status == PAUSED: self._audioSeek(self.getCurrentFrameTime()) if log and self.autoLog: self.win.logOnFlip("Set %s playing" %(self.name), level=logging.EXP, obj=self) self._updateFrameTexture() def pause(self, log=True): """ Pause the current point in the movie (sound will stop, current frame will not advance). If play() is called again both will restart. """ if self.status == PLAYING: self.status = PAUSED if self._audioStream: self._audioStream.stop() if log and self.autoLog: self.win.logOnFlip("Set %s paused" %(self.name), level=logging.EXP, obj=self) return True if log and self.autoLog: self.win.logOnFlip("Failed Set %s paused" %(self.name), level=logging.EXP, obj=self) return False def stop(self, log=True): """ Stop the current point in the movie (sound will stop, current frame will not advance). Once stopped the movie cannot be restarted - it must be loaded again. Use pause() if you may need to restart the movie. """ if self.status != STOPPED: self.status = STOPPED self._unload() self._reset() if log and self.autoLog: self.win.logOnFlip("Set %s stopped" %(self.name), level=logging.EXP,obj=self) def setVolume(self, volume): pass #to do def setFlipHoriz(self, newVal=True, log=True): """If set to True then the movie will be flipped horizontally (left-to-right). Note that this is relative to the original, not relative to the current state. """ self.flipHoriz = newVal logAttrib(self, log, 'flipHoriz') def setFlipVert(self, newVal=True, log=True): """If set to True then the movie will be flipped vertically (top-to-bottom). Note that this is relative to the original, not relative to the current state. """ self.flipVert = not newVal logAttrib(self, log, 'flipVert') def getFPS(self): """ Returns the movie frames per second playback speed. """ return self._mov.fps def getCurrentFrameTime(self): """ Get the time that the movie file specified the current video frame as having. """ return self._nextFrameT - self._frameInterval def _updateFrameTexture(self): if self._nextFrameT is None: # movie has no current position, need to reset the clock # to zero in order to have the timing logic work # otherwise the video stream would skip frames until the # time since creating the movie object has passed self._videoClock.reset() self._nextFrameT = 0 #only advance if next frame (half of next retrace rate) if self._nextFrameT > self.duration: self._onEos() elif (self._numpyFrame is not None) and \ (self._nextFrameT > (self._videoClock.getTime()-self._retraceInterval/2.0)): return None self._numpyFrame = self._mov.get_frame(self._nextFrameT) useSubTex=self.useTexSubImage2D if self._texID is None: self._texID = GL.GLuint() GL.glGenTextures(1, ctypes.byref(self._texID)) useSubTex=False #bind the texture in openGL GL.glEnable(GL.GL_TEXTURE_2D) GL.glBindTexture(GL.GL_TEXTURE_2D, self._texID)#bind that name to the target GL.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_WRAP_S,GL.GL_REPEAT) #makes the texture map wrap (this is actually default anyway) GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) # data from PIL/numpy is packed, but default for GL is 4 bytes #important if using bits++ because GL_LINEAR #sometimes extrapolates to pixel vals outside range if self.interpolate: GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR) GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR) if useSubTex is False: GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8, self._numpyFrame.shape[1],self._numpyFrame.shape[0], 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes) else: GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, self._numpyFrame.shape[1], self._numpyFrame.shape[0], GL.GL_RGB, GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes) else: GL.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_NEAREST) GL.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_NEAREST) if useSubTex is False: GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8, self._numpyFrame.shape[1],self._numpyFrame.shape[0], 0, GL.GL_BGR, GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes) else: GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, self._numpyFrame.shape[1], self._numpyFrame.shape[0], GL.GL_BGR, GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes) GL.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE)#?? do we need this - think not! if not self.status==PAUSED: self._nextFrameT += self._frameInterval def draw(self, win=None): """ Draw the current frame to a particular visual.Window (or to the default win for this object if not specified). The current position in the movie will be determined automatically. This method should be called on every frame that the movie is meant to appear""" if self.status==NOT_STARTED or (self.status==FINISHED and self.loop): self.play() elif self.status == FINISHED and not self.loop: return if win is None: win = self.win self._selectWindow(win) self._updateFrameTexture() #will check if it's needed yet in the function #scale the drawing frame and get to centre of field GL.glPushMatrix()#push before drawing, pop after GL.glPushClientAttrib(GL.GL_CLIENT_ALL_ATTRIB_BITS)#push the data for client attributes self.win.setScale('pix') #move to centre of stimulus and rotate vertsPix = self.verticesPix #bind textures GL.glActiveTexture (GL.GL_TEXTURE1) GL.glBindTexture (GL.GL_TEXTURE_2D,0) GL.glEnable(GL.GL_TEXTURE_2D) GL.glActiveTexture (GL.GL_TEXTURE0) GL.glBindTexture (GL.GL_TEXTURE_2D, self._texID) GL.glEnable(GL.GL_TEXTURE_2D) GL.glColor4f(1, 1, 1, self.opacity) # sets opacity (1,1,1 = RGB placeholder) array = (GL.GLfloat * 32)( 1, 1, #texture coords vertsPix[0,0], vertsPix[0,1], 0., #vertex 0, 1, vertsPix[1,0], vertsPix[1,1], 0., 0, 0, vertsPix[2,0], vertsPix[2,1], 0., 1, 0, vertsPix[3,0], vertsPix[3,1], 0., ) #2D texture array, 3D vertex array GL.glInterleavedArrays(GL.GL_T2F_V3F, 0, array) GL.glDrawArrays(GL.GL_QUADS, 0, 4) GL.glPopClientAttrib(GL.GL_CLIENT_ALL_ATTRIB_BITS) GL.glPopAttrib(GL.GL_ENABLE_BIT) GL.glPopMatrix() #unbind the textures GL.glActiveTexture(GL.GL_TEXTURE0) GL.glBindTexture(GL.GL_TEXTURE_2D, 0) GL.glEnable(GL.GL_TEXTURE_2D)#implicitly disables 1D def seek(self, t): """Go to a specific point in time for both the audio and video streams """ #video is easy: set both times to zero and update the frame texture self._nextFrameT = t self._videoClock.reset(t) self._audioSeek(t) def _audioSeek(self, t): #for sound we need to extract the array again and just begin at new loc if self._audioStream is None: return #do nothing self._audioStream.stop() sndArray = self._mov.audio.to_soundarray() startIndex = int(t*self._mov.audio.fps) self._audioStream = sound.Sound(sndArray[startIndex:,:], sampleRate = self._mov.audio.fps) self._audioStream.play() def _getAudioStreamTime(self): return self._audio_stream_clock.getTime() def _unload(self): try: self.clearTextures()#remove textures from graphics card to prevent crash except: pass self._mov = None self._numpyFrame = None self._audioStream = None self.status = FINISHED def _onEos(self): if self.loop: self.seek(0.0) else: self.status = FINISHED self.stop() if self.autoLog: self.win.logOnFlip("Set %s finished" %(self.name), level=logging.EXP,obj=self) def __del__(self): self._unload() def setAutoDraw(self, val, log=None): """Add or remove a stimulus from the list of stimuli that will be automatically drawn on each flip :parameters: - val: True/False True to add the stimulus to the draw list, False to remove it """ if val: self.play(log=False) # set to play in case stopped else: self.pause(log=False) #add to drawing list and update status setAttribute(self, 'autoDraw', val, log)
def test_fadeout(): with VideoFileClip("media/big_buck_bunny_0_30.webm").subclip(0, 5) as clip: clip1 = fadeout(clip, 1) clip1.write_videofile(os.path.join(TMP_DIR, "fadeout1.webm"))