Alt-Texte für Bilder mit AWS Rekognition und Node.js entwerfen
Verwenden Sie die Operation DetectLabels von AWS Rekognition, um Objekte und Szenen
vorzuschlagen, die eine Person in der Redaktion beim Schreiben von Alt-Texten berücksichtigen kann.
Diese Anleitung gibt bildspezifische Labelvorschläge mit einem Flag
reviewRequired aus und ergänzt anschließend Caching für lokale Dateien und ein kleines
Programm zur sequenziellen Batch-Verarbeitung.
Warum Alt-Texte automatisieren?
Labels können beim Einstieg in eine Beschreibung helfen, aber den Zweck eines Bildes auf einer
Seite nicht bestimmen. Nutzen Sie den
W3C-Entscheidungsbaum für Alt-Texte, um zu entscheiden,
ob Sie das Bild beschreiben, seine Link- oder Schaltflächenfunktion erklären oder für ein dekoratives
Bild einen leeren Alternativtext verwenden. Übernehmen Sie Vorschläge erst in das Attribut
alt, nachdem jemand das Bild im Kontext geprüft hat.
AWS Rekognition und Node.js integrieren
DetectLabels
liefert Labels und Konfidenzwerte statt einer kontextbezogenen Bildbeschreibung. Die Labels werden
auf Englisch zurückgegeben und können mehrere Namen für ein Objekt enthalten, etwa ein bestimmtes
Objekt und seine übergeordnete Kategorie. Dieses Beispiel behält bis zu fünf Namen bei einem
gewählten Konfidenzschwellenwert. Um Wörter in einem Bild zu lesen, verwenden Sie die separate
Operation DetectText von Rekognition.
Umgebung einrichten
Sie benötigen Bash, Node.js 24 LTS, npm und ein authentifiziertes
AWS-Profil oder eine IAM-Rolle mit der Berechtigung, rekognition:DetectLabels aufzurufen.
Die Beispiele wurden mit Node.js 24.21.0 und 26.8.1 sowie dem Paket
@aws-sdk/client-rekognition aus dem AWS SDK v3 in Version 3.1148.0 getestet. Diese Versionen
wurden getestet, sind aber keine zwingenden Mindestversionen für die API. Verwenden Sie eine
gepflegte Node.js-Version. Das Senden eines Bildes an AWS kann Kosten verursachen.
Verwenden Sie die bestehende Authentifizierungsmethode Ihrer Organisation und die
Standard-Anbieterkette für Zugangsdaten des SDK.
Melden Sie sich für ein lokales Profil zuerst an und setzen Sie AWS_PROFILE
in den folgenden Befehlen. Lassen Sie diese Variable bei einer IAM-Rolle weg. Temporäre Zugangsdaten
in Umgebungsvariablen benötigen neben dem Zugriffsschlüssel und dem geheimen Schlüssel auch
AWS_SESSION_TOKEN. Halten Sie deren Werte aus Quelldateien und Terminalausgaben heraus.
Führen Sie dies in dem Verzeichnis aus, in dem Sie ein neues Projekt namens
image-labels anlegen möchten. Die Subshell behält Ihr aktuelles Verzeichnis bei,
und mkdir verweigert das Überschreiben eines bestehenden Projekts.
Das explizite npm-Ziel stellt außerdem sicher, dass die Installation im neuen Projekt erfolgt,
auch wenn dessen übergeordnetes Verzeichnis einen anderen Paketmanager verwendet:
(
command -v node >/dev/null || { printf 'Install Node.js first.\n' >&2; exit 1; }
command -v npm >/dev/null || { printf 'Install npm first.\n' >&2; exit 1; }
[ -z "${NODE_OPTIONS:-}" ] || { printf 'Use a shell without NODE_OPTIONS.\n' >&2; exit 1; }
mkdir image-labels && cd image-labels &&
printf '{"private":true,"type":"module"}\n' > package.json &&
npm install --prefix "$PWD" --workspaces=false --ignore-scripts --save-exact \
@aws-sdk/client-rekognition@3.1148.0
)
Speichern Sie die folgenden Dateien in image-labels. Falls die Installation nach
dem Anlegen des Verzeichnisses fehlschlägt, beheben Sie das gemeldete Problem und führen Sie den
Befehl npm install in diesem Verzeichnis erneut aus. Behalten Sie die vorhandenen
Dateien bei. Wenn Sie den gesamten Erstellungsblock erneut ausführen, verweigert er dieses
Verzeichnis absichtlich.
Anforderungen an Bilder
Verwenden Sie JPEG- oder PNG-Bilder. AWS dokumentiert eine Obergrenze von 5 MB für direkt übergebene
Bytes und 15 MB für ein S3-Objekt. DetectLabels erfordert, dass jede Dimension
zwischen 80 und 10.000 Pixeln liegt. Die aktuellen Grenzen finden Sie in den
Rekognition-Kontingenten. Der Code sendet Ihre ursprünglichen Bytes,
ohne die Größe zu ändern, sie zu decodieren oder Farbprofile zu verändern. Eine erfolgreiche
Anfrage bestätigt weder, dass das Bild unbeschädigt ist, noch, dass die Labels korrekt sind.
Labelvorschläge implementieren
Speichern Sie dies als image-labels/labels.mjs. Das SDK akzeptiert den Dateipuffer direkt.
Codieren Sie ihn nicht manuell als Base64. Wenn Sie credentials nicht setzen,
bleibt die Authentifizierung über Profile und Rollen erhalten. Das Setzen von
maxAttempts: 1 deaktiviert automatische Retries, sodass eine fehlgeschlagene
Analyse ein fehlgeschlagener Aufruf bleibt.
import { DetectLabelsCommand, RekognitionClient } from '@aws-sdk/client-rekognition'
import fs from 'node:fs'
const client = new RekognitionClient({ region: process.env.AWS_REGION, maxAttempts: 1 })
async function detectImageLabels(image, minConfidence = 75) {
if (!Number.isFinite(minConfidence) || minConfidence < 0 || minConfidence > 100) {
throw new Error('Confidence must be a number between 0 and 100.')
}
const response = await client.send(new DetectLabelsCommand({
Image: image,
Features: ['GENERAL_LABELS'],
MaxLabels: 5,
MinConfidence: minConfidence,
}))
return (response.Labels ?? [])
.map((label) => label.Name)
.filter((name) => typeof name === 'string' && name.trim().length > 0)
}
async function suggestImageLabels(imagePath, minConfidence = 75) {
const imageBytes = fs.readFileSync(imagePath)
return detectImageLabels({ Bytes: imageBytes }, minConfidence)
}
function reviewRecord(source, labelSuggestions, minConfidence = 75) {
return { source, minConfidence, reviewRequired: true, labelSuggestions }
}
export { client, detectImageLabels, reviewRecord, suggestImageLabels }
Speichern Sie den Einstiegspunkt als image-labels/review.mjs:
import { client, reviewRecord, suggestImageLabels } from './labels.mjs'
try {
const [imagePath, confidence = '75', ...extra] = process.argv.slice(2)
if (!imagePath || extra.length > 0 || !process.env.AWS_REGION) {
throw new Error('Supply AWS_REGION and an image path, with optional confidence.')
}
const minConfidence = Number(confidence)
const labels = await suggestImageLabels(imagePath, minConfidence)
console.log(JSON.stringify(reviewRecord(imagePath, labels, minConfidence)))
} catch {
console.error('Unable to retrieve image label suggestions. Check the path, region, credentials, and image.')
process.exitCode = 1
} finally {
client.destroy()
}
Wählen Sie Ihre Region und ersetzen Sie MY_PROFILE und
./example.jpg. Pfade sind relativ zu dem Verzeichnis, in dem Sie Node.js ausführen.
Setzen Sie Dateinamen mit Leerzeichen in Anführungszeichen:
AWS_REGION=us-east-1 AWS_PROFILE=MY_PROFILE node image-labels/review.mjs './example.jpg'
Das JSON enthält die ausgewählten source, den Schwellenwert,
reviewRequired: true und labelSuggestions. Vergleichen Sie diese Namen mit
Ihrem tatsächlichen Bild. Eine leere Liste bedeutet eine erfolgreiche Analyse ohne brauchbare
Labels und muss daher ebenfalls geprüft werden. Fehler bei Dateien, Zugangsdaten oder dem Anbieter
geben eine Diagnose auf stderr aus, erzeugen keinen Erfolgsdatensatz und beenden das Programm mit
einem Exit-Code ungleich null. Kein Feld enthält fertigen Alt-Text.
Bilder aus S3 verarbeiten
Bei einem bestehenden S3-Bild muss die Region des Buckets mit der Region des Rekognition-Clients
übereinstimmen. Die aufrufende Identität benötigt s3:GetObject für das Objekt.
Siehe die Anleitung für S3-Bilder und die
IAM-Hinweise von AWS.
Dieses Beispiel liest das aktuelle Objekt unter dem angegebenen Schlüssel und wählt keine
historische Version aus.
Hängen Sie dies an image-labels/labels.mjs an:
async function suggestImageLabelsFromS3(bucket, key, minConfidence = 75) {
return detectImageLabels({ S3Object: { Bucket: bucket, Name: key } }, minConfidence)
}
export { suggestImageLabelsFromS3 }
Speichern Sie image-labels/review-s3.mjs:
import { client, reviewRecord, suggestImageLabelsFromS3 } from './labels.mjs'
try {
const [bucket, key, confidence = '75', ...extra] = process.argv.slice(2)
if (!bucket || !key || extra.length > 0 || !process.env.AWS_REGION) {
throw new Error('Supply AWS_REGION, a bucket, and an object key, with optional confidence.')
}
const minConfidence = Number(confidence)
const labels = await suggestImageLabelsFromS3(bucket, key, minConfidence)
console.log(JSON.stringify(reviewRecord({ bucket, key }, labels, minConfidence)))
} catch {
console.error('Unable to retrieve S3 image label suggestions. Check the key, region, credentials, and permissions.')
process.exitCode = 1
} finally {
client.destroy()
}
Ersetzen Sie Bucket und Schlüssel durch die Angaben Ihres eigenen bestehenden Bildes. Übergeben Sie den Schlüssel unverändert, einschließlich Leerzeichen oder Prozentzeichen. Codieren Sie ihn nicht für URLs. Dieser S3-Verarbeitungspfad nutzt keinen Cache und analysiert daher bei jedem Aufruf das aktuelle Objekt:
AWS_REGION=us-east-1 AWS_PROFILE=MY_PROFILE node image-labels/review-s3.mjs my-bucket 'images/example.jpg'
Sonderfälle und Fehler behandeln
Eine fehlgeschlagene Anfrage unterscheidet sich von einer leeren Labelliste. Die Hilfsfunktionen weisen Fehler zurück. Die Einstiegspunkte melden sie, ohne rohe AWS-Antworten oder Zugangsdaten offenzulegen. Prüfen Sie zur Fehlerbehebung zuerst den lokalen Pfad, dann Authentifizierung und Region. Prüfen Sie bei S3 zusätzlich den exakten Schlüssel und die Leseberechtigungen für das Objekt. Die DetectLabels-Fehler von AWS umfassen nicht unterstützte Formate, ungültige Parameter, nicht zugängliche S3-Objekte sowie Dienst- oder Kontingentfehler. Beheben Sie die Ursache, bevor Sie den Befehl erneut ausführen. Jeder erneute Versuch ist eine weitere mögliche Analyse.
Funktionen erweitern
Caching einrichten
Speichern Sie bei lokalen Bildern erfolgreich ermittelte Namen anhand des Bildinhalts und der
Anfrageeinstellungen im Cache. Dieser optionale Abschnitt setzt einen bereits laufenden
Redis-Server und dessen Verbindungs-URL voraus. Er wurde mit Redis 7.4.11 und dem aktuellen Client
redis in Version 6.3.0 getestet. Installieren Sie den Client im bestehenden
Projekt:
test -f image-labels/package.json &&
npm install --prefix "$PWD/image-labels" --workspaces=false --ignore-scripts --save-exact redis@6.3.0
Speichern Sie image-labels/cache.mjs. Die Cache-Identität enthält die Region, den
Inhalts-Hash, den Konfidenzschwellenwert und die festen Label-Einstellungen. Lesen und analysieren
Sie denselben Puffer, damit eine geänderte Datei keine Labels einer früheren Version wiederverwenden
kann. Speichern Sie erst nach einer erfolgreichen Anbieterantwort. Fehlerhaft formatierte oder
nicht passende Cache-Datensätze führen zu einem sichtbaren Fehler, statt als Labels behandelt zu
werden:
import { createHash } from 'node:crypto'
import fs from 'node:fs'
import { createClient } from 'redis'
import { detectImageLabels } from './labels.mjs'
const redisClient = createClient({
url: process.env.REDIS_URL,
socket: { connectTimeout: 5000, reconnectStrategy: false },
})
redisClient.on('error', () => console.error('Redis connection error.'))
async function getCachedOrSuggestImageLabels(imagePath, minConfidence = 75) {
if (!Number.isFinite(minConfidence) || minConfidence < 0 || minConfidence > 100) {
throw new Error('Confidence must be a number between 0 and 100.')
}
const imageBytes = fs.readFileSync(imagePath)
const imageHash = createHash('sha256').update(imageBytes).digest('hex')
const identity = JSON.stringify({
region: process.env.AWS_REGION, imageHash, minConfidence,
features: ['GENERAL_LABELS'], maxLabels: 5,
})
const cacheKey = `image_labels:v2:${createHash('sha256').update(identity).digest('hex')}`
const cached = await redisClient.get(cacheKey)
if (cached !== null) {
const record = JSON.parse(cached)
if (record.identity !== identity || !Array.isArray(record.labels) ||
!record.labels.every((name) => typeof name === 'string' && name.trim().length > 0)) {
throw new Error('Invalid image-label cache record.')
}
return record.labels
}
const labels = await detectImageLabels({ Bytes: imageBytes }, minConfidence)
await redisClient.set(cacheKey, JSON.stringify({ identity, labels }), { EX: 60 * 60 * 24 })
return labels
}
export { getCachedOrSuggestImageLabels, redisClient }
Speichern Sie image-labels/review-cached.mjs:
import { client, reviewRecord } from './labels.mjs'
let redisClient
try {
const [imagePath, confidence = '75', ...extra] = process.argv.slice(2)
if (!imagePath || extra.length > 0 || !process.env.AWS_REGION || !process.env.REDIS_URL) {
throw new Error('Supply AWS_REGION, REDIS_URL, and an image path, with optional confidence.')
}
const cache = await import('./cache.mjs')
redisClient = cache.redisClient
await redisClient.connect()
const minConfidence = Number(confidence)
const labels = await cache.getCachedOrSuggestImageLabels(imagePath, minConfidence)
console.log(JSON.stringify(reviewRecord(imagePath, labels, minConfidence)))
} catch {
console.error('Unable to retrieve cached image label suggestions. Check Redis and the image prerequisites.')
process.exitCode = 1
} finally {
if (redisClient?.isOpen) await redisClient.close()
client.destroy()
}
Geben Sie Ihre Redis-URL an und führen Sie denselben Befehl zweimal aus. Der zweite Durchlauf sollte das gespeicherte Ergebnis ohne weitere Rekognition-Analyse lesen. Die TTL von 24 Stunden begrenzt die Wiederverwendung, legt aber die Modellversion von AWS nicht fest. Erhöhen Sie den Cache-Namespace, wenn Sie die Projektion oder die festen Einstellungen ändern. Dieses Beispiel schlägt fehl, wenn Redis nicht verfügbar ist. Es wechselt nicht stillschweigend zu einer kostenpflichtigen Anfrage ohne Cache.
AWS_REGION=us-east-1 AWS_PROFILE=MY_PROFILE REDIS_URL=redis://127.0.0.1:6379 node image-labels/review-cached.mjs './example.jpg'
Batch-Verarbeitung
Verarbeiten Sie bei einer kleinen Liste jeweils eine Datei und behalten Sie das Ergebnis jeder
Datei bei. Ein Fehler bei einer Datei verhindert nicht die Analyse späterer Dateien, führt aber
für den gesamten Befehl zu einem Exit-Code ungleich null. Dieses Programm nutzt keinen Cache und
sendet eine Analyse pro lesbarem Bild. Speichern Sie image-labels/review-batch.mjs:
import { client, reviewRecord, suggestImageLabels } from './labels.mjs'
async function batchProcessImages(imagePaths) {
const results = []
for (const imagePath of imagePaths) {
try {
const labels = await suggestImageLabels(imagePath)
results.push(reviewRecord(imagePath, labels))
} catch {
results.push({ source: imagePath, reviewRequired: true, status: 'failed' })
}
}
return results
}
try {
const imagePaths = process.argv.slice(2)
if (imagePaths.length === 0 || !process.env.AWS_REGION) {
throw new Error('Supply AWS_REGION and at least one image path.')
}
const results = await batchProcessImages(imagePaths)
console.log(JSON.stringify(results))
if (results.some((result) => result.status === 'failed')) process.exitCode = 1
} catch {
console.error('Unable to run the image-label batch. Check the region and arguments.')
process.exitCode = 1
} finally {
client.destroy()
}
Prüfen Sie bei jedem Datensatz source, bevor Sie seine Vorschläge verwenden.
Der Datensatz für eine fehlgeschlagene Analyse enthält keine Labeldaten:
AWS_REGION=us-east-1 AWS_PROFILE=MY_PROFILE node image-labels/review-batch.mjs './image1.jpg' './image2.jpg' './image3.jpg'
Konfidenzschwellenwert anpassen
Übergeben Sie einem Befehl für ein einzelnes Bild als letztes Argument einen Schwellenwert zwischen 0 und 100. Fordern Sie beispielsweise eine Mindestkonfidenz von 90 % an:
AWS_REGION=us-east-1 AWS_PROFILE=MY_PROFILE node image-labels/review.mjs './example.jpg' 90
Ein höherer Schwellenwert kann neben unsicheren Labels auch nützliche entfernen. Selbst eine Vorhersage mit hoher Konfidenz kann falsch sein. Die Cache-Hilfsfunktion nimmt diesen Wert in ihre Identität auf. Daher kann eine Anfrage mit 90 % kein Ergebnis wiederverwenden, das mit 75 % angefordert wurde.
Abschließende Gedanken
Nutzen Sie die Vorschläge als Anregungen für eine Person in der Redaktion, die das Bild und den umgebenden Inhalt sehen kann. Konfidenz beschreibt die Vorhersage des Modells, nicht die Qualität der Barrierefreiheit. Falls Ihre Anwendung auch andere Bildanalyseoperationen benötigt, entdecken Sie unseren 🤖 Dienst für künstliche Intelligenz.
