sticker-convert 2.8.10__py3-none-any.whl → 2.8.11__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -430,19 +430,37 @@ class StickerConvert:
430
430
  and im.n_frames != 0
431
431
  and self.codec_info_orig.fps != 0.0
432
432
  ):
433
+ # Pillow is not reliable for getting webp frame durations
434
+ durations: Optional[List[int]]
435
+ if im.format == "WEBP":
436
+ _, _, _, durations = CodecInfo._get_file_fps_frames_duration_webp(
437
+ self.in_f
438
+ )
439
+ else:
440
+ durations = None
441
+
433
442
  duration_ptr = 0.0
434
443
  duration_inc = 1 / self.codec_info_orig.fps * 1000
435
- next_frame_start_duration = im.info.get("duration", 1000)
436
444
  frame = 0
445
+ if durations is None:
446
+ next_frame_start_duration = cast(int, im.info.get("duration", 1000))
447
+ else:
448
+ next_frame_start_duration = durations[0]
437
449
  while True:
438
450
  self.frames_raw.append(np.asarray(im.convert("RGBA")))
439
451
  duration_ptr += duration_inc
440
452
  if duration_ptr >= next_frame_start_duration:
453
+ frame += 1
441
454
  if frame == im.n_frames:
442
455
  break
443
456
  im.seek(frame)
444
- next_frame_start_duration += im.info.get("duration", 1000)
445
- frame += 1
457
+
458
+ if durations is None:
459
+ next_frame_start_duration += cast(
460
+ int, im.info.get("duration", 1000)
461
+ )
462
+ else:
463
+ next_frame_start_duration += durations[frame]
446
464
  else:
447
465
  self.frames_raw.append(np.asarray(im.convert("RGBA")))
448
466
 
@@ -725,11 +743,11 @@ class StickerConvert:
725
743
  if self.out_f.suffix in (".apng", ".png"):
726
744
  codec = "apng"
727
745
  pixel_format = "rgba"
728
- options_container["plays"] = "0"
746
+ options_stream["plays"] = "0"
729
747
  elif self.out_f.suffix in (".webm", ".mkv"):
730
748
  codec = "libvpx-vp9"
731
749
  pixel_format = "yuva420p"
732
- options_container["loop"] = "0"
750
+ options_stream["loop"] = "0"
733
751
  elif self.out_f.suffix == ".webp":
734
752
  codec = "webp"
735
753
  pixel_format = "yuva420p"
@@ -737,7 +755,7 @@ class StickerConvert:
737
755
  else:
738
756
  codec = "libvpx-vp9"
739
757
  pixel_format = "yuv420p"
740
- options_container["loop"] = "0"
758
+ options_stream["loop"] = "0"
741
759
 
742
760
  with av.open(
743
761
  self.tmp_f,
@@ -80,9 +80,9 @@ class CodecInfo:
80
80
  @staticmethod
81
81
  def get_file_fps_frames_duration(
82
82
  file: Union[Path, bytes], file_ext: Optional[str] = None
83
- ) -> Tuple[float, int, float]:
83
+ ) -> Tuple[float, int, int]:
84
84
  fps: float
85
- duration: float
85
+ duration: int
86
86
 
87
87
  if not file_ext and isinstance(file, Path):
88
88
  file_ext = CodecInfo.get_file_ext(file)
@@ -94,7 +94,9 @@ class CodecInfo:
94
94
  else:
95
95
  duration = 0
96
96
  elif file_ext == ".webp":
97
- fps, frames, duration = CodecInfo._get_file_fps_frames_duration_webp(file)
97
+ fps, frames, duration, _ = CodecInfo._get_file_fps_frames_duration_webp(
98
+ file
99
+ )
98
100
  elif file_ext in (".gif", ".apng", ".png"):
99
101
  fps, frames, duration = CodecInfo._get_file_fps_frames_duration_pillow(file)
100
102
  else:
@@ -115,7 +117,7 @@ class CodecInfo:
115
117
  if file_ext == ".tgs":
116
118
  return CodecInfo._get_file_fps_tgs(file)
117
119
  elif file_ext == ".webp":
118
- fps, _, _ = CodecInfo._get_file_fps_frames_duration_webp(file)
120
+ fps, _, _, _ = CodecInfo._get_file_fps_frames_duration_webp(file)
119
121
  return fps
120
122
  elif file_ext in (".gif", ".apng", ".png"):
121
123
  fps, _, _ = CodecInfo._get_file_fps_frames_duration_pillow(file)
@@ -159,8 +161,8 @@ class CodecInfo:
159
161
  @staticmethod
160
162
  def get_file_duration(
161
163
  file: Union[Path, bytes], file_ext: Optional[str] = None
162
- ) -> float:
163
- duration: float
164
+ ) -> int:
165
+ duration: int
164
166
 
