Skip to content

Commit e555688

Browse files
Preprocessing the frames more faster (GH-62)
2 parents b8a91a0 + 36e8b3b commit e555688

File tree

6 files changed

+40
-40
lines changed

6 files changed

+40
-40
lines changed

src/thumbnails/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from .thumbnail import ThumbnailVTT
2323
from .thumbnail import register_thumbnail
2424

25-
__version__ = "0.1.7"
25+
__version__ = "0.1.8"
2626
__all__ = (
2727
"Generator",
2828
"Thumbnail",

src/thumbnails/frame.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ def __init__(self, size):
1717
self._max_height = math.ceil(self._max_width * self._height / self._width)
1818

1919
# Final size of the frame
20-
self.__width = None
21-
self.__height = None
20+
self._final_width = None
21+
self._final_height = None
2222

2323
@property
2424
def compress(self):
@@ -38,17 +38,17 @@ def columns_count(self):
3838
@property
3939
def width(self):
4040
"""Calculates and caches the frame width."""
41-
if not self.__width:
42-
self.__width = round(self._width * self.compress)
43-
self.__width = max(self.__width, self._min_width)
44-
self.__width = min(self.__width, self._max_width)
45-
return self.__width
41+
if not self._final_width:
42+
self._final_width = round(self._width * self.compress)
43+
self._final_width = max(self._final_width, self._min_width)
44+
self._final_width = min(self._final_width, self._max_width)
45+
return self._final_width
4646

4747
@property
4848
def height(self):
4949
"""Calculates and caches the frame height."""
50-
if not self.__height:
51-
self.__height = round(self._height * self.compress)
52-
self.__height = max(self.__height, self._min_height)
53-
self.__height = min(self.__height, self._max_height)
54-
return self.__height
50+
if not self._final_height:
51+
self._final_height = round(self._height * self.compress)
52+
self._final_height = max(self._final_height, self._min_height)
53+
self._final_height = min(self._final_height, self._max_height)
54+
return self._final_height

src/thumbnails/generator.py

+14-15
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from .constants import DEFAULT_OUTPUT
1212
from .constants import DEFAULT_SKIP
1313
from .pathtools import listdir
14-
from .pathtools import metadata_path
1514
from .progress import use_progress
1615
from .thumbnail import ThumbnailExistsError
1716
from .thumbnail import ThumbnailFactory
@@ -36,6 +35,9 @@ def __init__(self, inputs):
3635
self.compress = DEFAULT_COMPRESS
3736
self.interval = DEFAULT_INTERVAL
3837

38+
# Remove non-video files in case of input directory already contains other generated files.
39+
self.inputs = [file for file in self.inputs if re.match(r"^.*\.(?:(?!png|vtt|json).)+$", file)]
40+
3941
@staticmethod
4042
def worker(video, fmt, base, skip, output):
4143
"""Executes the required workflows for generating a thumbnail."""
@@ -46,21 +48,18 @@ def worker(video, fmt, base, skip, output):
4648
thumbnail.prepare_frames()
4749
thumbnail.generate()
4850

49-
@use_progress
50-
def generate(self):
51-
self.inputs = [file for file in self.inputs if re.match(r"^.*\.(?:(?!png|vtt|json).)+$", file)]
52-
self.inputs = dict(zip(map(lambda i: metadata_path(i, self.output, self.format), self.inputs), self.inputs))
51+
def __iter__(self):
52+
return self
5353

54-
with concurrent.futures.ThreadPoolExecutor() as executor:
55-
videos = executor.map(
56-
functools.partial(
57-
Video,
58-
compress=self.compress,
59-
interval=self.interval,
60-
),
61-
self.inputs.values(),
62-
)
54+
def __next__(self):
55+
"""Returns the next video to be processed."""
56+
try:
57+
return Video(self.inputs.pop(), self.compress, self.interval)
58+
except IndexError:
59+
raise StopIteration
6360

61+
@use_progress
62+
def generate(self):
6463
with concurrent.futures.ThreadPoolExecutor() as executor:
6564
executor.map(
6665
functools.partial(
@@ -70,5 +69,5 @@ def generate(self):
7069
skip=self.skip,
7170
output=self.output,
7271
),
73-
videos,
72+
self,
7473
)

src/thumbnails/progress.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ def use_progress(func):
4646
@functools.wraps(func)
4747
def wrapper(*args, **kwargs):
4848
Progress.start()
49-
func(*args, **kwargs)
50-
Progress.stop()
49+
try:
50+
func(*args, **kwargs)
51+
finally:
52+
Progress.stop()
5153

5254
return wrapper

src/thumbnails/thumbnail.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ def prepare_frames(self):
108108
offset = extract_name(frame).replace("-", ":").split(".")[0]
109109
progress.update("Processing [bold]%s[/bold] frame" % offset)
110110
with Image.open(frame) as image:
111-
image = image.resize((self.width, self.height), Image.ANTIALIAS)
112111
master.paste(image, (x, y))
113112

114113
with Progress("Saving the result at '%s'" % master_path):
@@ -124,9 +123,8 @@ def format_time(secs):
124123
route = os.path.join(prefix, extract_name(self.filepath) + ".png")
125124
route = pathlib.Path(route).as_posix()
126125

127-
with Progress("Saving thumbnail metadata at '%s'" % self.metadata_path) as progress:
126+
with Progress("Saving thumbnail metadata at '%s'" % self.metadata_path):
128127
for _, start, end, x, y in self.thumbnails():
129-
progress.update("Generating metadata for '%s'" % route)
130128
thumbnail_data = "%s --> %s\n%s#xywh=%d,%d,%d,%d\n\n" % (
131129
format_time(start), format_time(end),
132130
route, x, y, self.width, self.height,
@@ -148,17 +146,17 @@ def calc_thumbnail_dir(self):
148146
return ensure_tree(os.path.join(basedir, extract_name(self.filepath)), True)
149147

150148
def prepare_frames(self):
151-
if os.path.exists(self.thumbnail_dir):
152-
remove_tree(self.thumbnail_dir)
153-
copy_tree(self.tempdir.name, self.thumbnail_dir)
149+
with Progress("Copying the frames to the output directory"):
150+
if os.path.exists(self.thumbnail_dir):
151+
remove_tree(self.thumbnail_dir)
152+
copy_tree(self.tempdir.name, self.thumbnail_dir)
154153

155154
def generate(self):
156155
metadata = {}
157156

158-
for frame, start, *_ in self.thumbnails():
159-
frame = os.path.join(self.thumbnail_dir, os.path.basename(frame))
160-
with Image.open(frame) as image:
161-
image.resize((self.width, self.height), Image.ANTIALIAS).save(frame)
157+
with Progress("Saving thumbnail metadata at '%s'" % self.metadata_path):
158+
for frame, start, *_ in self.thumbnails():
159+
frame = os.path.join(self.thumbnail_dir, os.path.basename(frame))
162160
base = os.path.join(self.base, os.path.basename(self.thumbnail_dir))
163161
prefix = base if self.base else os.path.relpath(self.thumbnail_dir)
164162
route = os.path.join(prefix, os.path.basename(frame))

src/thumbnails/video.py

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ def _extract_frame(self, start_time):
9292
"-i", self.filepath,
9393
"-loglevel", "error",
9494
"-vframes", "1",
95+
"-vf", "scale=%d:%d" % (self.width, self.height),
9596
output,
9697
"-y",
9798
)

0 commit comments

Comments
 (0)