Skip to content

Commit

Permalink
Calculate fps based on all frames duration instead of first frame
Browse files Browse the repository at this point in the history
  • Loading branch information
laggykiller committed Dec 17, 2023
1 parent 21b0327 commit 7991278
Showing 1 changed file with 29 additions and 14 deletions.
43 changes: 29 additions & 14 deletions src/sticker_convert/utils/media/codec_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,37 @@ def get_file_fps(file: str) -> float:
fps = anim.lottie_animation_get_framerate()
else:
if file_ext == ".webp":
total_duration = 0
frames = 0

with open(file, "r+b") as f:
mm = mmap.mmap(f.fileno(), 0)
anmf_pos = mm.find(b"ANMF")
if anmf_pos == -1:
return 1
mm.seek(anmf_pos + 20)
frame_duration_32 = mm.read(4)
frame_duration = frame_duration_32[:-1] + bytes(
int(frame_duration_32[-1]) & 0b11111100
)
fps = 1000 / int.from_bytes(frame_duration, "little")
while True:
anmf_pos = mm.find(b"ANMF")
if anmf_pos == -1:
break
mm.seek(anmf_pos + 20)
frame_duration_32 = mm.read(4)
frame_duration = frame_duration_32[:-1] + bytes(
int(frame_duration_32[-1]) & 0b11111100
)
total_duration += int.from_bytes(frame_duration, "little")
frames += 1

if frames == 0:
fps = 1
else:
fps = frames / total_duration * 1000
elif file_ext in (".gif", ".apng", ".png"):
metadata = iio.immeta(
file, index=0, plugin="pillow", exclude_applied=False
)
fps = int(1000 / metadata.get("duration", 1000))
total_duration = 0
frames = len([* iio.imiter(file, plugin="pillow")])

for frame in range(frames):
metadata = iio.immeta(
file, index=frame, plugin="pillow", exclude_applied=False
)
total_duration += metadata.get("duration", 1000)
fps = frames / total_duration * 1000
else:
metadata = iio.immeta(file, plugin="pyav", exclude_applied=False)
fps = metadata.get("fps", 1)
Expand Down Expand Up @@ -95,7 +110,7 @@ def get_file_frames(file: str) -> int:
if file_ext == ".webp":
frames = Image.open(file).n_frames
else:
frames = len(iio.imread(file, plugin="pyav"))
frames = frames = len([* iio.imiter(file, plugin="pyav")])

return frames

Expand Down

0 comments on commit 7991278

Please sign in to comment.