Bildbeschreibungen sind wichtig, nerven aber zu schreiben. Das sah auch ein Mensch so, dessen Blogpost ich neulich irgendwo gelesen habe. Der Post beschrieb eine iOS/iPadOS/macOS-Automation, mit der Bildbeschreibungen von in der Zwischenablage befindlichen Bildern durch die OpenAI-API erzeugt werden konnten. Diese Bildbeschreibung sollte man dann selbst in den ALT-Text des zu postenden Bildes kopieren.
Ich habe mir überlegt, dass man die Automatisierung noch ein wenig weiter treiben kann, und habe diesen Python-Stub erzeugt: Das CLI-Tool nimmt bis zu vier Bilder per Kommandozeile entgegen, fragt zuerst den Text des Posts ab, dann die zu nutzenden Tags und wirft dann die Bilder der Reihe nach in die OpenAI. Die so von dort geernteten Bildbeschreibungen landen als ALT-Texte im automatisch erzeugten Mastodon-Post.
Neat.
from openai import OpenAI
import base64
import os
import sys
import io
from PIL import Image
from mastodon import Mastodon
from termcolor import colored
client = OpenAI(api_key='sk-proj-...')
server = "https://server.tld/"
token = "..."
mastodon = Mastodon(access_token=token, api_base_url=server)
def resize_image(image_path):
with Image.open(image_path) as img:
max_size = 800
if max(img.size) > max_size:
img.thumbnail((max_size, max_size))
print(colored(f"Bild verkleinert: {image_path}", "cyan"))
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format=img.format)
img_byte_arr.seek(0)
return img_byte_arr
def generate_image_description(image_path):
prompt = """
Erstelle eine prägnante, objektive Bildbeschreibung in maximal 50 Wörtern, die das Bild für blinde oder sehbehinderte Menschen zugänglich macht.
Nutze das Schema 'Hauptobjekt – Handlung – Kontext'.
Falls relevanter Text im Bild vorhanden ist, transkribiere ihn vollständig.
Vermeide generische Phrasen und beginne nicht mit 'Das Bild zeigt'.
Die Beschreibung sollte klar und informativ sein.
"""
try:
print(colored(f"Generiere Bildbeschreibung für: {image_path}", "cyan"))
img_byte_arr = resize_image(image_path)
base64_image = base64.b64encode(img_byte_arr.getvalue()).decode('utf-8')
file_extension = os.path.splitext(image_path)[1].lower()
mime_type = {
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.png': 'image/png',
'.gif': 'image/gif',
'.webp': 'image/webp'
}.get(file_extension, 'image/jpeg')
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": f"data:{mime_type};base64,{base64_image}"}}
]}
],
max_tokens=300,
)
return response.choices[0].message.content
except Exception as e:
return colored(f"Fehler: {e}", "red")
def post_to_mastodon(image_paths, descriptions, user_text, hashtags):
try:
print(colored("Bilder werden auf Mastodon hochgeladen...", "yellow"))
media_ids = []
for image_path, description in zip(image_paths, descriptions):
media = mastodon.media_post(image_path, description=description)
media_ids.append(media['id'])
status_text = f"{user_text}\n\n{hashtags}" if hashtags else user_text
status = mastodon.status_post(status_text, media_ids=media_ids)
print(colored(f"Bild erfolgreich gepostet: {status['url']}", "green"))
except Exception as e:
print(colored(f"Fehler beim Posten auf Mastodon: {e}", "red"))
def main():
print(colored("Willkommen bei Holger's KI-Masto-Poster!", "magenta", attrs=["bold"]))
if len(sys.argv) < 2:
print(colored("Bitte mindestens ein Bild als Argument angeben.", "red"))
return
image_paths = sys.argv[1:]
if len(image_paths) > 4:
print(colored("Maximal 4 Bilder erlaubt. Vorgang abgebrochen.", "red"))
return
user_text = input(colored("Gib eine Beschreibung für den Post ein: ", "blue")).strip()
hashtags = input(colored("Gib eine Liste von Hashtags ein: ", "blue")).strip()
descriptions = []
for image_path in image_paths:
if not os.path.exists(image_path):
print(colored(f"Fehler: Datei {image_path} existiert nicht", "red"))
continue
description = generate_image_description(image_path)
print(colored(f"Bildbeschreibung für {image_path}: {description}", "green"))
descriptions.append(description)
if descriptions:
post_to_mastodon(image_paths, descriptions, user_text, hashtags)
if __name__ == "__main__":
main()
Schreibe einen Kommentar