def test_set_duration(): bitmap = [["R"], ["R"], ["B"], ["B"], ["G"], ["G"]] clip = BitmapClip(bitmap) duration_clip = clip.set_duration(len(bitmap)) assert duration_clip.fps == 1 assert duration_clip.duration == 6
def test_write_gif(util, clip_class, opt, loop, with_mask, pixel_format): filename = os.path.join(util.TMP_DIR, "moviepy_write_gif.gif") if os.path.isfile(filename): os.remove(filename) fps = 10 if clip_class == "BitmapClip": original_clip = BitmapClip([["R"], ["G"], ["B"]], fps=fps).with_duration(0.3) else: original_clip = concatenate_videoclips([ ColorClip( (1, 1), color=color, ).with_duration(0.1).with_fps(fps) for color in [(255, 0, 0), (0, 255, 0), (0, 0, 255)] ]) if with_mask: original_clip = original_clip.with_mask( ColorClip((1, 1), color=1, is_mask=True).with_fps(fps).with_duration(0.3)) kwargs = {} if pixel_format is not None: kwargs["pixel_format"] = pixel_format write_gif( original_clip, filename, fps=fps, with_mask=with_mask, program="ffmpeg", logger=None, opt=opt, loop=loop, **kwargs, ) if pixel_format != "invalid": final_clip = VideoFileClip(filename) r, g, b = final_clip.get_frame(0)[0][0] assert r == 252 assert g == 0 assert b == 0 r, g, b = final_clip.get_frame(0.1)[0][0] assert r == 0 assert g == 252 assert b == 0 r, g, b = final_clip.get_frame(0.2)[0][0] assert r == 0 assert g == 0 assert b == 255 assert final_clip.duration == (loop or 1) * round( original_clip.duration, 6)
def test_clip_with_is_mask(): clip = BitmapClip([["RR", "GG"]], fps=1) assert not clip.is_mask assert clip.with_is_mask(True).is_mask assert not clip.with_is_mask(False).is_mask
def test_set_fps(): bitmap = [["R"], ["R"], ["B"], ["B"], ["G"], ["G"]] clip = BitmapClip(bitmap) fps_clip = clip.set_fps(1) assert fps_clip.fps == 1 assert fps_clip.duration == 6
def test_rotate(angle_offset): # Run several times to ensure that adding 360 to rotation angles has no effect clip = BitmapClip([["AAAA", "BBBB", "CCCC"], ["ABCD", "BCDE", "CDEA"]]).set_fps(1) clip1 = rotate(clip, 0 + angle_offset) target1 = BitmapClip([["AAAA", "BBBB", "CCCC"], ["ABCD", "BCDE", "CDEA"]]).set_fps( 1 ) assert clip1 == target1 clip2 = rotate(clip, 90 + angle_offset) target2 = BitmapClip( [["ABC", "ABC", "ABC", "ABC"], ["DEA", "CDE", "BCD", "ABC"]] ).set_fps(1) assert clip2 == target2, clip2.to_bitmap() clip3 = rotate(clip, 180 + angle_offset) target3 = BitmapClip([["CCCC", "BBBB", "AAAA"], ["AEDC", "EDCB", "DCBA"]]).set_fps( 1 ) assert clip3 == target3 clip4 = rotate(clip, 270 + angle_offset) target4 = BitmapClip( [["CBA", "CBA", "CBA", "CBA"], ["CBA", "DCB", "EDC", "AED"]] ).set_fps(1) assert clip4 == target4
def test_colorx(): color_dict = {"H": (0, 0, 200), "L": (0, 0, 50), "B": (0, 0, 255), "O": (0, 0, 0)} clip = BitmapClip([["LLO", "BLO"]], color_dict=color_dict, fps=1) clipfx = colorx(clip, 4) target = BitmapClip([["HHO", "BHO"]], color_dict=color_dict, fps=1) assert target == clipfx
def test_compositing_with_same_layers(): bottom_clip = BitmapClip([["ABC"], ["BCA"]], fps=1) top_clip = BitmapClip([["DEF"], ["EFD"]], fps=1) composite_clip = CompositeVideoClip([bottom_clip, top_clip]) reversed_composite_clip = CompositeVideoClip([top_clip, bottom_clip]) assert composite_clip == top_clip assert reversed_composite_clip == bottom_clip
def test_concatenate_self(util): clip = BitmapClip([["AAA", "BBB"], ["CCC", "DDD"]], fps=1) target = BitmapClip([["AAA", "BBB"], ["CCC", "DDD"]], fps=1) concatenated = concatenate_videoclips([clip]) concatenated.write_videofile( os.path.join(util.TMP_DIR, "test_concatenate_self.mp4")) assert concatenated == target
def test_clip_equality(): bitmap = [["RR", "RR"], ["RB", "RB"]] different_bitmap = [["RR", "RB"], ["RB", "RB"]] clip = BitmapClip(bitmap).set_fps(1) same_clip = BitmapClip(bitmap).set_fps(1) different_clip = BitmapClip(different_bitmap).set_fps(1) assert clip == same_clip assert clip != different_clip
def test_to_bitmap(): bitmap = [["R"], ["R"], ["B"], ["B"], ["G"], ["G"]] clip1 = BitmapClip(bitmap, fps=0.345) clip2 = BitmapClip(bitmap, fps=1) clip3 = BitmapClip(bitmap, fps=3.12345) assert bitmap == clip1.to_bitmap() assert bitmap == clip2.to_bitmap() assert bitmap == clip3.to_bitmap()
def test_invert_colors(): clip = BitmapClip( [["AB", "BC"]], color_dict={"A": (0, 0, 0), "B": (50, 100, 150), "C": (255, 255, 255)}, ).set_fps(1) clip1 = invert_colors(clip) target1 = BitmapClip( [["CD", "DA"]], color_dict={"A": (0, 0, 0), "D": (205, 155, 105), "C": (255, 255, 255)}, ).set_fps(1) assert clip1 == target1
def test_copied_videoclip_write_videofile(): """Check if a copied ``VideoClip`` instance can render a file which has the same features as the copied clip when opening with ``VideoFileClip``. """ clip = BitmapClip([["RRR", "GGG", "BBB"]], fps=1) copied_clip = clip.copy() output_filepath = os.path.join(TMP_DIR, "copied_videoclip_from_bitmap.webm") copied_clip.write_videofile(output_filepath) copied_clip_from_file = VideoFileClip(output_filepath) assert list(copied_clip.size) == list(copied_clip_from_file.size) assert copied_clip.duration == copied_clip_from_file.duration
def test_time_mirror(): clip = BitmapClip([["AA", "AA"], ["BB", "BB"], ["CC", "CC"]], fps=1) clip1 = time_mirror(clip) target1 = BitmapClip([["CC", "CC"], ["BB", "BB"], ["AA", "AA"]], fps=1) assert clip1 == target1 clip2 = BitmapClip( [["AA", "AA"], ["BB", "BB"], ["CC", "CC"], ["DD", "DD"]], fps=1) clip3 = time_mirror(clip2) target3 = BitmapClip( [["DD", "DD"], ["CC", "CC"], ["BB", "BB"], ["AA", "AA"]], fps=1) assert clip3 == target3
def test_freeze_region(): clip = BitmapClip([["AAB", "CCC"], ["BBR", "DDD"], ["CCC", "ABC"]], fps=1) # Test region clip1 = freeze_region(clip, t=1, region=(2, 0, 3, 1)) target1 = BitmapClip([["AAR", "CCC"], ["BBR", "DDD"], ["CCR", "ABC"]], fps=1) assert clip1 == target1 # Test outside_region clip2 = freeze_region(clip, t=1, outside_region=(2, 0, 3, 1)) target2 = BitmapClip([["BBB", "DDD"], ["BBR", "DDD"], ["BBC", "DDD"]], fps=1) assert clip2 == target2 pass
def test_time_symmetrize(): clip = BitmapClip([["AA", "AA"], ["BB", "BB"], ["CC", "CC"]]).set_fps(1) clip1 = time_symmetrize(clip) target1 = BitmapClip( [ ["AA", "AA"], ["BB", "BB"], ["CC", "CC"], ["CC", "CC"], ["BB", "BB"], ["AA", "AA"], ] ).set_fps(1) assert clip1 == target1
def test_clip_memoize(): clip = BitmapClip([["RR", "RR"], ["GG", "GG"], ["BB", "BB"]], fps=1) assert not clip.memoize memoize_clip = clip.with_memoize(True) assert memoize_clip.memoize # get_frame memoizing memoize_clip.memoized_t = 5 memoize_clip.memoized_frame = "foo" assert memoize_clip.get_frame(5) == "foo" assert isinstance(memoize_clip.get_frame(1), np.ndarray)
def test_clip_equality(): bitmap = [["RR", "RR"], ["RB", "RB"]] different_bitmap = [["RR", "RB"], ["RB", "RB"]] different_duration_bitmap = [["RR", "RR"], ["RB", "RB"], ["RR", "RR"]] clip = BitmapClip(bitmap, fps=1) same_clip = BitmapClip(bitmap, fps=1) different_clip = BitmapClip(different_bitmap, fps=1) different_duration_clip = BitmapClip(different_duration_bitmap, fps=1) assert clip == same_clip assert clip != different_clip assert clip != different_duration_clip assert different_clip != different_duration_clip
def test_margin(): clip = BitmapClip([["RRR", "RRR"], ["RRB", "RRB"]], fps=1) # Make sure that the default values leave clip unchanged clip1 = margin(clip) assert clip == clip1 # 1 pixel black margin clip2 = margin(clip, mar=1) target = BitmapClip( [ [ "OOOOO", "ORRRO", "ORRRO", "OOOOO", ], [ "OOOOO", "ORRBO", "ORRBO", "OOOOO", ], ], fps=1, ) assert target == clip2 # 1 pixel green margin clip3 = margin(clip, mar=1, color=(0, 255, 0)) target = BitmapClip( [ [ "GGGGG", "GRRRG", "GRRRG", "GGGGG", ], [ "GGGGG", "GRRBG", "GRRBG", "GGGGG", ], ], fps=1, ) assert target == clip3
def test_set_layer(): bottom_clip = BitmapClip([["ABC"], ["BCA"], ["CAB"]], fps=1).set_layer(1) top_clip = BitmapClip([["DEF"], ["EFD"]], fps=1).set_layer(2) composite_clip = CompositeVideoClip([bottom_clip, top_clip]) reversed_composite_clip = CompositeVideoClip([top_clip, bottom_clip]) # Make sure that the order of clips makes no difference to the composite clip assert composite_clip.subclip(0, 2) == reversed_composite_clip.subclip(0, 2) # Make sure that only the 'top' clip is kept assert top_clip.subclip(0, 2) == composite_clip.subclip(0, 2) # Make sure that it works even when there is only one clip playing at that time target_clip = BitmapClip([["DEF"], ["EFD"], ["CAB"]], fps=1) assert composite_clip == target_clip
def test_crop(): # x: 0 -> 4, y: 0 -> 3 inclusive clip = BitmapClip([["ABCDE", "EDCBA", "CDEAB", "BAEDC"]], fps=1) clip1 = crop(clip) target1 = BitmapClip([["ABCDE", "EDCBA", "CDEAB", "BAEDC"]], fps=1) assert clip1 == target1 clip2 = crop(clip, x1=1, y1=1, x2=3, y2=3) target2 = BitmapClip([["DC", "DE"]], fps=1) assert clip2 == target2 clip3 = crop(clip, y1=2) target3 = BitmapClip([["CDEAB", "BAEDC"]], fps=1) assert clip3 == target3 clip4 = crop(clip, x1=2, width=2) target4 = BitmapClip([["CD", "CB", "EA", "ED"]], fps=1) assert clip4 == target4 # TODO x_center=1 does not perform correctly clip5 = crop(clip, x_center=2, y_center=2, width=3, height=3) target5 = BitmapClip([["ABC", "EDC", "CDE"]], fps=1) assert clip5 == target5 clip6 = crop(clip, x_center=2, width=2, y1=1, y2=2) target6 = BitmapClip([["DC"]], fps=1) assert clip6 == target6
def test_freeze(): clip = BitmapClip([["R"], ["G"], ["B"]], fps=1) # 3 separate frames clip1 = freeze(clip, t=1, freeze_duration=1) target1 = BitmapClip([["R"], ["G"], ["G"], ["B"]], fps=1) assert clip1 == target1 clip2 = freeze(clip, t="end", freeze_duration=1) target2 = BitmapClip([["R"], ["G"], ["B"], ["B"]], fps=1) assert clip2 == target2 clip3 = freeze(clip, t=1, total_duration=4) target3 = BitmapClip([["R"], ["G"], ["G"], ["B"]], fps=1) assert clip3 == target3 clip4 = freeze(clip, t="end", total_duration=4, padding_end=1) target4 = BitmapClip([["R"], ["G"], ["G"], ["B"]], fps=1) assert clip4 == target4
def test_fadein(): color_dict = { "I": (0, 0, 0), "R": (255, 0, 0), "G": (0, 255, 0), "B": (0, 0, 255), "W": (255, 255, 255), } clip = BitmapClip([["R"], ["G"], ["B"]], color_dict=color_dict, fps=1) clip1 = fadein(clip, 1) # default initial color target1 = BitmapClip([["I"], ["G"], ["B"]], color_dict=color_dict, fps=1) assert clip1 == target1 clip2 = fadein(clip, 1, initial_color=(255, 255, 255)) # different initial color target2 = BitmapClip([["W"], ["G"], ["B"]], color_dict=color_dict, fps=1) assert clip2 == target2
def test_clip_generation(): bitmap = [["RR", "RR"], ["RB", "RB"]] expected_frame_array = np.array([ np.array([[(255, 0, 0), (255, 0, 0)], [(255, 0, 0), (255, 0, 0)]]), np.array([[(255, 0, 0), (0, 0, 255)], [(255, 0, 0), (0, 0, 255)]]), ]) unexpected_frame_array = np.array([ np.array([[(255, 0, 0), (255, 0, 0)], [(255, 0, 0), (255, 0, 1)]]), np.array([[(255, 0, 0), (0, 0, 255)], [(255, 0, 0), (0, 0, 255)]]), ]) clip = BitmapClip(bitmap, fps=1) frame_array = np.array(list(clip.iter_frames())) # Check that frame_list == expected_frame_list assert np.array_equal(frame_array, expected_frame_array) # Check that frame_list != unexpected_frame_list assert not np.array_equal(frame_array, unexpected_frame_array)
def test_loop(): clip = BitmapClip([["R"], ["G"], ["B"]], fps=1) clip1 = loop(clip, n=2) # loop 2 times target1 = BitmapClip([["R"], ["G"], ["B"], ["R"], ["G"], ["B"]], fps=1) assert clip1 == target1 clip2 = loop(clip, duration=8) # loop 8 seconds target2 = BitmapClip( [["R"], ["G"], ["B"], ["R"], ["G"], ["B"], ["R"], ["G"]], fps=1) assert clip2 == target2 clip3 = loop(clip).with_duration(5) # infinite loop target3 = BitmapClip([["R"], ["G"], ["B"], ["R"], ["G"]], fps=1) assert clip3 == target3 clip = get_test_video() clip1 = loop(clip).with_duration(3) # infinite looping clip1.write_videofile(os.path.join(TMP_DIR, "loop1.webm")) return # Still buggy. TODO fix
def test_clip_subclip(duration, start_time, end_time, expected_duration): if duration is None: clip = ColorClip(color=(255, 0, 0), size=(2, 2)).with_fps(1) else: clip = BitmapClip([["RR", "GG"] for _ in range(duration)], fps=1) if hasattr(expected_duration, "__traceback__"): with pytest.raises(expected_duration): clip.subclip(start_time=start_time, end_time=end_time) else: sub_clip = clip.subclip(start_time=start_time, end_time=end_time) assert sub_clip.duration == expected_duration
def test_save_frame(util, with_mask, t, mask_color, frames): filename = os.path.join(util.TMP_DIR, "moviepy_VideoClip_save_frame.png") if os.path.isfile(filename): try: os.remove(filename) except PermissionError: pass width, height = (len(frames[0][0]), len(frames[0])) clip = BitmapClip(frames, fps=1) if with_mask: mask = ColorClip(color=mask_color, is_mask=True, size=(width, height)) clip = clip.with_mask(mask) clip.save_frame(filename, t) t = int(convert_to_seconds(t)) # expected RGB e_r, e_g, e_b = BitmapClip.DEFAULT_COLOR_DICT[frames[t][0][0]] im = Image.open(filename, mode="r") assert im.width == width assert im.height == height for i in range(im.width): for j in range(im.height): rgba = im.getpixel((i, j)) if len(rgba) == 4: r, g, b, a = rgba else: r, g, b = rgba assert r == e_r assert g == e_g assert b == e_b if with_mask: assert round(a / 254, 2) == mask_color
def test_speedx(): clip = BitmapClip([["A"], ["B"], ["C"], ["D"]], fps=1) clip1 = speedx(clip, 0.5) # 1/2x speed target1 = BitmapClip( [["A"], ["A"], ["B"], ["B"], ["C"], ["C"], ["D"], ["D"]], fps=1 ) assert clip1 == target1 clip2 = speedx(clip, final_duration=8) # 1/2x speed target2 = BitmapClip( [["A"], ["A"], ["B"], ["B"], ["C"], ["C"], ["D"], ["D"]], fps=1 ) assert clip2 == target2 clip3 = speedx(clip, final_duration=12) # 1/2x speed target3 = BitmapClip( [ ["A"], ["A"], ["A"], ["B"], ["B"], ["B"], ["C"], ["C"], ["C"], ["D"], ["D"], ["D"], ], fps=1, ) assert clip3 == target3 clip4 = speedx(clip, 2) # 2x speed target4 = BitmapClip([["A"], ["C"]], fps=1) assert clip4 == target4 clip5 = speedx(clip, final_duration=2) # 2x speed target5 = BitmapClip([["A"], ["C"]], fps=1) assert clip5 == target5 clip6 = speedx(clip, 4) # 4x speed target6 = BitmapClip([["A"]], fps=1) assert ( clip6 == target6 ), f"{clip6.duration} {target6.duration} {clip6.fps} {target6.fps}"
def test_even_size(): clip1 = BitmapClip([["ABC", "BCD"]], fps=1) # Width odd clip1even = even_size(clip1) target1 = BitmapClip([["AB", "BC"]], fps=1) assert clip1even == target1 clip2 = BitmapClip([["AB", "BC", "CD"]], fps=1) # Height odd clip2even = even_size(clip2) target2 = BitmapClip([["AB", "BC"]], fps=1) assert clip2even == target2 clip3 = BitmapClip([["ABC", "BCD", "CDE"]], fps=1) # Width and height odd clip3even = even_size(clip3) target3 = BitmapClip([["AB", "BC"]], fps=1) assert clip3even == target3
def test_videoclip_copy(copy_func): """It must be possible to do a mixed copy of VideoClip using ``clip.copy()``, ``copy.copy(clip)`` and ``copy.deepcopy(clip)``. """ clip = VideoClip() other_clip = VideoClip() for attr in clip.__dict__: # mask and audio are shallow copies that should be initialized if attr in ("mask", "audio"): if attr == "mask": nested_object = BitmapClip([["R"]], duration=0.01) else: nested_object = AudioClip( lambda t: [np.sin(880 * 2 * np.pi * t)], duration=0.01, fps=44100) setattr(clip, attr, nested_object) else: setattr(clip, attr, "foo") copied_clip = copy_func(clip) # VideoClip attributes are copied for attr in copied_clip.__dict__: value = getattr(copied_clip, attr) assert value == getattr(clip, attr) # other instances are not edited assert value != getattr(other_clip, attr) # shallow copies of mask and audio if attr in ("mask", "audio"): for nested_attr in value.__dict__: assert getattr(value, nested_attr) == getattr(getattr(clip, attr), nested_attr) # nested objects of instances copies are not edited assert other_clip.mask is None assert other_clip.audio is None
def test_FramesMatches_from_clip( bitmap, expected_matches, distance_threshold, max_duration, ): clip = BitmapClip(bitmap, fps=1) matching_frames = FramesMatches.from_clip( clip, distance_threshold, max_duration, logger=None, ) assert matching_frames assert isinstance(matching_frames, FramesMatches) assert isinstance(matching_frames[0], FramesMatch) for i, match in enumerate(matching_frames): for j, n in enumerate(match): assert round(n, 4) == expected_matches[i][j]