165
167
  # Return duration in miliseconds
166
168
  if not file_ext and isinstance(file, Path):
@@ -173,7 +175,7 @@ class CodecInfo:
173
175
  else:
174
176
  duration = 0
175
177
  elif file_ext == ".webp":
176
- _, _, duration = CodecInfo._get_file_fps_frames_duration_webp(file)
178
+ _, _, duration, _ = CodecInfo._get_file_fps_frames_duration_webp(file)
177
179
  elif file_ext in (".gif", ".png", ".apng"):
178
180
  _, _, duration = CodecInfo._get_file_fps_frames_duration_pillow(file)
179
181
  else:
@@ -233,9 +235,9 @@ class CodecInfo:
233
235
  @staticmethod
234
236
  def _get_file_fps_frames_duration_pillow(
235
237
  file: Union[Path, bytes], frames_only: bool = False
236
- ) -> Tuple[float, int, float]:
237
- total_duration = 0.0
238
- durations: List[float] = []
238
+ ) -> Tuple[float, int, int]:
239
+ total_duration = 0
240
+ durations: List[int] = []
239
241
 
240
242
  with Image.open(file) as im:
241
243
  if "n_frames" in dir(im):
@@ -244,7 +246,7 @@ class CodecInfo:
244
246
  return 0.0, frames, 1
245
247
  for i in range(im.n_frames):
246
248
  im.seek(i)
247
- frame_duration = cast(float, im.info.get("duration", 1000))
249
+ frame_duration = cast(int, im.info.get("duration", 1000))
248
250
  if frame_duration not in durations and frame_duration != 0:
249
251
  durations.append(frame_duration)
250
252
  total_duration += frame_duration
@@ -255,7 +257,7 @@ class CodecInfo:
255
257
  else:
256
258
  duration_gcd = durations_gcd(*durations)
257
259
  frames_apparent = total_duration / duration_gcd
258
- fps = frames_apparent / total_duration * 1000
260
+ fps = float(frames_apparent / total_duration * 1000)
259
261
  return fps, frames, total_duration
260
262
 
261
263
  return 0.0, 1, 0
@@ -263,10 +265,11 @@ class CodecInfo:
263
265
  @staticmethod
264
266
  def _get_file_fps_frames_duration_webp(
265
267
  file: Union[Path, bytes],
266
- ) -> Tuple[float, int, int]:
268
+ ) -> Tuple[float, int, int, List[int]]:
267
269
  total_duration = 0
268
270
  frames = 0
269
271
  durations: List[int] = []
272
+ durations_unique: List[int] = []
270
273
 
271
274
  def _open_f(file: Union[Path, bytes]) -> BinaryIO:
272
275
  if isinstance(file, Path):
@@ -285,22 +288,23 @@ class CodecInfo:
285
288
  int(frame_duration_32[-1]) & 0b11111100
286
289
  )
287
290
  frame_duration = int.from_bytes(frame_duration_bytes, "little")
288
- if frame_duration not in durations and frame_duration != 0:
289
- durations.append(frame_duration)
291
+ if frame_duration not in durations_unique and frame_duration != 0:
292
+ durations_unique.append(frame_duration)
293
+ durations.append(frame_duration)
290
294
  total_duration += frame_duration
291
295
  frames += 1
292
296
 
293
297
  if frames <= 1:
294
- return 0.0, 1, 0
298
+ return 0.0, 1, 0, durations
295
299
 
296
- if len(durations) == 1:
300
+ if len(durations_unique) == 1:
297
301
  fps = frames / total_duration * 1000
298
302
  else:
299
- duration_gcd = durations_gcd(*durations)
303
+ duration_gcd = durations_gcd(*durations_unique)
300
304
  frames_apparent = total_duration / duration_gcd
301
305
  fps = float(frames_apparent / total_duration * 1000)
302
306
 
303
- return fps, frames, total_duration
307
+ return fps, frames, total_duration, durations
304
308
 
305
309
  @staticmethod
