mirror of
https://github.com/Paillat-dev/FABLE.git
synced 2026-01-02 01:06:20 +00:00
112 lines
5.0 KiB
Python
112 lines
5.0 KiB
Python
|
|
import openai
|
||
|
|
import os
|
||
|
|
|
||
|
|
from PIL import Image, ImageDraw, ImageFont
|
||
|
|
import random
|
||
|
|
from dotenv import load_dotenv
|
||
|
|
from PIL import Image
|
||
|
|
load_dotenv()
|
||
|
|
|
||
|
|
openai.api_key = os.getenv("OPENAI_API_KEY")
|
||
|
|
'''
|
||
|
|
Putpose of this file is to generate a miniature of the video.
|
||
|
|
It has a function that takes a path, title, and description and generates a miniature.
|
||
|
|
It uses pillow to generate the image, and openai to generate text1 and text2.
|
||
|
|
|
||
|
|
text 1 is a short text max 2 words to put on the top of the image.
|
||
|
|
text 2 is a 3 word text to put in the middle of the image.
|
||
|
|
|
||
|
|
The function returns the path of the image.
|
||
|
|
|
||
|
|
First open bcg.png. Then create a new image and add a random gradient to it from top to bottom.
|
||
|
|
then put the png on top of the gradient.
|
||
|
|
Then add text1 and text2 to the image.
|
||
|
|
'''
|
||
|
|
|
||
|
|
prompt = '''Generate 2 short textes OF MAX 2-4 WORDS each to put on the top of the miniature of the video. Here are some examples:
|
||
|
|
For the title "Python Exception Handling" the text1 could be "No more crashes!" and the text2 could be "Easy!"
|
||
|
|
The second text is often shorter than the first one.
|
||
|
|
Answer without anything else, just with the 2 textes. Answer with text1 on the first line and text2 on the second line. Nothing else.
|
||
|
|
Here is the title of the video: [TITLE]
|
||
|
|
Here is the description of the video: [DESCRIPTION]'''
|
||
|
|
|
||
|
|
def rand_gradient(image):
|
||
|
|
randr = random.SystemRandom().randint(1, 20)
|
||
|
|
randg = random.SystemRandom().randint(1, 20)
|
||
|
|
randb = random.SystemRandom().randint(1, 20)
|
||
|
|
|
||
|
|
for i in range(image.size[0]):
|
||
|
|
for j in range(image.size[1]):
|
||
|
|
colors = [i//randr, j//randg, i//randb]
|
||
|
|
position1 = [image.size[0]//5, image.size[1]//5]
|
||
|
|
position2 = [image.size[0]//5, image.size[1]//2]
|
||
|
|
if i == position1[0] and j == position1[1]:
|
||
|
|
textcolor1 = colors
|
||
|
|
if i == position2[0] and j == position2[1]:
|
||
|
|
textcolor2 = colors
|
||
|
|
image.putpixel((i,j), (colors[0], colors[1], colors[2]))
|
||
|
|
return image, textcolor1, textcolor2
|
||
|
|
|
||
|
|
def generate_miniature(path, title, description):
|
||
|
|
prmpt = prompt.replace("[TITLE]", title).replace("[DESCRIPTION]", description)
|
||
|
|
response = openai.ChatCompletion.create(
|
||
|
|
model="gpt-4",
|
||
|
|
messages=[
|
||
|
|
{"role":"user","content":prmpt},
|
||
|
|
],
|
||
|
|
)
|
||
|
|
response['choices'][0]['message']['content']
|
||
|
|
text1 = response['choices'][0]['message']['content'].split("\n")[0]
|
||
|
|
text2 = response['choices'][0]['message']['content'].split("\n")[1]
|
||
|
|
generate_image(path, text1, text2)
|
||
|
|
|
||
|
|
def generate_image(path, text1, text2):
|
||
|
|
bcg = Image.open("bcg.png")
|
||
|
|
img = Image.new('RGBA', (1920, 1080))
|
||
|
|
img, textcolor1, textcolor2 = rand_gradient(img)
|
||
|
|
draw = ImageDraw.Draw(img)
|
||
|
|
font1 = ImageFont.truetype("./Sigmar-Regular.ttf", 200)
|
||
|
|
font2 = ImageFont.truetype("./Sigmar-Regular.ttf", 200)
|
||
|
|
text1words = text1.split(" ")
|
||
|
|
text2words = text2.split(" ")
|
||
|
|
text1def = ""
|
||
|
|
text2def = ""
|
||
|
|
#max charachters per line is 7, but if a word is longer than 7 charachters, do not split it. Howerver if 2 or more words can fit on the same line, put them on the same line.
|
||
|
|
for word in text1words:
|
||
|
|
if len(text1def.split("\n")[-1]) + len(word) > 7:
|
||
|
|
text1def += "\n"
|
||
|
|
text1def += word + " "
|
||
|
|
for word in text2words:
|
||
|
|
if len(text2def.split("\n")[-1]) + len(word) > 7:
|
||
|
|
text2def += "\n"
|
||
|
|
text2def += word + " "
|
||
|
|
maxlen1 = max([len(line) for line in text1def.split("\n")])
|
||
|
|
maxlen2 = max([len(line) for line in text2def.split("\n")])
|
||
|
|
#if the text is too long, reduce the font size proportionally
|
||
|
|
if maxlen1 > 7:
|
||
|
|
font1 = ImageFont.truetype("./Sigmar-Regular.ttf", 200 - (maxlen1 - 7)*10)
|
||
|
|
if maxlen2 > 7:
|
||
|
|
font2 = ImageFont.truetype("./Sigmar-Regular.ttf", 200 - (maxlen2 - 7)*10)
|
||
|
|
text1def = text1def.upper().strip()
|
||
|
|
text2def = text2def.upper().strip()
|
||
|
|
textcolor1 = [255 - textcolor1[0], 255 - textcolor1[1], 255 - textcolor1[2]]
|
||
|
|
textcolor2 = [255 - textcolor2[0], 255 - textcolor2[1], 255 - textcolor2[2]]
|
||
|
|
imgtext1 = Image.new('RGBA', (1920, 1080))
|
||
|
|
imgtext2 = Image.new('RGBA', (1920, 1080))
|
||
|
|
drawtext1 = ImageDraw.Draw(imgtext1)
|
||
|
|
drawtext1.text((imgtext1.size[0]//8*2, 0), text1def, font=font1, fill=(textcolor1[0], textcolor1[1], textcolor1[2]))
|
||
|
|
imgtext1 = imgtext1.rotate(-5, expand=True)
|
||
|
|
drawtext2 = ImageDraw.Draw(imgtext2)
|
||
|
|
drawtext2.text((imgtext2.size[0]//8*2.5, imgtext2.size[1]//5*2), text2def, font=font2, fill=(textcolor2[0], textcolor2[1], textcolor2[2]))
|
||
|
|
imgtext2 = imgtext2.rotate(5, expand=True)
|
||
|
|
#paste the textes on the image
|
||
|
|
img.paste(bcg, (0, 0), bcg)
|
||
|
|
img.paste(imgtext1, (0, 0-img.size[1]//8), imgtext1)
|
||
|
|
if len(text1def.split("\n")) > 2: #if the text is too long, put the second text on the third line
|
||
|
|
img.paste(imgtext2, (0, img.size[1]//8), imgtext2)
|
||
|
|
else:
|
||
|
|
img.paste(imgtext2, (0, 0), imgtext2)
|
||
|
|
img.save(path + "/miniature.png")
|
||
|
|
return path + "/miniature.png"
|
||
|
|
|
||
|
|
generate_image("test", "Master python loops", "Effortlessly")
|