From 12cfa053145de661e333fece64ea30d1972ddd05 Mon Sep 17 00:00:00 2001 From: Mikel Bober-Irizar Date: Sun, 4 Oct 2020 11:16:28 +0100 Subject: [PATCH 1/5] Add change_duration flag to Clip.set_fps() --- moviepy/Clip.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/moviepy/Clip.py b/moviepy/Clip.py index c135dff7a..42cec9f09 100644 --- a/moviepy/Clip.py +++ b/moviepy/Clip.py @@ -298,11 +298,20 @@ def set_make_frame(self, make_frame): """ self.make_frame = make_frame - @outplace - def set_fps(self, fps): + def set_fps(self, fps, change_duration=False): """Returns a copy of the clip with a new default fps for functions like - write_videofile, iterframe, etc.""" - self.fps = fps + write_videofile, iterframe, etc. + If ``change_duration=True``, then the video speed will change to match the + new fps (conserving all frames 1:1). For example, if the fps is + halved in this mode, the duration will be doubled.""" + + if change_duration: + newclip = self.speedx(fps / self.fps) + else: + newclip = self.copy() + + newclip.fps = fps + return newclip @outplace def set_ismask(self, ismask): From 53925ab9047ffc4f60a9e47155bf44635a0b1c60 Mon Sep 17 00:00:00 2001 From: Mikel Bober-Irizar Date: Sun, 4 Oct 2020 12:24:57 +0100 Subject: [PATCH 2/5] Add speedx import to set_fps with change_duration --- moviepy/Clip.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/moviepy/Clip.py b/moviepy/Clip.py index 42cec9f09..587c4d560 100644 --- a/moviepy/Clip.py +++ b/moviepy/Clip.py @@ -306,7 +306,8 @@ def set_fps(self, fps, change_duration=False): halved in this mode, the duration will be doubled.""" if change_duration: - newclip = self.speedx(fps / self.fps) + from moviepy.video.fx.speedx import speedx + newclip = speedx(self, fps / self.fps) else: newclip = self.copy() From b0552407c0f2da862bf38efcd8efd1cdcabdc4fa Mon Sep 17 00:00:00 2001 From: Mikel Bober-Irizar Date: Sun, 4 Oct 2020 12:25:21 +0100 Subject: [PATCH 3/5] Add VideoClip.set_fps tests --- tests/test_VideoClip.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/test_VideoClip.py b/tests/test_VideoClip.py index a1ba719ae..b5c458f9c 100644 --- a/tests/test_VideoClip.py +++ b/tests/test_VideoClip.py @@ -260,6 +260,29 @@ def test_withoutaudio(): assert new_clip.audio is None close_all_clips(locals()) +def test_setfps_withoutchangeduration(): + clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0, 1) + # The sum is unique for each frame, so we can use it as a frame-ID + # to check which frames are being preserved + clip_sums = [f.sum() for f in clip.iter_frames()] + + clip2 = clip.set_fps(48) + clip2_sums = [f.sum() for f in clip2.iter_frames()] + assert clip2_sums[::2] == clip_sums + assert clip2.duration == clip.duration + close_all_clips(locals()) + +def test_setfps_withchangeduration(): + clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0, 1) + # The sum is unique for each frame, so we can use it as a frame-ID + # to check which frames are being preserved + clip_sums = [f.sum() for f in clip.iter_frames()] + + clip2 = clip.set_fps(48, change_duration=True) + clip2_sums = [f.sum() for f in clip2.iter_frames()] + assert clip2_sums == clip_sums + assert clip2.duration == clip.duration / 2 + close_all_clips(locals()) if __name__ == "__main__": pytest.main() From a1392d1d6e97dbec877a208bc8b628a463eb9e87 Mon Sep 17 00:00:00 2001 From: Mikel Bober-Irizar Date: Sun, 4 Oct 2020 12:27:05 +0100 Subject: [PATCH 4/5] Black format set_fps tests --- moviepy/Clip.py | 1 + tests/test_VideoClip.py | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/moviepy/Clip.py b/moviepy/Clip.py index 587c4d560..c1318ef93 100644 --- a/moviepy/Clip.py +++ b/moviepy/Clip.py @@ -307,6 +307,7 @@ def set_fps(self, fps, change_duration=False): if change_duration: from moviepy.video.fx.speedx import speedx + newclip = speedx(self, fps / self.fps) else: newclip = self.copy() diff --git a/tests/test_VideoClip.py b/tests/test_VideoClip.py index b5c458f9c..ae7a5dad6 100644 --- a/tests/test_VideoClip.py +++ b/tests/test_VideoClip.py @@ -260,9 +260,10 @@ def test_withoutaudio(): assert new_clip.audio is None close_all_clips(locals()) + def test_setfps_withoutchangeduration(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0, 1) - # The sum is unique for each frame, so we can use it as a frame-ID + # The sum is unique for each frame, so we can use it as a frame-ID # to check which frames are being preserved clip_sums = [f.sum() for f in clip.iter_frames()] @@ -272,9 +273,10 @@ def test_setfps_withoutchangeduration(): assert clip2.duration == clip.duration close_all_clips(locals()) + def test_setfps_withchangeduration(): clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0, 1) - # The sum is unique for each frame, so we can use it as a frame-ID + # The sum is unique for each frame, so we can use it as a frame-ID # to check which frames are being preserved clip_sums = [f.sum() for f in clip.iter_frames()] @@ -284,5 +286,6 @@ def test_setfps_withchangeduration(): assert clip2.duration == clip.duration / 2 close_all_clips(locals()) + if __name__ == "__main__": pytest.main() From d746418275b78d2f44e3f665cd6b71a43f83aa13 Mon Sep 17 00:00:00 2001 From: Tom Burrows Date: Sun, 4 Oct 2020 20:24:43 +0100 Subject: [PATCH 5/5] Added changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6efd382c3..e89aa5b86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - New `pix_fmt` parameter in `VideoFileClip`, `VideoClip.write_videofile()`, `VideoClip.write_gif()` that allows passing a custom `pix_fmt` parameter such as `"bgr24"` to FFmpeg [#1237] +- New `change_duration` parameter in `Clip.set_fps()` that allows changing the video speed to match the new fps [#1329] ### Changed - `FFMPEG_AudioReader.close_proc()` -> `FFMPEG_AudioReader.close()` for consistency with `FFMPEG_VideoReader` [#1220]