diff --git a/.github/workflows/thumb-gen.yml b/.github/workflows/thumb-gen.yml index 10a6085..31acc43 100644 --- a/.github/workflows/thumb-gen.yml +++ b/.github/workflows/thumb-gen.yml @@ -26,7 +26,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install pytest Pillow get-video-properties ffmpy ffmpeg-python + python -m pip install pytest Pillow get-video-properties ffmpy sudo wget -P /home/ "https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4" sudo apt-get install ffmpeg - name: Test with pytest diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6788022..0000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: python - -python: "3.6" - -before_install: - - sudo wget -P /home/ "https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4" - - sudo apt-get install ffmpeg - -install: - - pip install Pillow - - pip install get-video-properties - - pip install ffmpy - - pip install ffmpeg-python - -script: - - pytest tests diff --git a/README.md b/README.md index f9e9180..071e3bf 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,13 @@ You can use pip: ## Configurations -(These may change during the update) - - The number of screen images that should be included in the final thumbnail image - - Thumbnail image quality - - Font type in the video info panel. You can add a file path of a font file (.ttf) to this - - Font size in the video info panel - - Custom text in the video info panel +- Background color of the thumbnail (Hex codes are also supported) +- Font colour of the thumbnail (Hex codes are also supported) Download font files : [FontSquirrel](https://www.fontsquirrel.com/) @@ -54,6 +50,8 @@ IMAGE_QUALITY = 80 FONT = FONT_SIZE = 30 CUSTOM_TEXT = +BG_COLOUR = white +FONT_COLOUR = black ``` ## Usage @@ -95,15 +93,15 @@ CUSTOM_TEXT = ### Python -- If you don't set an output folder, thumbnail images will be saved in the video folder (video_path). -- If you don't need a custom text and custom font file (including font size) and you have already set these for the configuration file (using console or defaults), it will be added automatically. To avoid this set the `custom_text` value to `False` and add a custom font file location. +- If you don't set an output folder, thumbnail images will be saved in the video folder (video_path). +- If you don't need a custom text and custom font file (including font size) and you have already set these for the configuration file (using console or defaults), it will be added automatically. To avoid this set the `custom_text` value to `False` and add a custom font file location. #### Example 1 ``` python from thumb_gen.worker import Generator -#video_path, output_path='', custom_text=True, font_dir='', font_size= +#video_path, output_path='', custom_text=True, font_dir='', font_size=0, bg_colour='', font_colour='' app = Generator("C:/input/video.mp4", "C:/output/", "www.example.com", "C:/Windows/Fonts/Arial.ttf", 30) app.run() ``` @@ -117,6 +115,6 @@ from thumb_gen.worker import Generator folder = 'C:/input' for video in os.listdir(folder): if video.endswith('.mp4') or video.endswith('.mkv'): - app = Generator(os.path.join(folder, video), custom_text=False, font_dir="C:/Project/font.ttf", font_size=25) + app = Generator(os.path.join(folder, video), custom_text=False, font_dir="C:/Project/font.ttf", font_size=25, bg_colour='blue', font_colour='red') app.run() ``` diff --git a/README.rst b/README.rst index 2324044..e74bf8c 100644 --- a/README.rst +++ b/README.rst @@ -30,17 +30,13 @@ You can use pip: Configurations -------------- -(These may change during the update) - - The number of screen images that should be included in the final thumbnail image. - - Thumbnail image quality - - Font type in the video info panel. You can add a file path of a font file (.ttf) to this. - - Font size in the video info panel - - Custom text in the video info panel +- Background color of the thumbnail (Hex codes are also supported) +- Font colour of the thumbnail (Hex codes are also supported) Download font files : `FontSquirrel `_ @@ -63,6 +59,8 @@ By program default: FONT = FONT_SIZE = 30 CUSTOM_TEXT = + BG_COLOUR = white + FONT_COLOUR = black ----- Usage @@ -109,7 +107,6 @@ Python ====== - If you don't set an output folder, thumbnail images will be saved in the video folder (video_path). - - If you don't need a custom text and custom font file (including font size) and you have already set these for the configuration file (using console or defaults), it will be added automatically. To avoid this set the `custom_text` value to `False` and add a custom font file location. Example 1 @@ -131,6 +128,6 @@ Example 2 folder = 'C:/input' for video in os.listdir(folder): - if video.endswith('.mp4') or video.endswith('.mkv'): - app = Generator(os.path.join(folder, video), custom_text=False) - app.run() + if video.endswith('.mp4') or video.endswith('.mkv'): + app = Generator(os.path.join(folder, video), custom_text=False, font_dir="C:/Project/font.ttf", font_size=25, bg_colour='blue', font_colour='red') + app.run() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..092470f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +ffmpy +get_video_properties +Pillow diff --git a/thumb_gen/application.py b/thumb_gen/application.py index c2750ac..9124148 100644 --- a/thumb_gen/application.py +++ b/thumb_gen/application.py @@ -1,5 +1,6 @@ import os import re +import sys import datetime from ffmpy import FFmpeg @@ -7,6 +8,7 @@ from PIL import Image from PIL import ImageFont from PIL import ImageDraw +from PIL import ImageColor from .config import read_config from .utils import listToString, video_info, get_file_size, convert_unit, packagePath @@ -79,7 +81,7 @@ def lining(text, font, font_size, image_width): return lines -def imageText(video_path, secure_tmp, bg_width, bg_height, custom_text, font_dir, font_size): +def imageText(video_path, secure_tmp, bg_width, bg_height, custom_text, font_dir, font_size, bg_colour, font_colour): if font_dir == '': font_name = read_config('font') if font_name == '': @@ -97,6 +99,12 @@ def imageText(video_path, secure_tmp, bg_width, bg_height, custom_text, font_dir elif custom_text == 'False': custom_text = '' + if bg_colour == '': + bg_colour = read_config('bg_colour') + + if font_colour == '': + font_colour = read_config('font_colour') + filename = re.split(pattern = r"[/\\]", string = video_path) filename = filename[-1] @@ -183,7 +191,25 @@ def imageText(video_path, secure_tmp, bg_width, bg_height, custom_text, font_dir bg_new_height = text_area_height + bg_height - img = Image.new('RGB', (bg_width, bg_new_height), color = 'white') + try: + bg_colour = ImageColor.getrgb(bg_colour) + except ValueError: + bg_colour = bg_colour + print("ValueError: unknown color specifier: {}".format(bg_colour)) + print("This can be fixed by changing the configurations.\n" \ + "Ex: Background colour = 'white' / Background colour = '#ffffff'") + sys.exit() + + try: + font_colour = ImageColor.getrgb(font_colour) + except ValueError: + font_colour = font_colour + print("ValueError: unknown color specifier: {}".format(font_colour)) + print("This can be fixed by changing the configurations.\n" \ + "Ex: Font colour = 'black' / Font colour = '#ffffff'") + sys.exit() + + img = Image.new('RGB', (bg_width, bg_new_height), bg_colour) img.save(os.path.join(secure_tmp, 'bg.png')) background = Image.open(os.path.join(secure_tmp, 'bg.png')) @@ -211,21 +237,21 @@ def imageText(video_path, secure_tmp, bg_width, bg_height, custom_text, font_dir for lines in info_filename_line['line{}'.format(rounds)]: if lines != []: font_height = font_info(info_filename, font_name, font_size)[1] - draw.text((x, y), lines, 'black', font=font) + draw.text((x, y), lines, font_colour, font=font) y = y + font_height font_height = font_info(info_filesize, font_name, font_size)[1] #line2 - draw.text((x, y), info_line2, 'black', font=font) + draw.text((x, y), info_line2, font_colour, font=font) y = y + 5 + font_height #line3 - draw.text((x, y), info_line3, 'black', font=font) + draw.text((x, y), info_line3, font_colour, font=font) y = y + 5 + font_height #line4 - draw.text((x, y), info_line4, 'black', font=font) + draw.text((x, y), info_line4, font_colour, font=font) y = y + 5 + font_height rounds = 0 @@ -236,7 +262,7 @@ def imageText(video_path, secure_tmp, bg_width, bg_height, custom_text, font_dir for lines in text_lines['line{}'.format(rounds)]: if lines != []: font_height = font_info(lines, font_name, font_size)[1] - draw.text((x, y), lines, 'black', font=font) + draw.text((x, y), lines, font_colour, font=font) y = y + font_height y = y + 5 @@ -277,7 +303,7 @@ def resize(screenshot_folder, resize_folder): return True -def thumb(video_path, output_folder, resize_folder, secure_temp, custom_text, font_dir, font_size): +def thumb(video_path, output_folder, resize_folder, secure_temp, custom_text, font_dir, font_size, bg_colour, font_colour): for img in os.listdir(resize_folder): image = Image.open(os.path.join(resize_folder, img)) r_new_width, new_height = image.size @@ -292,7 +318,7 @@ def thumb(video_path, output_folder, resize_folder, secure_temp, custom_text, fo bg_new_width = int((r_new_width * 3) + 20) bg_new_height = int((new_height * img_rows) + ((5 * img_rows) + 5)) - y = imageText(video_path, secure_temp, bg_new_width, bg_new_height, custom_text, font_dir, font_size) + y = imageText(video_path, secure_temp, bg_new_width, bg_new_height, custom_text, font_dir, font_size, bg_colour, font_colour) backgroud = Image.open(os.path.join(secure_temp, 'bg.png')) diff --git a/thumb_gen/config.py b/thumb_gen/config.py index 195dee9..f2abf26 100644 --- a/thumb_gen/config.py +++ b/thumb_gen/config.py @@ -4,7 +4,7 @@ from .utils import get_datadir, CheckIfFileExists from .version import config_version -def create_config(IMAGES=12, IMAGE_QUALITY=80, FONT='', FONT_SIZE=30, CUSTOM_TEXT=''): +def create_config(IMAGES=12, IMAGE_QUALITY=80, FONT='', FONT_SIZE=30, CUSTOM_TEXT='', BG_COLOUR='white', FONT_COLOUR='black'): my_datadir = get_datadir() / "thumb-gen" try: @@ -16,7 +16,7 @@ def create_config(IMAGES=12, IMAGE_QUALITY=80, FONT='', FONT_SIZE=30, CUSTOM_TEX finally: configfile_path = os.path.join(str(my_datadir), "config.ini") config_object = configparser.ConfigParser() - config_object["DEFAULT"] = {"images": IMAGES, "image_quality": IMAGE_QUALITY, "font":FONT, "font_size":FONT_SIZE, "custom_text":CUSTOM_TEXT} + config_object["DEFAULT"] = {"images": IMAGES, "image_quality": IMAGE_QUALITY, "font":FONT, "font_size":FONT_SIZE, "custom_text":CUSTOM_TEXT, "bg_colour":BG_COLOUR, "font_colour":FONT_COLOUR} config_object["VERSION"] = {"config_version": config_version} with open(configfile_path, 'w') as conf: config_object.write(conf) @@ -49,6 +49,12 @@ def modify_config(options, value): else: userinfo["custom_text"] = str(value) + elif options == "bg_colour": + userinfo["bg_colour"] = str(value) + + elif options == "font_colour": + userinfo["font_colour"] = str(value) + with open(configfile_path, 'w') as conf: config_object.write(conf) @@ -96,6 +102,10 @@ def read_config(option): return int(default['font_size']) elif option == 'custom_text': return str(default['custom_text']) + elif option == 'bg_colour': + return str(default['bg_colour']) + elif option == 'font_colour': + return str(default['font_colour']) loop = False except KeyError: diff --git a/thumb_gen/options.py b/thumb_gen/options.py index 5834175..0abae21 100644 --- a/thumb_gen/options.py +++ b/thumb_gen/options.py @@ -41,8 +41,7 @@ def parseOpts(argument_list): sys.exit() elif opt in ("-c", "--config"): - conf_images, conf_image_quality, conf_font, conf_font_size, conf_custom_text = configurations() - + conf_images, conf_image_quality, conf_font, conf_font_size, conf_custom_text, conf_bg_colour, conf_font_colour = configurations() if conf_images != 0: modify_config('images', conf_images) @@ -55,9 +54,15 @@ def parseOpts(argument_list): if conf_font_size != 0: modify_config('font_size', conf_font_size) - if conf_custom_text != 0: + if conf_custom_text != '': modify_config('custom_text', conf_custom_text) + if conf_bg_colour != '': + modify_config('bg_colour', conf_bg_colour) + + if conf_font_colour != '': + modify_config('font_colour', conf_font_colour) + sys.exit() def begin(args='', opt=''): diff --git a/thumb_gen/version.py b/thumb_gen/version.py index e48aa39..6a9f5af 100644 --- a/thumb_gen/version.py +++ b/thumb_gen/version.py @@ -1,2 +1,2 @@ -__version__ = "1.0.4" -config_version = "2021.03.25" \ No newline at end of file +__version__ = "1.0.5" +config_version = "2021.04.03" \ No newline at end of file diff --git a/thumb_gen/viewer.py b/thumb_gen/viewer.py index 2cfa225..8ce8a3f 100644 --- a/thumb_gen/viewer.py +++ b/thumb_gen/viewer.py @@ -3,6 +3,7 @@ from .config import read_config from .utils import CheckIfFileExists, check_os from datetime import datetime +from PIL import ImageColor now = datetime.now() current_time = now.strftime("%H:%M:%S") @@ -36,67 +37,97 @@ def helps(): def configurations(): print("Configurations\n") - print("Images = {}\nThumbnail Quality = {}\n".format(read_config('images'), read_config('image_quality'))) - - loop = True - while loop: + print("Images = {}\n" \ + "Thumbnail Quality = {}\n" \ + "Font = {}\n" \ + "Font Size = {}\n" \ + "Custom Text = {}\n" \ + "Background Colour = {}\n" \ + "Font Colour = {}\n" \ + .format(read_config('images'), \ + read_config('image_quality'), \ + read_config('font'), \ + read_config('font_size'), \ + read_config('custom_text'), \ + read_config('bg_colour'), \ + read_config('font_colour'))) + + while True: try: - loop2 = True - while loop2: + while True: print("If you do not want to change the values, leave the input blank and press Enter.\n") print("CTRL + C to exit.") try: images = int(input("Images: ") or 0) - loop2 = False + break except ValueError: print("Invalid input! Please enter a valid number.") - loop3 = True - while loop3: + while True: try: - loop4 = True - while loop4: + while True: image_quality = int(input("Thumbnail Quality (10 - 100): ") or 0) if 101 > image_quality > 9 or image_quality == 0: - loop4 = False - loop3 = False + break else: print("Enter number between 10 - 100!") + break except ValueError: print("Invalid input! Please enter a valid number.") - loop5 = True - while loop5: + while True: font_path = str(input("Font Path: ") or '0') font_path_status = CheckIfFileExists(font_path) if font_path_status or font_path == '0': - loop5 = False + break else: print("No font file found. Check the path and re-enter it") - loop6 = True - while loop6: + while True: try: - loop7 = True - while loop7: + while True: font_size = int(input("Font Size (10 - 100): ") or 0) if 9 < font_size < 101 or font_size == 0: - loop7 = False - loop6 = False + break else: print("Enter number between 10 - 100!") + break except ValueError: print("Invalid input! Please enter a valid number.") + print("Input 'clear' or '000' to clear custom text") custom_text = str(input("Custom text: ") or '') + while True: + try: + bg_colour = str(input("Background Colour: ") or '') + if bg_colour == '': + pass + else: + ImageColor.getrgb(bg_colour) + except ValueError: + print("Color not recognized: {}. Enter a valid colour!".format(bg_colour)) + else: + break + + while True: + try: + font_colour = str(input("Font Colour: ") or '') + if font_colour == '': + pass + else: + ImageColor.getrgb(font_colour) + except ValueError: + print("Color not recognized: {}. Enter a valid colour!".format(font_colour)) + else: + break + except KeyboardInterrupt: - loop = False - sys.exit() + sys.exit('\n') - loop = False + break - return images, image_quality, font_path, font_size, custom_text + return images, image_quality, font_path, font_size, custom_text, bg_colour, font_colour def print_process(name): oss = check_os() diff --git a/thumb_gen/worker.py b/thumb_gen/worker.py index e4a13df..f929e53 100644 --- a/thumb_gen/worker.py +++ b/thumb_gen/worker.py @@ -7,14 +7,8 @@ from .utils import listToString class Generator: - def __init__(self, video_path, output_path='', custom_text='True', font_dir='', font_size=0): + def __init__(self, video_path, output_path='', custom_text='True', font_dir='', font_size=0, bg_colour='', font_colour=''): self.video_path = video_path - self.font_dir = font_dir - - if isinstance(font_size, int): - self.font_size = font_size - elif isinstance(font_size, str): - raise ValueError("Font size must be an integer") if output_path == '': self.output_path = self.video_path[:-4] @@ -26,6 +20,16 @@ def __init__(self, video_path, output_path='', custom_text='True', font_dir='', self.output_folder = self.output_path self.custom_text = str(custom_text) + self.font_dir = font_dir + + if isinstance(font_size, int): + self.font_size = font_size + elif isinstance(font_size, str): + raise ValueError("Font size must be an integer") + + self.bg_colour = bg_colour + self.font_colour = font_colour + self.temp_dir = tempfile.TemporaryDirectory() self.secure_temp = self.temp_dir.name self.screenshot_folder = os.path.join(self.secure_temp, 'screenshots') @@ -37,7 +41,7 @@ def run(self): print_process(self.video_path) screenshots(self.video_path, self.screenshot_folder) resize(self.screenshot_folder, self.resize_folder) - thumb_out = thumb(self.video_path, self.output_path, self.resize_folder, self.secure_temp, self.custom_text, self.font_dir, self.font_size) + thumb_out = thumb(self.video_path, self.output_path, self.resize_folder, self.secure_temp, self.custom_text, self.font_dir, self.font_size, self.bg_colour, self.font_colour) if thumb_out: print_success(self.output_folder)