diff --git a/CHANGELOG.md b/CHANGELOG.md index f33a81708..93b4126dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed `clip.preview()` crashing at exit when running inside Jupyter Notebook in Windows [\#1537](https://github.com/Zulko/moviepy/pull/1537) - Fixed rotate FX not being applied to mask images [\#1399](https://github.com/Zulko/moviepy/pull/1399) - Fixed opacity error blitting VideoClips [\#1552](https://github.com/Zulko/moviepy/pull/1552) +- Fixed rotation metadata of input not being taken into account rendering VideoClips [\#577](https://github.com/Zulko/moviepy/pull/577) ## [v2.0.0.dev2](https://github.com/zulko/moviepy/tree/v2.0.0.dev2) (2020-10-05) diff --git a/media/rotated-90-degrees.mp4 b/media/rotated-90-degrees.mp4 new file mode 100644 index 000000000..585c4d8f2 Binary files /dev/null and b/media/rotated-90-degrees.mp4 differ diff --git a/moviepy/video/io/ffmpeg_reader.py b/moviepy/video/io/ffmpeg_reader.py index 45d97aa66..ab2c9037a 100644 --- a/moviepy/video/io/ffmpeg_reader.py +++ b/moviepy/video/io/ffmpeg_reader.py @@ -37,7 +37,12 @@ def __init__( ) self.fps = infos["video_fps"] self.size = infos["video_size"] - self.rotation = infos.get("video_rotation", 0) + + # ffmpeg automatically rotates videos if rotation information is + # available, so exchange width and height + self.rotation = abs(infos.get("video_rotation", 0)) + if self.rotation in [90, 270]: + self.size = [self.size[1], self.size[0]] if target_resolution: if None in target_resolution: diff --git a/tests/test_ffmpeg_reader.py b/tests/test_ffmpeg_reader.py index c69c3f329..9c866f3ee 100644 --- a/tests/test_ffmpeg_reader.py +++ b/tests/test_ffmpeg_reader.py @@ -14,6 +14,7 @@ FFmpegInfosParser, ffmpeg_parse_infos, ) +from moviepy.video.io.VideoFileClip import VideoFileClip from moviepy.video.VideoClip import BitmapClip from tests.test_helper import TMP_DIR @@ -299,6 +300,27 @@ def test_ffmpeg_parse_infos_metadata_with_attached_pic(): assert len(d["metadata"].keys()) == 7 +def test_ffmpeg_parse_video_rotation(): + d = ffmpeg_parse_infos("media/rotated-90-degrees.mp4") + assert d["video_rotation"] == 90 + assert d["video_size"] == [1920, 1080] + + +def test_correct_video_rotation(): + """See https://github.com/Zulko/moviepy/pull/577""" + clip = VideoFileClip("media/rotated-90-degrees.mp4").subclip(0.2, 0.4) + + corrected_rotation_filename = os.path.join( + TMP_DIR, + "correct_video_rotation.mp4", + ) + clip.write_videofile(corrected_rotation_filename) + + d = ffmpeg_parse_infos(corrected_rotation_filename) + assert "video_rotation" not in d + assert d["video_size"] == [1080, 1920] + + def test_ffmpeg_parse_infos_multiline_metadata(): """Check that the parser can parse multiline metadata values.""" infos = """Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/110_PREV_FINAL.mov':