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.
.
|