Web Design IES
Web Design in Easy Steps, now in its 7th Edition, shows you how to make effective websites that work on any device.
Bedtime Stories is a pair of Python programs that create illustrated stories for you. The first program, the Bedtime Story Maker, uses ChatGPT and Stable Diffusion to create stories starring your chosen heroes, and in your chosen location and genre. Each paragraph of the story has an illustration. The second program, Bedtime Story Reader, reads the story aloud for you while showing you the approriate image at each point of the story.
Bedtime Story Maker saves all the files relating to a particular story in a folder with a name that includes the time of creation. It takes a little while to generate stories, so it makes sense to generate stories and play them back separately. Because stories are saved, you can return to favourites as often as you like.
To play a story, you need to add its folder name where shown at the start of the Bedtime Story Reader program.
ChatGPT sometimes returns unusual results. A valid story folder should contain the same number of story files and images, or have one extra story file (for the title). Check that you have a valid story folder before trying to have it read to you.
Stable Diffusion can produce some unusual images, and I think of this project as more of an art project than a genuine story generator for children. Images may have distorted faces and odd anatomy (missing arms and legs, extra heads, etc.). Check the images before showing them to young children or other people who may find any oddities disturbing.
For best results, install Bedtime Stories on a Raspberry Pi and use a small screen so it can sit in the palm of the hand. I'm using a Pimoroni 4" HyperPixel display.
I wrote an article for The MagPi magazine about Bedtime Stories. Find it in issue 130. The MagPi is avaliable for free download, but you can support the magazine by subscribing here, or buying a copy in a shop.
To find out more about how the text-to-speech code works, see my previous Raspberry Radio project. See also my simple demonstration of how to create and download an image using the DeepAI API for Stable Diffusion.
Here are some of my favourite images generated by the program. The remarkable thing is that the image prompts were created using ChatGPT, so it took very minimal user input to create these images, just a suggestion of some characters, a location, and a story genre. The black and white images are particularly evocative.
These images do show some of the oddities that occur, such as the inconsistent scale of the boat and children in the first image, and the strange anatomy of the dragon and robots. There were, of course, many more images that were not so successful, but the project nonetheless is able to surprise and delight, and provides a fun platform for exploring the state of AI today.
For more example images, see the article in issue 130 of The MagPi.
You'll need to install the required libraries and text-to-speech software. Open a terminal window and then enter the following instructions:
pip install pyttsx3 requests openai
sudo apt install espeak mopidy
To use this project, you will need an API key for ChatGPT and an API key for DeepAI.
# Story Maker - by Sean McManus - www.sean.co.uk
import os, openai, requests, datetime, random, time
def write_list(list_to_write, filename):
for number, paragraph in enumerate(list_to_write):
filepath = os.path.join(directory, f"{filename}-{number}.txt")
with open(filepath, "w") as file:
file.write(paragraph)
date_time_str = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
directory = f"Story {date_time_str}"
os.mkdir(directory)
image_prompts, story_paragraphs = [], []
character1_name = input("What is your main character's name? ")
character1_type = input("What kind of a character is that? ")
character2_name = input("What is your second character's name? ")
character2_type = input("And what kind of a character is that? ")
venue = input("Where does the story take place? (e.g. in a castle, on Mars) ")
genre = input("What is your story genre? ")
story_prompt = f"Please write me a short {genre}\
story. In this story, {character1_name} is a\
{character1_type} and {character2_name} is a\
{character2_type}. The story takes place {venue}.\
For each paragraph, write me an image prompt for\
an AI image generator. Each image prompt must\
start in a new paragraph and have the words 'Image\
Prompt:' at the start. Choose a book illustrator\
and put something in the image prompts to say the\
images should be made in the style of that artist."
while len(image_prompts) == 0:
print("Making ChatGPT request")
openai.api_key = "YOUR API KEY" ### PUT YOUR CHATGPT API KEY HERE
ChatGPT_output = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a children's author."},
{"role": "user", "content": story_prompt}
] )
new_story = ChatGPT_output.choices[0].message["content"]
print(new_story)
for paragraph in new_story.split("\n\n"):
if paragraph.startswith("Image Prompt"):
image_prompts.append(paragraph)
else:
story_paragraphs.append(paragraph)
write_list(story_paragraphs, "story")
write_list(image_prompts, "prompt")
for number, image_prompt in enumerate(image_prompts):
image_prompt += f"{character1_name} is {character1_type} and {character2_name} is {character2_type}. They are {venue}."
print(f"Generating image {number}")
r = requests.post(
"https://api.deepai.org/api/text2img",
data={'text': image_prompt,
'negative_prompt': "poorly drawn face, mutation, deformed, distorted face, extra limbs, bad anatomy",
'width': "720", 'height': "720",
'grid_size': "1"},
headers={'api-key': 'YOUR API KEY'} ### PUT YOUR DEEPAI API KEY HERE
)
image_url = (r.json()["output_url"])
print(f"Image {number} is at {image_url}. Saving now...\n\n")
filename = f"{number}.jpg"
filepath = os.path.join(directory, filename)
img_data = requests.get(image_url).content
with open(filepath, 'wb') as handler:
handler.write(img_data)
print(f"Your files are in {directory}.")
# Story Reader - by Sean McManus - www.sean.co.uk
# Put your story folder below
path = "Story 2023-04-10-12-35-04"
import os, pygame, pyttsx3
win_width, win_height = 720, 720
pygame.init()
windowSurface = pygame.display.set_mode((win_width, win_height))
pygame.mouse.set_visible(False)
voice = pyttsx3.init()
voice.setProperty('rate', 170)
story_files, image_files = [], []
for file in os.listdir(path):
if file.lower().endswith('.jpg'):
image_files.append(file)
elif file.lower().startswith('story'):
story_files.append(file)
story_has_title = len(story_files) > len (image_files)
story_files = sorted(story_files)
image_files = sorted(image_files)
for number, story in enumerate(story_files):
if story_has_title:
image_path = os.path.join(path, image_files[max(0, number - 1)])
else:
image_path = os.path.join(path, image_files[number])
image_to_show = pygame.image.load(image_path)
image_to_show = pygame.transform.scale(image_to_show, (win_width, win_height))
windowSurface.blit(image_to_show, (0,0))
pygame.display.update()
story_path = os.path.join(path, story)
with open(story_path, "r") as file:
story = file.readlines()
voice.say(story)
voice.runAndWait()
pygame.quit()
© Sean McManus. All rights reserved.
Visit www.sean.co.uk for free chapters from Sean's coding books (including Mission Python, Scratch Programming in Easy Steps and Coder Academy) and more!
Web Design in Easy Steps, now in its 7th Edition, shows you how to make effective websites that work on any device.
Power up your Microsoft Excel skills with this powerful pocket-sized book of tips that will save you time and help you learn more from your spreadsheets.
This book, now fully updated for Scratch 3, will take you from the basics of the Scratch language into the depths of its more advanced features. A great way to start programming.
Code a space adventure game in this Python programming book published by No Starch Press.
Discover how to make 3D games, create mazes, build a drum machine, make a game with cartoon animals and more!
In this entertaining techno-thriller for adults, Sean McManus takes a slice through the music industry: from the boardroom to the stage; from the studio to the record fair.