resources/archive/shot_saver.py

This module provides a high-level interface for saving screenshots asynchronously in the form of the ShotSaver class.

Class arguments

  • pool_size (int, optional): Maximum number of simultaneously saved screenshots. 10 by default.
  • callback (callable[str, str], optional)Callback function that is called after the screenshots are saved. The guid of the task to save and the current status of the task are passed to this function.

Class public attributes

  • timeout_sec (int): Screenshot waiting time, sec. 10 by default.
  • buffer_ts(int): Waiting time for creating a screenshot with figures. 0 by default.
  • max_tries (int): Number of attempts to save a screenshot. 2 by default.
  • callback (callable[str, str]): Same as the callback argument.
  • pool_size (int): Same as the pool_size argument.
  • screenshots_folder (str): Screenshots folder by default, if no other is specified when calling the method. Server screenshot folder by default.

Class methods

  • save - Saves a screenshot to a file. Returns task's guid and a path, where the screenshot will be saved.
    Method's arguments:
    • channel_full_guid (str): Channel guid in a form of ChannelGuid_ServerGuid .
    • dt (datetime.datetime, optional): Date and time of a screenshot saving. Current date and time by default.
    • figures (bool, optional): If True - saves a screenshot with figures. False by default.
    • file_name (str, optional): Screenshot name. By default, it is generated according to the template  {channel.name} (%Y.%m.%d %H-%M-%S.%f).jpg
      In the screenshot name, date and time formatting is supported (available arguments are at https://strftime.org/) as well as channel and server objects.
    • file_path (str, optional): Full name for screenshot saving. By default, screenshot will be saved in the directory, defined in screenshots_folder attribute.
    • callback (callable[str, str], optional)Callback function that is called after screenshots are saved. The guid of the task to save and the current status of the task are passed to this function. If not defined - callback of class is used.
    • task_guid (str, optional): Task's guid. host.random_guid() function define it by default.
  • get - Returns image in callback, bytes
    Method arguments:
    • channel_full_guid (str): Channel guid in a form of ChannelGuid_ServerGuid .
    • dt (datetime.datetime, optional): Date and time of a screenshot saving. Current date and time by default.
    • figures (bool, optional): If True - saves a screenshot with figures. False by default.
    • callback (callable[str, str])Callback function that is called after screenshots are saved. The guid of the task to save and the current status of the task are passed to this function. If not defined - callback of class is used. Raises EnvironmentError if callback of class is also not defined.

Possible states of screenshot saving are contained in the status object:

  • status.saving - Screenshot is being saved.
  • status.error - Error of screenshot saving.
  • status.success - Screenshot is successfully saved.
  • status.in_queue - Screenshot is added to a saving queue.


During the initialization, the ShotSaver class creates a thread pool from several separate threads (worker), the number of threads is equal to the pool_size parameter.

Saving screenshots in thread pool is necessary to limit the number of screenshots requested at the same time, for a large number of requests of the host.screenshot_v2 or host.screenshot_v2_figures method can lead to the Trassir crash.

Each call of the save method adds a save task to the task queue. Which later pick up the workers in turn. Also status.in_queue is passed to the callback.

Worker calls the host.screenshot_v2 or host.screenshot_v2_figures method depending on the figures parameter and passes status.saving to the callback. Then it waits for the file to appear in the specified folder during the time specified in the timeout_sec parameter.

If the screenshot does not appear within the specified time in the folder and max_tries > 1, then the worker will call the method for saving the screenshot again. Then the logic of waiting and re-saving is repeated as many times as specified in the max_tries parameter.

If the screenshot has been successfully saved, then status.success is passed to the callback.

If the screenshot does not appear in the folder after all attempts, status.error is passed to the callback.

The get method works the same way as the save method, except that after successfully saving the screenshot, it gets the image and passes the result to the callback, after which it deletes the screenshot file.

Code examples

Simple example

Saving the current screenshot from the channel with a standard name to the screenshots folder.

from shot_saver import ShotSaver

CHANNEL_GUID = "uR76TlcA_O4Yazs8u"  # Must be replaced with the guid of your channel

ss = ShotSaver()

ss.save(CHANNEL_GUID)
Changing the folder of screenshots saving

If you want all screenshots of this script to be saved in a separate folder, you can change it globally for the entire class.

from shot_saver import ShotSaver

CHANNEL_GUID = "uR76TlcA_O4Yazs8u"  # Must be replaced with the guid of your channel 

ss = ShotSaver()
ss.screenshots_folder = r"D:\DSSL\shots"

ss.save(CHANNEL_GUID)

Or assign directly when saving a screenshot

from shot_saver import ShotSaver

CHANNEL_GUID = "uR76TlcA_O4Yazs8u"  # Must be replaced with the guid of your channel 

ss = ShotSaver()

ss.save(CHANNEL_GUID, file_path=r"D:\DSSL\shots")
Screenshot request for a specific date / time

We can also change the name of the screenshot, and / or add the date / time for which we want to save the screenshot.
For example, let's save a screenshot for the current date, and change the time to 00:00:00 .

import datetime
from shot_saver import ShotSaver

CHANNEL_GUID = "uR76TlcA_O4Yazs8u"  # Must be replaced with the guid of your channel 

ss = ShotSaver()

dt = datetime.datetime.combine(
    datetime.datetime.now().date(),  # Current date
    datetime.time()  # Время 00:00:00
)
ss.save(CHANNEL_GUID, dt=dt, file_name="midnight_shot.jpg")
Tracking of the screenshot saving status

Upon successful saving, the resulting image is opened.
We use the tasks variable to store the current tasks and the paths for the screenshot saves for each task.

import os
import host
from shot_saver import ShotSaver, status

CHANNEL_GUID = "uR76TlcA_O4Yazs8u"

ss = ShotSaver()

tasks = {}


def callback(guid, state):
    host.message("[%s] %s" % (guid, state))  # Displaying the current task status
    if state == status.success:
        # Opening the image if the screenshot was successfully saved 
        fpath = tasks.pop(guid)
        os.startfile(fpath)
    elif state == status.error:
        # Removing the task from the list if an error occurs 
        fpath = tasks.pop(guid)
        host.message("Can't save shot: %s" % fpath)


task_guid, file_path = ss.save(CHANNEL_GUID, callback=callback)
tasks[task_guid] = file_path
Getting an image in bytes

For example, to display in a window host.question

import base64
import host
from shot_saver import ShotSaver

CHANNEL_GUID = "uR76TlcA_O4Yazs8u"

ss = ShotSaver()

__image_html = """<img src="data:image/png;base64,{img}" width="800">"""


def show_image(image_bytes):
    host.question(
        __image_html.format(img=base64.b64encode(image_bytes)),
        "OK", lambda: 0
    )


ss.get(CHANNEL_GUID, callback=show_image)


  • Нет меток