diff --git a/CHANGELOG.md b/CHANGELOG.md index bb3d1c79e..1d8f0b4df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support pillow 11 ### Changed +- Subclipping outside of clip boundaries now raise an exception ### Deprecated diff --git a/moviepy/Clip.py b/moviepy/Clip.py index e931f5551..2d4c0b2fd 100644 --- a/moviepy/Clip.py +++ b/moviepy/Clip.py @@ -422,6 +422,14 @@ def subclipped(self, start_time=0, end_time=None): end_time = self.duration + end_time if end_time is not None: + # Allow a slight tolerance to account for rounding errors + if (self.duration is not None) and (end_time - self.duration > 0.00000001): + raise ValueError( + "end_time (%.02f) " % end_time + + "should be smaller or equal to the clip's " + + "duration (%.02f)." % self.duration + ) + new_clip.duration = end_time - start_time new_clip.end = new_clip.start + new_clip.duration diff --git a/tests/test_Clip.py b/tests/test_Clip.py index 397f228bb..0dcabf841 100644 --- a/tests/test_Clip.py +++ b/tests/test_Clip.py @@ -184,6 +184,7 @@ def test_clip_copy(copy_func): (3, 3, None, ValueError), # start_time == duration (3, 1, -1, 1), # negative end_time (None, 1, -1, ValueError), # negative end_time for clip without duration + (1, 0, 2, ValueError), # end_time after video end should raise exception ), ) def test_clip_subclip(duration, start_time, end_time, expected_duration): diff --git a/tests/test_VideoClip.py b/tests/test_VideoClip.py index 53c04817b..6cd61bb76 100644 --- a/tests/test_VideoClip.py +++ b/tests/test_VideoClip.py @@ -389,16 +389,16 @@ def test_afterimage(util): def test_add(): clip = VideoFileClip("media/fire2.mp4") - new_clip = clip[0:1] + clip[2:3.2] - assert new_clip.duration == 2.2 - assert np.array_equal(new_clip[1.1], clip[2.1]) + new_clip = clip[0:1] + clip[1.5:2] + assert new_clip.duration == 1.5 + assert np.array_equal(new_clip[1.1], clip[1.6]) def test_slice_tuples(): clip = VideoFileClip("media/fire2.mp4") - new_clip = clip[0:1, 2:3.2] - assert new_clip.duration == 2.2 - assert np.array_equal(new_clip[1.1], clip[2.1]) + new_clip = clip[0:1, 1.5:2] + assert new_clip.duration == 1.5 + assert np.array_equal(new_clip[1.1], clip[1.6]) def test_slice_mirror(): diff --git a/tests/test_issues.py b/tests/test_issues.py index ae2d6acda..79a086df9 100644 --- a/tests/test_issues.py +++ b/tests/test_issues.py @@ -303,9 +303,8 @@ def test_issue_470(util): audio_clip = AudioFileClip("media/crunching.mp3") # end_time is out of bounds - subclip = audio_clip.subclipped(start_time=6, end_time=9) - - with pytest.raises(IOError): + with pytest.raises(ValueError): + subclip = audio_clip.subclipped(start_time=6, end_time=9) subclip.write_audiofile(wav_filename, write_logfile=True) # but this one should work.. @@ -334,7 +333,7 @@ def test_issue_636(): def test_issue_655(): video_file = "media/fire2.mp4" - for subclip in [(0, 2), (1, 2), (2, 3)]: + for subclip in [(0, 2), (1, 2), (2, 2.10)]: with VideoFileClip(video_file) as v: with v.subclipped(1, 2) as _: pass