|
| 1 | +import asyncio |
| 2 | +import concurrent.futures |
| 3 | +import math |
| 4 | + |
| 5 | +from PIL import Image |
| 6 | + |
| 7 | +from ffmpeg import Ffmpeg |
| 8 | + |
| 9 | +width, height = 300, 200 |
| 10 | +interval = 20 |
| 11 | +columns = 3 |
| 12 | + |
| 13 | +files = ["valerian-1080p.avi", "valerian-1080p.mkv", "valerian-1080p.mov", "valerian-1080p.mp4", |
| 14 | + "valerian-1080p.webm", "valerian-1080p.wmv", "valerian-1080p.mpeg", "valerian-1080p.mpg"] |
| 15 | + |
| 16 | + |
| 17 | +def worker(video): |
| 18 | + line, column = 0, 0 |
| 19 | + frames_count = len(range(0, int(video.duration), interval)) |
| 20 | + master_width = width * columns |
| 21 | + master_height = height * int(math.ceil(float(frames_count) / columns)) |
| 22 | + |
| 23 | + try: |
| 24 | + master = Image.new(mode="RGBA", size=(master_width, master_height)) |
| 25 | + except IOError: |
| 26 | + master = Image.new(mode="RGB", size=(master_width, master_height)) |
| 27 | + |
| 28 | + for moment in range(0, int(video.duration), interval): |
| 29 | + x, y = width * column, height * line |
| 30 | + image = video.get_frame_buffer(moment) |
| 31 | + image = image.resize((width, height), Image.ANTIALIAS) |
| 32 | + master.paste(image, (x, y)) |
| 33 | + |
| 34 | + column += 1 |
| 35 | + |
| 36 | + if column == columns: |
| 37 | + line += 1 |
| 38 | + column = 0 |
| 39 | + |
| 40 | + master.save(video.filename + ".png") |
| 41 | + |
| 42 | + |
| 43 | +async def main(): |
| 44 | + fps = [Ffmpeg(fp) for fp in files] |
| 45 | + |
| 46 | + with concurrent.futures.ThreadPoolExecutor() as executor: |
| 47 | + executor.map(worker, fps) |
| 48 | + |
| 49 | + for fp in fps: |
| 50 | + fp.close() |
| 51 | + |
| 52 | + |
| 53 | +loop = asyncio.get_event_loop() |
| 54 | +loop.run_until_complete(main()) |
| 55 | +loop.close() |
0 commit comments