306
310
  def _get_file_frames_duration_av(
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
- __version__ = "2.8.10"
3
+ __version__ = "2.8.11"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sticker-convert
3
- Version: 2.8.10
3
+ Version: 2.8.11
4
4
  Summary: Convert (animated) stickers to/from WhatsApp, Telegram, Signal, Line, Kakao, Viber, iMessage. Written in Python.
5
5
  Author-email: laggykiller <chaudominic2@gmail.com>
6
6
  Maintainer-email: laggykiller <chaudominic2@gmail.com>
@@ -1,12 +1,12 @@
1
1
  sticker_convert/__init__.py,sha256=iQnv6UOOA69c3soAn7ZOnAIubTIQSUxtq1Uhh8xRWvU,102
2
2
  sticker_convert/__main__.py,sha256=6RJauR-SCSSTT3TU7FFB6B6PVwsCxO2xZXtmZ3jc2Is,463
3
3
  sticker_convert/cli.py,sha256=DUPaI0Vw-a63TxxC2SSskLd1PlAuQtFOklggMo04IJc,18854
4
- sticker_convert/converter.py,sha256=hXJ1bS2e1DNShGOVbic0rvbW9WWdI9xFs2LfQY0F5ck,35142
4
+ sticker_convert/converter.py,sha256=XMiYzIzlcdvx_AFyyk7j-Zdyj3ablLFJFUZ6tjrlGIs,35861
5
5
  sticker_convert/definitions.py,sha256=ZhP2ALCEud-w9ZZD4c3TDG9eHGPZyaAL7zPUsJAbjtE,2073
6
6
  sticker_convert/gui.py,sha256=TRPGwMhSMPHnZppHmw2OWHKTJtGoeLpGWD0eRYi4_yk,30707
7
7
  sticker_convert/job.py,sha256=vKv1--y4MVmZV_IBpUhEfNEiUeEqrTR1umzlALPXKdw,25775
8
8
  sticker_convert/job_option.py,sha256=JHAFCxp7-dDwD-1PbpYLAFRF3OoJu8cj_BjOm5r8Gp8,7732
9
- sticker_convert/version.py,sha256=UtJ9dsXpGqw7NMojAfGIj-YUjczQKkZ2Tj8O0zGVRM4,47
9
+ sticker_convert/version.py,sha256=oxsRvN-1re7LUAQn0GzovVDlajKtGywZotOzD3vzeIE,47
10
10
  sticker_convert/downloaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  sticker_convert/downloaders/download_base.py,sha256=x18bI2mPpbXRnSmStBHEb1IvN-VPCilOHLQUs6YPUEU,4041
12
12
  sticker_convert/downloaders/download_kakao.py,sha256=UFp7EpMea62fIePY5DfhH4jThAwdeazfoC5iW1g4dAo,8516
@@ -90,12 +90,12 @@ sticker_convert/utils/files/metadata_handler.py,sha256=UVKpwflsXwiVh-F-HNr0Ucrix
90
90
  sticker_convert/utils/files/run_bin.py,sha256=QalA9je6liHxiOtxsjsFsIkc2t59quhcJCVpP1X3p50,1743
91
91
  sticker_convert/utils/files/sanitize_filename.py,sha256=HBklPGsHRJjFQUIC5rYTQsUrsuTtezZXIEA8CPhLP8A,2156
92
92
  sticker_convert/utils/media/apple_png_normalize.py,sha256=LbrQhc7LlYX4I9ek4XJsZE4l0MygBA1jB-PFiYLEkzk,3657
93
- sticker_convert/utils/media/codec_info.py,sha256=SJSFvQzXHnGkj7MH9xJ5xiC4cqiOjFKckFKE_FICdT4,15562
93
+ sticker_convert/utils/media/codec_info.py,sha256=1QfW3wgZ5vOk7T4XtLHYvJK1x8RbASRPSvhKEPkcu9A,15747
94
94
  sticker_convert/utils/media/decrypt_kakao.py,sha256=4wq9ZDRnFkx1WmFZnyEogBofiLGsWQM_X69HlA36578,1947
95
95
  sticker_convert/utils/media/format_verify.py,sha256=Xf94jyqk_6M9IlFGMy0wYIgQKn_yg00nD4XW0CgAbew,5732
96
- sticker_convert-2.8.10.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
97
- sticker_convert-2.8.10.dist-info/METADATA,sha256=wH0_wi0emJzWMyoaa2SkkpCUnN_VIQ6gvQu0Pp4XpF0,50376
98
- sticker_convert-2.8.10.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
99
- sticker_convert-2.8.10.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
100
- sticker_convert-2.8.10.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
101
- sticker_convert-2.8.10.dist-info/RECORD,,
96
+ sticker_convert-2.8.11.dist-info/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
97
+ sticker_convert-2.8.11.dist-info/METADATA,sha256=yeRKxmheS7CvSGvQIwZ8-uqxUs7NAL6Ammf3KKBQCYo,50376
98
+ sticker_convert-2.8.11.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
99
+ sticker_convert-2.8.11.dist-info/entry_points.txt,sha256=MNJ7XyC--ugxi5jS1nzjDLGnxCyLuaGdsVLnJhDHCqs,66
100
+ sticker_convert-2.8.11.dist-info/top_level.txt,sha256=r9vfnB0l1ZnH5pTH5RvkobnK3Ow9m0RsncaOMAtiAtk,16
101
+ sticker_convert-2.8.11.dist-info/RECORD,,