Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import io
2import time
3import threading
4from logging import getLogger
5from PIL import Image
8class screencast(threading.Thread):
9 def __init__(self, drvobj, crop, interval=1.0, thumbnail=None):
10 super().__init__()
11 self.drvobj = drvobj
12 if crop is None:
13 self.crop = crop
14 else:
15 self.crop = tuple(crop)
16 self.thumbnail = thumbnail
17 self.log = getLogger(self.name)
18 self.stop = False
19 self.interval = interval
20 self.frames = []
22 def run(self):
23 self.start_ts = time.time()
24 while not self.stop:
25 t1 = time.time()
26 with self.drvobj.lock:
27 p = self.drvobj.saveshot()
28 self.log.info("shot: %d bytes, %f sec", len(p), time.time() - t1)
29 if len(p) != 0:
30 img = Image.open(io.BytesIO(p))
31 if self.crop is not None:
32 self.log.info("crop %s, %f sec", self.crop, time.time() - t1)
33 img = img.crop(self.crop)
34 if self.thumbnail is not None:
35 img.thumbnail(self.thumbnail, Image.ANTIALIAS)
36 self.frames.append(img)
37 td = time.time() - t1
38 if self.interval is not None and self.interval > td:
39 self.log.info("sleep %f - %f", self.interval, td)
40 time.sleep(self.interval - td)
41 self.finished_ts = time.time()
43 def savefile(self, output_fn, optimize=False, loop=0, speed=1.0):
44 if len(self.frames) == 0:
45 raise Exception("no image found")
46 d = 1000 * (self.finished_ts - self.start_ts) / len(self.frames) / speed
47 self.log.info("%d frames, %d sec. duration=%f(ms)", len(
48 self.frames), self.finished_ts - self.start_ts, d)
49 self.frames[0].save(output_fn, save_all=True, duration=d, optimize=optimize,
50 loop=loop, append_images=self.frames[1:])
53scr_th = None
56def Base_screencast(self, param):
57 """
58 - name: start screencast
59 screencast:
60 interval: 0.5
61 thumbnail: [100, 100]
62 - name: sleep
63 sleep: 3
64 - name: save screencast
65 screencast: output.gif
66 """
67 global scr_th
68 if isinstance(param, dict) and "output" not in param:
69 if scr_th is not None:
70 raise Exception("screencast already working")
71 scr_th = screencast(self, param.get("crop"), param.get("interval"),
72 param.get("thumbnail"))
73 scr_th.start()
74 return "started"
75 if scr_th is None:
76 raise Exception("screencast is not working")
77 self.log.debug("stop cast")
78 scr_th.stop = True
79 scr_th.join(2)
80 if scr_th.is_alive():
81 self.log.warn("cannot stop screencast thread.")
82 else:
83 self.log.debug("done join. saving")
84 if isinstance(param, str):
85 self.log.info("save to %s", param)
86 scr_th.savefile(param)
87 elif isinstance(param, dict):
88 output = param.get("output")
89 assert output is not None
90 self.log.info("save to %s", output)
91 scr_th.savefile(output,
92 optimize=param.get("optimize", False),
93 loop=param.get("loop", 0),
94 speed=param.get("speed", 1.0))
95 scr_th = None
96 return "finished"