Skip to content

Commit

Permalink
Fix to support changes in ffmpeg >= 7
Browse files Browse the repository at this point in the history
  • Loading branch information
osaajani committed Jan 22, 2025
1 parent da7d9f7 commit f12ee5a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 16 deletions.
17 changes: 14 additions & 3 deletions moviepy/video/io/ffmpeg_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def parse(self):
self.result["duration"] = self.parse_duration(line)

# parse global bitrate (in kb/s)
bitrate_match = re.search(r"bitrate: (\d+) kb/s", line)
bitrate_match = re.search(r"bitrate: (\d+) k(i?)b/s", line)
self.result["bitrate"] = (
int(bitrate_match.group(1)) if bitrate_match else None
)
Expand Down Expand Up @@ -528,8 +528,11 @@ def parse(self):

if self._current_stream["stream_type"] == "video":
field, value = self.video_metadata_type_casting(field, value)
# ffmpeg 7 now use displaymatrix instead of rotate
if field == "rotate":
self.result["video_rotation"] = value
elif field == "displaymatrix":
self.result["video_rotation"] = value

# multiline metadata value parsing
if field == "":
Expand Down Expand Up @@ -644,7 +647,7 @@ def parse_audio_stream_data(self, line):
# AttributeError: 'NoneType' object has no attribute 'group'
# ValueError: invalid literal for int() with base 10: '<string>'
stream_data["fps"] = "unknown"
match_audio_bitrate = re.search(r"(\d+) kb/s", line)
match_audio_bitrate = re.search(r"(\d+) k(i?)b/s", line)
stream_data["bitrate"] = (
int(match_audio_bitrate.group(1)) if match_audio_bitrate else None
)
Expand Down Expand Up @@ -672,7 +675,7 @@ def parse_video_stream_data(self, line):
% (self.filename, self.infos)
)

match_bitrate = re.search(r"(\d+) kb/s", line)
match_bitrate = re.search(r"(\d+) k(i?)b/s", line)
stream_data["bitrate"] = int(match_bitrate.group(1)) if match_bitrate else None

# Get the frame rate. Sometimes it's 'tbr', sometimes 'fps', sometimes
Expand Down Expand Up @@ -785,6 +788,14 @@ def video_metadata_type_casting(self, field, value):
"""Cast needed video metadata fields to other types than the default str."""
if field == "rotate":
return (field, float(value))

elif field == "displaymatrix":
match = re.search(r"[-+]?\d+(\.\d+)?", value)
if match:
# We must multiply by -1 because displaymatrix return info
# about how to rotate to show video, not about video rotation
return (field, float(match.group()) * -1)

return (field, value)


Expand Down
2 changes: 2 additions & 0 deletions tests/test_PR.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def test_PR_528(util):


def test_PR_529():
#print(ffmpeg_tools.ffplay_version())
print(ffmpeg_tools.ffmpeg_version())
with VideoFileClip("media/fire2.mp4") as video_clip:
assert video_clip.rotation == 180

Expand Down
10 changes: 9 additions & 1 deletion tests/test_ffmpeg_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
FFmpegInfosParser,
ffmpeg_parse_infos,
)
from moviepy.video.io.ffmpeg_tools import (
ffmpeg_version,
)
from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.video.VideoClip import BitmapClip, ColorClip

Expand Down Expand Up @@ -59,7 +62,7 @@ def test_ffmpeg_parse_infos_video_nframes():
("decode_file", "expected_duration"),
(
(False, 30),
(True, 30.02),
(True, 30),
),
ids=(
"decode_file=False",
Expand All @@ -69,6 +72,11 @@ def test_ffmpeg_parse_infos_video_nframes():
def test_ffmpeg_parse_infos_decode_file(decode_file, expected_duration):
"""Test `decode_file` argument of `ffmpeg_parse_infos` function."""
d = ffmpeg_parse_infos("media/big_buck_bunny_0_30.webm", decode_file=decode_file)

# On old version of ffmpeg, duration and video duration was different
if int(ffmpeg_version()[1].split('.')[0]) < 7:
expected_duration += 0.02

assert d["duration"] == expected_duration

# check metadata is fine
Expand Down
27 changes: 15 additions & 12 deletions tests/test_ffmpeg_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ffmpeg_extract_subclip,
ffmpeg_resize,
ffmpeg_stabilize_video,
ffmpeg_version
)
from moviepy.video.io.VideoFileClip import VideoFileClip

Expand Down Expand Up @@ -57,9 +58,10 @@ def test_ffmpeg_resize(util):
ffmpeg_resize("media/bitmap.mp4", outputfile, expected_size, logger=None)
assert os.path.isfile(outputfile)

# overwrite file
with pytest.raises(OSError):
ffmpeg_resize("media/bitmap.mp4", outputfile, expected_size, logger=None)
# overwrite file on old version of ffmpeg
if int(ffmpeg_version()[1].split('.')[0]) < 7:
with pytest.raises(OSError):
ffmpeg_resize("media/bitmap.mp4", outputfile, expected_size, logger=None)

clip = VideoFileClip(outputfile)
assert clip.size[0] == expected_size[0]
Expand Down Expand Up @@ -98,15 +100,16 @@ def test_ffmpeg_stabilize_video(util):
expected_filepath = os.path.join(stabilize_video_tempdir, "foo.mp4")
assert os.path.isfile(expected_filepath)

# don't overwrite file
with pytest.raises(OSError):
ffmpeg_stabilize_video(
"media/bitmap.mp4",
output_dir=stabilize_video_tempdir,
outputfile="foo.mp4",
overwrite_file=False,
logger=None,
)
# don't overwrite file on old version of ffmpeg
if int(ffmpeg_version()[1].split('.')[0]) < 7:
with pytest.raises(OSError):
ffmpeg_stabilize_video(
"media/bitmap.mp4",
output_dir=stabilize_video_tempdir,
outputfile="foo.mp4",
overwrite_file=False,
logger=None,
)

if os.path.isdir(stabilize_video_tempdir):
try:
Expand Down

0 comments on commit f12ee5a

Please sign in to comment.