Kodi Community Forum
Correct method for taking screenshots via API? - Printable Version

+- Kodi Community Forum (https://forum.kodi.tv)
+-- Forum: Development (https://forum.kodi.tv/forumdisplay.php?fid=32)
+--- Forum: Kodi Application (https://forum.kodi.tv/forumdisplay.php?fid=93)
+---- Forum: JSON-RPC (https://forum.kodi.tv/forumdisplay.php?fid=174)
+---- Thread: Correct method for taking screenshots via API? (/showthread.php?tid=377776)



Correct method for taking screenshots via API? - DoubleT - 2024-06-01

Hi,

Im working on a update of my KodiKontroller web app and currently looking at retrieving screenshots of Kodi.
I have it working with this JSON packet;
Code:
{
        "jsonrpc": "2.0",
        "method": "Input.ExecuteAction",
        "params": {"action": "screenshot"},
        "id": 5
    }
which i stole from Chorus - is this the only method available?

I see in Doxygen that the underlying function can take a URL param for where to save the image, can this be accessed from the API in anyway?
https://xbmc.github.io/docs.kodi.tv/master/kodi-base/d0/d3e/page__list_of_built_in_functions.html#built_in_functions_5 TakeScreenshot(url[,sync)

Or is it possible to set the screenshot location programmatically?


RE: Correct method for taking screenshots via API? - scott967 - 2024-06-05

I wrote a simple addon to take screenshots using a keymapped key to runscript.  The screenshot is stored next to the video as fanartnn.jpg or in an extrafanart subfolder as screenshotnn.jpg.  This might get you started.

python:
    def get_screenshot(self, use_folderarts: bool) -> None:
        """takes a screenshot and saves file as jpg in appropriate folder

        Args:
            use_folderarts (bool): switch between extrafanart and fanartnn styles
        """
        if (xbmc.getCondVisibility('VideoPlayer.Content(episodes)')
                or xbmc.getCondVisibility('VideoPlayer.Content(files)')):
            current_folder = xbmc.getInfoLabel('Player.Folderpath')
        else:
            current_folder = xbmc.getInfoLabel('Player.Folderpath')
        if (not xbmc.getCondVisibility('Player.HasMedia')
                or xbmc.getCondVisibility('Player.IsInternetStream')):
            self.log('No valid save location for screenshot', LOG_LEVEL[1])
            return
        self.log(f'Current playing media folder path: {current_folder}')
        current_folder = current_folder.replace('\\', '/')
        if use_folderarts:
            shot_folder = current_folder + 'extrafanart/'
        else:
            shot_folder = current_folder
        unc_folder = shot_folder.lstrip('smb:')
        if not os.path.exists(unc_folder):
            os.mkdir(unc_folder)
            self.log(f'Created new folder {unc_folder}')
        str_shot_folder =  '\"' + shot_folder + '\"'
        # set the screenshot folder in Kodi
        response = xbmc.executeJSONRPC('{"jsonrpc":"2.0", '
                                        '"method":"Settings.SetSettingValue",'
                                        '"params": {'
                                            '"setting": "debug.screenshotpath", '
                                            '"value":  %s}, '
                                        '"id":1}' % str_shot_folder)

        if 'result' in response:
            xbmc.executebuiltin('TakeScreenshot')
            notify_dialog = xbmcgui.Dialog()
            notify_dialog.notification('Screenshot','','',1000)
        shot_pattern = re.compile(r'screenshot(\d+)\.png')
        jpg_shot_pattern = re.compile(r'screenshot(\d+)\.jpg')
        fanart_pattern = re.compile(r'fanart(\d+)')
        xbmc.sleep(500) #ensure screenshot has been saved
        screenshot_files: list = [png_file for png_file in os.listdir(unc_folder)
                                  if shot_pattern.fullmatch(png_file)]
        maxfile: int = 0
        jpgmaxfile: int = 0
        # get list of all screenshotnnnn.jpg files in folder and find max nnnn
        jpg_files: list = [jpg_file for jpg_file in os.listdir(unc_folder)
                           if jpg_shot_pattern.fullmatch(jpg_file)]
        for jpg_file in jpg_files:
            if int(jpg_shot_pattern.search(jpg_file).group(1)) > jpgmaxfile:
                jpgmaxfile = int(jpg_shot_pattern.search(jpg_file).group(1))
        #convert image from png to jpg and save then delete png file
        for file in screenshot_files:
            try:
                with Image.open(unc_folder + file) as image:
                    image = image.convert('RGB')
                    newfile = 'screenshot' + str(jpgmaxfile +1).zfill(4) + '.jpg'
                    image.save(unc_folder + newfile)
                jpgmaxfile = jpgmaxfile +1
                os.remove(unc_folder + file)
                if use_folderarts:
                    self.log(f'{newfile} added to extrafanart folder', LOG_LEVEL[2])
                else:
                    # rename screenshotmm.jpg to fanartnn+1.jpg where nn is current max fanart
                    fanart_files: list = [fanart for fanart in os.listdir(unc_folder)
                                    if fanart_pattern.fullmatch(fanart.split('.')[0])]
                    # get the max fanartnn.jpg nn value so new fanart can be added as next nn
                    for fanart_file in fanart_files:
                        if int(fanart_pattern.search(fanart_file).group(1)) > maxfile:
                            maxfile = int(fanart_pattern.search(fanart_file).group(1))
                    os.rename(unc_folder + newfile, unc_folder + 'fanart'
                                + str(maxfile + 1) + '.jpg')
                    self.log(f'screenshot added as fanart{str(maxfile + 1)}.jpg', LOG_LEVEL[2])
            except IOError as ioerror:
                self.log(f'Unable to process {file} due to {ioerror}', LOG_LEVEL[1])

I guess you would need to use "Player.GetItem" JSON method instead of Player.FolderPath and also ensure you have read/write access to the folders.

scott s.
.