aiprov: warum ein ExifTool-Aufruf nicht gereicht hat
Metadaten schreiben ist leicht. Die richtigen wegzulassen leider nicht.
Der Untertitel bringt es schon sehr schön auf den Punkt. Aber das wäre als Entstehungsgeschichte für aiprov tatsächlich etwas kurz gegriffen.
Im vorangegangenen Teil meiner Serie ging es darum, dass die Kennzeichnung von KI-generierten Bildern auf der eigenen Website bzw. im eigenen Blog ab 2026 nicht nur eine faire Geste ist, sondern Teil einer nachvollziehbaren Publikationspraxis werden muss.
Der EU AI Act verlangt Transparenz. IPTC, XMP und C2PA liefern technische Bausteine. Bildgeneratoren setzen Metadaten mal mehr, mal weniger – und mal gar nicht. Irgendwann steht man vor der überraschend handfesten Frage:
Wie kommen diese Informationen eigentlich zuverlässig in eine Bilddatei?1
Mein erster Gedanke war naheliegend: ExifTool
Ein Befehl, ein paar XMP-Tags, fertig.
Dachte ich.
Eigentlich hätte ein ExifTool-Aufruf gereicht
Für lediglich „ein paar Bilder“ hätte wirklich ein Shell-Skript gereicht. Das soll kein Argument gegen
aiprov sein, sondern meine anfänglichen Überlegungen schildern.
ExifTool kann XMP-Felder sehr zuverlässig schreiben. Man kann ein Bild nehmen, ein paar Tags setzen und danach prüfen, ob sie angekommen sind. 2
Zum Beispiel so:
exiftool \
-XMP-dc:Creator="Michael Kortstiege" \
-XMP-iptcExt:DigitalSourceType="trainedAlgorithmicMedia" \
-XMP-photoshop:Credit="Michael Kortstiege / Ideogram" \
bild.png
Nicht besonders dramatisch, oder?
ExifTool ist eines dieser Programme, die man erst dann richtig schätzen lernt, wenn man nichts anderes zur Hand hat (oder wenn alles andere zwar irgendwie funktioniert, aber nur so lange, bis man genauer hinsieht).
Die eigentliche Schwierigkeit lag woanders:
Ich wollte nicht „nur Metadaten“ schreiben.
Ich wollte zukünftig nicht bei jedem neuen Bild anfangen zu überlegen, welche Metadaten dort hinein gehören und welche nicht. Und erst recht wollte ich nicht aus Bequemlichkeit Felder setzen, die nach mehr rechtlicher Sicherheit klingen, als tatsächlich vorhanden ist.
Das war der Moment, in dem aus einem Befehl langsam ein Werkzeug wurde.
Nicht weil ExifTool zu wenig kann.
Sondern weil ExifTool sehr viel kann.
Wenn ein Werkzeug alles kann, braucht man eine Grenze
ExifTool schreibt fast alles, was man ihm sagt.
Das ist seine Stärke.
Und genau deshalb wünschte ich mir eine kleine aber feine „redaktionelle Bremse“.
Denn Metadaten sind nicht nur Technik, sie sind Aussagen.
Wenn ich den Metadaten eines Bildes hinterlege, dass es mit einem trainierten algorithmischen System erzeugt
wurde, ist das eine
Herkunftsinformation. Der IPTC-Wert trainedAlgorithmicMedia
bedeutet „Created using Generative AI“ — also digitale Medien, die algorithmisch mit einem auf erfasstem
Inhalt trainierten KI-Modell erzeugt wurden.
3
Wenn ich in ein Bild schreibe, wer es in meinem Veröffentlichungsworkflow verantwortet, ist das eine redaktionelle Zuordnung.
Sollte ich aber automatisch einen Copyright-Hinweis oder eine Lizenz-URL setzen, dann behaupte ich mehr.
Dann sage ich nicht nur:
Dieses Bild wurde mit KI erzeugt.
Sondern möglicherweise auch:
Ich halte Rechte an diesem Bild und darf sie lizenzieren.
Bei „meinen Bildern“ wollte ich genau das nicht automatisch bzw. automatisiert behaupten. Nicht, weil Rechtefragen egal wären. Sondern weil ich sie zu wichtig finde, um sie durch eine bequeme Standardeinstellung zu ersetzen.
Ich bin kein Rechtsberater, sondern technischer Autor. Deshalb sollte mein Tool eine Grenze ziehen. Denn nicht jede mögliche Metadatenangabe ist auch eine sinnvolle Metadatenangabe.
Das klingt wie ein Satz, den man sich auf einem Zettel an den Monitor kleben könnte.
Ich habe es nicht getan.
Noch nicht.
Reset, dann Setzen
Der erste Gedanke hinter aiprov war deshalb nicht:
Wie schreibe ich möglichst viele Felder?
Sondern eher:
Wie komme ich zu einem Bild, dessen Metadaten ich später erklären und verantworten kann?
Dazu gehört auch, vorhandene Metadaten nicht blind weiterzutragen.
Ein Bild kann bereits XMP-Daten enthalten. Manche stammen vom Generator. Manche aus früheren Bearbeitungsschritten. Manche sind nützlich. Manche sind Ballast. Manche möchte man öffentlich haben. Andere wiederum nicht.
Ein optimaler Workflow sieht deshalb für mich in etwa so aus:
1. vorhandene relevante Metadaten einlesen
2. sinnvolle Defaults anbieten
3. bewusst bestätigen oder ändern
4. interne Felder getrennt behandeln
5. nur gewünschte Metadaten schreiben
Kurz:
Erst aufräumen, dann bewusst neu schreiben
Das klingt trivial.
Ist es aber nicht, wenn man denselben Ablauf nicht nur einmal, sondern regelmäßig ausführen möchte.
Ein einzelner ExifTool-Befehl ist schnell geschrieben. Ein wiederholbarer Veröffentlichungsworkflow ist etwas anderes.
Genau dort beginnt die kleine Lücke, in die aiprov hineingerutscht ist.
Nicht als monumentales Brückenbauwerk.
Eher als Geländer.
Die Felder, die wirklich ins Bild gehören
aiprov
ist eine kleine TUI um ExifTool herum. Keine große Anwendung. Kein Bildverwaltungssystem. Kein CMS-Plugin.
4
Eher die Sorte Werkzeug, die man nicht bemerken möchte: kurz installieren, Bildname übergeben, Felder prüfen, bestätigen - fertig.
Demzufolge ist sein Aufruf entsprechend unspektakulär:
npx @mkorun/aiprov cover.png
Oder, wenn es im Projekt installiert ist:
npm install --save-dev @mkorun/aiprov
npx aiprov cover.png
Seine Konfiguration ist bewusst klein gehalten:
{
"namespace": "myns",
"namespaceUrl": "https://mysite.com/xmp/myns/1.0/",
"creator": "Michael Kortstiege",
"subject": "AI-generated",
"dstType": "trainedAlgorithmicMedia",
"aiTool": "Ideogram",
"destination": "teblo.de"
}
Mehr braucht es nicht.
Öffentliche Standardfelder wie XMP-dc:Creator, XMP-dc:Description oder XMP-iptcExt:DigitalSourceType
gehören in bekannte XMP-Bereiche. Interne Felder wie das verwendete KI-Werkzeug, das Zielsystem oder der
Prompt können in einem eigenen Namespace liegen.
Nicht, weil sie verheimlicht werden sollen, sondern weil sie anders behandelt werden müssen.
Der Prompt, mit dem ein Bild entstanden ist, kann für mich selbst nützlich sein. Für die spätere Veröffentlichung eines Web-Derivats stellt er möglicherweise zu viel Information dar, ist zu sperrig – oder schlicht nicht für den öffentlichen Kontext gedacht.
Also trennt aiprov zwischen dem, was ins Bild gehört, und dem, was in meinem Arbeitsprozess hilfreich ist.
Die Feldliste ist überschaubar:
XMP-dc:Creator
XMP-xmp:CreateDate
XMP-dc:Description
XMP-dc:Subject
XMP-iptcExt:DigitalSourceType
XMP-photoshop:Credit
XMP-<eigener Namespace>:aiTool
XMP-<eigener Namespace>:destination
XMP-<eigener Namespace>:aiPrompt
Das ist keine vollständige Metadatenphilosophie.
Es ist eine Werkstattentscheidung.
Diese Felder reichen für meinen Workflow.
Und gerade deshalb ist interessant, welche Felder fehlen.
Der Bildnachweis ist nicht dasselbe wie der Autor
Eine Ergänzung, die ich kurz vor Veröffentlichung vorgenommen habe, ist XMP-photoshop:Credit.
Das Feld wirkt auf den ersten Blick unspektakulär.
Zum Beispiel:
Michael Kortstiege / Ideogram
Aber genau dieses kleine Feld löst ein praktisches Problem.
Creator
beschreibt, wer im redaktionellen oder schöpferischen Workflow als Ersteller geführt wird. Bei den Bildern auf
teblo bin das in der Regel ich selbst.
Das KI-Werkzeug steht in seinem eigenen Feld, zum Beispiel:
Ideogram
Für die sichtbare oder strukturierte Ausgabe auf einer Website brauche ich aber häufig eine andere Form:
Michael Kortstiege / Ideogram
Das ist kein juristischer Copyright-Hinweis.
Es ist ein Bildnachweis.
Eine knappe, lesbare Zuordnung.
Der IPTC-Guide beschreibt die Credit Line
als Feld für den gewünschten Bildnachweis bei Veröffentlichung; technisch entspricht das in XMP dem Feld
photoshop:Credit. 5
Deshalb fragt aiprov auch nach XMP-photoshop:Credit
. Wenn im Bild bereits ein Credit vorhanden ist, wird er als Default gelesen. Wenn nicht, schlägt die TUI
automatisch eine Kombination aus Creator und KI-Werkzeug vor.
Im Code sieht der Kern dieser Entscheidung ungefähr so aus:
const creditDefault = defaults.credit || [creator, aiTool]
.filter(Boolean)
.join(' / ')
const credit = await ask(t.creditHint, creditDefault)
Und später wird daraus ein ExifTool-Argument:
...(credit ? [`-XMP-photoshop:Credit=${credit}`] : [])
Das ist ein kleines Detail.
Aber genau solche Details entscheiden darüber, ob ein Werkzeug im Alltag hilft.
Nicht, weil es unmöglich wäre, diesen String jedes Mal selbst zu tippen. Das ist kein Problem! Man könnte dann
auch jedes Mal überlegen, ob man
Creator, Credit, DigitalSourceType und interne Felder sauber auseinanderhält.
Man kann vieles.
Manches möchte man nur nicht jedes Mal wieder aufs neue machen.
Die TUI ist keine Oberfläche. Sie ist eine Leitplanke.
Eine TUI für Metadaten klingt zunächst nach Komfort.
Ein paar Eingabefelder im Terminal. Pfeiltasten. Bestätigen. Fertig.
Für aiprov ist die TUI aber weniger Oberfläche als Leitplanke.
Sie führt mich durch eine kleine Reihe von Entscheidungen, die ich nicht jedes Mal neu rekonstruieren möchte.
Welcher Creator?
Welches KI-Werkzeug?
Welche Beschreibung?
Welche Tags?
Welcher DigitalSourceType?
Welcher Credit?
Welcher Prompt bleibt intern erhalten?
Für ein einzelnes Bild wäre das vielleicht übertrieben, aber für einen wiederholbaren Veröffentlichungsprozess ist es beruhigend.
Zumal aiprov
vorhandene XMP-Tags liest und als Defaults anbietet. Die Reihenfolge ist bewusst einfach gehalten:
bestehende XMP-Werte
↓
config.json
↓
eingebaute Fallbacks
Das verhindert, dass ein schon sauber vorbereitetes Bild versehentlich durch allgemeine Projektdefaults überschrieben wird.
Und es verhindert, dass ich jedes Mal bei null anfange.
An dieser Stelle merke ich, dass ein Tool manchmal nicht dadurch nützlich wird, dass es besonders viel automatisiert, sondern dadurch, dass es die richtigen Fragen in der richtigen Reihenfolge stellt.
Als aiprov
vom privaten Skript zum kleinen Werkzeug „auch für andere“ wurde (das passierte allerdings sehr schnell :),
änderten sich deshalb auch ein paar Dinge, die mit Metadaten zunächst wenig zu tun haben:
--help, --version, eine stabile Config-Location und ein Build-Check vor der Veröffentlichung.
Für ein privates Skript wäre das nur Beiwerk gewesen. Für ein veröffentlichtes CLI ist es Teil des Versprechens: Wer das Werkzeug benutzt, soll nicht erst meine Werkstattordnung erraten müssen.
Was aiprov bewusst nicht schreibt
Der wichtigste Teil von aiprov
befindet sich nicht in der Liste der Felder, die es schreibt – sondern in der Liste der Felder, die es
nicht schreibt.
SEO-Tools und strukturierte Daten können bei Bildern Felder wie creditText, copyrightNotice, license oder acquireLicensePage erwarten oder zumindest vorschlagen. Schema.org kennt diese Eigenschaften für ImageObject beziehungsweise CreativeWork
; Google nutzt Lizenz-Metadaten außerdem für seine „Licensable“-Darstellung in der Bildsuche.
6
Für klassische Fotografien kann das sinnvoll sein.
Für KI-generierte Bilder gilt das in meinem Workflow nicht.
Ich möchte nicht automatisch einen Copyright-Hinweis in eine Datei schreiben, solange ich nicht sauber begründen kann, dass diese konkrete Datei urheberrechtlich als mein Werk geschützt ist.
Auch möchte ich keine Lizenz-URL setzen, wenn ich gar nicht sicher bin, welche Rechte ich damit eigentlich einräume.
Das ist keine große juristische These.
Es ist eine kleine technische Vorsichtsmaßnahme.
aiprov schreibt deshalb bewusst nicht:
XMP-dc:rights
XMP-xmpRights:WebStatement
acquireLicensePage
Oder in JSON-LD-Begriffen:
{
"copyrightNotice": "nicht automatisch setzen",
"license": "nicht automatisch setzen",
"acquireLicensePage": "nicht automatisch setzen"
}
Das wirkt zunächst wie eine Lücke.
Für mich ist es das Gegenteil.
Es ist der Punkt, an dem das Werkzeug nicht einfach alles ausfüllt, was irgendwo möglich wäre.
Ein gutes Metadatenwerkzeug schreibt nicht möglichst viel, es schreibt das, wofür man Verantwortung übernehmen kann.
DigitalSourceType ist keine Lizenz
Das wichtigste Feld bleibt deshalb für KI-Bilder DigitalSourceType.
In meinem Workflow setzt aiprov hier den IPTC-Wert:
trainedAlgorithmicMedia
Das sagt nicht:
Dieses Bild gehört mir.
Es sagt:
Dieses Bild wurde mit einem trainierten algorithmischen System erzeugt.
Das ist die Information, um die es bei KI-Bildtransparenz eigentlich geht. 3
Natürlich löst dieses Feld nicht alle Fragen. Es ist kein Wasserzeichen. Es ist kein Herkunftszertifikat. Es ist keine Lizenz. Und es ist erst recht keine Garantie, dass jede Plattform diese Information erhält.
Aber es ist ein standardisierter maschinenlesbarer Hinweis.
Und für einen eigenen Blog ist das ein sinnvoller Anfang.
Nicht die ganze Lösung.
Ein Anfang.
Das klingt klein – ist es auch. Aber Publishing besteht erstaunlich oft aus kleinen, richtigen Entscheidungen, die man konsequent wiederholt.
Leider auch aus kleinen falschen.
Die wiederholt man dann ebenfalls konsequent.
Ich mache das aber nur ungern öffentlich.
XMP ist nur eine Schicht
Damit ist allerdings noch nicht die ganze Veröffentlichung beschrieben.
XMP steckt in der Bilddatei.
Eine Website besteht aber nicht nur aus Bilddateien.
Sie besteht aus HTML, strukturierten Daten, Open-Graph-Bildern, Vorschaubildern, alternativen Formaten, komprimierten Derivaten, vielleicht JSON-LD, vielleicht sichtbaren Hinweisen.
Deshalb gehören Informationen nicht nur in die Bilddatei, sondern auch in den Quelltext oder direkt auf die Seite.
Ein Beispiel ist creditText.
In der Bilddatei kann XMP-photoshop:Credit stehen:
Michael Kortstiege / Ideogram
In JSON-LD kann daraus später etwas werden wie:
{
"@type": "ImageObject",
"creditText": "Michael Kortstiege / Ideogram",
"digitalSourceType": "https://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia",
"description": "KI-generiertes Titelbild für einen Blogartikel"
}
Schema.org kennt für ImageObject unter anderem creditText und digitalSourceType; digitalSourceType
verweist dabei auf eine IPTC Digital Source Enumeration.
7
Aber auch hier gilt:
Nur weil ein Feld möglich ist, muss es nicht gesetzt werden.
Für meinen Workflow ist die Bilddatei die erste Schicht.
Die Website ist die zweite.
Und genau da beginnt das nächste Problem.
Der Moment, in dem das Originalbild nicht mehr das Bild ist
Nach aiprov sah die Sache zunächst ordentlich aus.
Das Originalbild hatte die relevanten Metadaten.
Der Creator war gesetzt.
Der DigitalSourceType war gesetzt.
Der Bildnachweis war gesetzt.
Interne Felder lagen im eigenen Namespace.
Der Prompt konnte im Arbeitsbild bleiben, jedoch ohne Veröffentlichung.
Mit ExifTool ließ sich das prüfen:
exiftool -XMP:all -G1 -a my-image.png
So weit, so sauber.
Leider veröffentliche ich keine Originalbilder.
hadley
, mein eigener Static Site Generator, verarbeitet Bilder – wie auch alle anderen SSGs und CMS-Systeme –
weiter. Aus einem Quellbild werden Webformate, Größenvarianten, Vorschaubilder, Open-Graph-Grafiken. Dafür ist
zum Beispiel Sharp hervorragend geeignet.
Hervorragend.
Bis man Metadaten behalten möchte.
Oder gezielt entfernen.
Oder nach einer Transformation wieder korrekt einfügen.
Damit waren die Metadaten im Originalbild dank aiprov jetzt sauber.
Leider veröffentliche ich keine Originalbilder.
Und das ist die Geschichte für meinen nächsten Artikel.