Ein Cyborg-Mastodon

Mastodon-Posts mit AI-erzeugten Bildbeschreibungen

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()

Beitrag veröffentlicht am

Kommentare

2 Antworten zu „Mastodon-Posts mit AI-erzeugten Bildbeschreibungen“

  1. Avatar von Stefan

    Das ist schon smart, Holger!
    Müsste mir sowas mal raussuchen für meine Mediathek im Blog. Da ist das Thema ja ein ähnliches.
    Na da hab ich ja wieder was zum denken… 😉

    1. Avatar von Holger
      Holger

      Ja, für das Blog wäre das ein totaler Segen… Eigentlich müsste man ja „nur“ den lokalen File-Storage anzapfen und die Datenbank mit den Beschreibungen befüllen… hmmmmm, ….!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert