# Referencia de marca de agua de foto local API

Herramientas fotográficas locales gratuitas: marca de agua por lotes, etiquetas de nombre de archivo y sellos de fecha.

## Elige una superficie de ejecución

El descubrimiento API es público, gratuito, de solo lectura y no requiere ninguna clave API. Describe herramientas y configuraciones; Nunca acepta imágenes. No hay POST/marca de agua, servicio de procesamiento en la nube ni punto final MCP alojado.

Utilice el navegador SDK para archivos seleccionados explícitamente en este origen. Para un asistente con acceso al sistema de archivos local, conecte explícitamente el servidor stdio MCP del repositorio y autorice un directorio raíz. Un modelo que encuentre esta documentación no tendrá acceso a un dispositivo ni a sus archivos.



| Superficie | Propósito |
| --- | --- |
| OBTENER JSON / Rebaja | Descubra capacidades, recetas, restricciones y firmas de herramientas locales. |
| Navegador ESM SDK | Decodificar y renderizar archivos localmente; requiere Canvas, DOM, createImageBitmap y File/Blob. No es un Node ni un procesamiento HTTP remoto API. |
| CLI local/estdio MCP | Automatización local conectada explícitamente mediante Google Chrome instalado y dependencias del repositorio. |


## Recursos públicos

GET y HEAD devuelven recursos estáticos. Sin autenticación, cuerpo de solicitud, parámetros de consulta ni datos de usuario. Las rutas de recursos desconocidas devuelven 404. Trate la versión 1 como la versión del contrato; marque rutas canónicas en lugar de fragmentos de compilación con hash. No se promete acceso a navegadores de distintos orígenes; utilizar importaciones SDK del mismo origen.

- [Catálogo de capacidades](/api/v1/capabilities.json)
- [Recetas predeterminadas completas y variables de texto compatibles](/api/v1/templates.json)
- [Receta JSON Schema (2020-12)](/api/v1/recipe.schema.json)
- [Esquemas de entrada locales MCP](/api/v1/mcp-tools.json)
- [Especificación de descubrimiento OpenAPI 3.1](/openapi.json)
- [Directorio de descubrimiento opcional](/llms.txt)

```
curl https://watermark.noxxxx.com/api/v1/capabilities.json
curl https://watermark.noxxxx.com/api/v1/recipes/filename.json
```


## Navegador SDK

Importe /sdk/watermark.js en el origen de este sitio. Esta es una URL de entrada estable ESM; Los fragmentos de implementación pueden cambiar. El siguiente ejemplo espera una entrada de varios archivos y se ejecuta después de que el usuario selecciona archivos locales. Crea un ZIP de copias exitosas; las personas que llaman deben inspeccionar failures y cancelled en lugar de tratar la exportación parcial como completa.



```
import { createRecipe, validateRecipe, inspectImage, processBatch, packageResults }
  from '/sdk/watermark.js';

// Run on this site's origin in a modern browser, after explicit file selection.
const files = [...document.querySelector('input[type="file"]').files];
const recipe = createRecipe('filename'); // watermark | filename | date | frame
const errors = validateRecipe(recipe);
if (errors.length) throw new Error(errors.join('; '));
const records = [];
try {
  for (const file of files) records.push(await inspectImage(file));
  const result = await processBatch(records, recipe);
  if (result.failures.length || result.cancelled) {
    console.warn('Check partial results before downloading', result);
  }
  if (result.entries.length) {
    const zip = await packageResults(result.entries);
    const url = URL.createObjectURL(zip);
    const link = document.createElement('a');
    link.href = url; link.download = 'labeled-photos.zip'; link.click();
    setTimeout(() => URL.revokeObjectURL(url), 30000);
  }
} finally {
  records.forEach(record => URL.revokeObjectURL(record.thumbnail));
}
```

| Función | Entrada → resultado |
| --- | --- |
| createRecipe(mode) | watermark \| filename \| date \| frame → receta v1 independiente. |
| validateRecipe(recipe) | Receta → cadena [] errores; vacío significa que la configuración es válida. La validación semántica también verifica los ID únicos y los límites de recorte. |
| inspectImage(file) | File → Promise<Record> con ID, nombre, archivo, ancho, alto, URL del objeto en miniatura, anulaciones, metadatos, advertencia de metadatos. Revocar la miniatura cuando haya terminado. `{id,name,file,width,height,thumbnail,overrides,metadata,metadataWarning}` |
| renderImage(record, recipe, options?) | → Promise<{blob, geometry}>; preview:true devuelve {canvas, geometry}. opciones: activos:Map<assetId,ImageBitmap\|Canvas>, índice:número, maxDimension:número, lienzo:Canvas. missingMetadataText?:string. `{blob,geometry} \| {canvas,geometry}` |
| processBatch(records, recipe, options?) | → Promise<{entries,failures,cancelled}>. Entrada: {name,blob,width,height,sourceId}; falla: {id,name,longEdge,message}. opciones: activos, señal:AbortSignal, onProgress({done,total,failed}), onResult(entrada). missingMetadataText?:string. `{entries:[{name,blob,width,height,sourceId}],failures:[{id,name,longEdge,message}],cancelled}` |
| packageResults(entries) | → Promise<Blob> ZIP; rechaza cuando la salida combinada supera los 450 MiB. |
| decodeImage(blob) | → Promise<ImageBitmap>; close() cuando haya terminado. HEIC utiliza la primera imagen decodificada. |
| parseLabelCsv(text) | filename,text CSV → Map<cadena,cadena>; coincidencias de nombres exactos, se rechazan nombres duplicados. Configure record.label usted mismo antes de procesar. |
| imageRecipe(recipe, record) | Fusiona record.overrides.image y record.overrides.layers[id] sin mutar la receta compartida. |
| renderStudioImage / cleanLogo | Ayudantes Canvas de bajo nivel; consulte paquetes de repositorio/watermark-core/src/studio.js para obtener firmas. Prefiera renderImage para salida codificada. |


## Reglas y errores de la receta.

Descargue recetas completas de /api/v1/recipes/watermark.json, filename.json, date.json o frame.json. Valide primero JSON Schema y luego validateRecipe para realizar comprobaciones semánticas. Los ID de capa deben ser únicos. El recorte x + ancho e y + alto debe permanecer dentro de la imagen. Los tamaños, márgenes, bordes y pies de página utilizan porcentajes del borde corto de la imagen recortada y girada. La salida longEdge:0 mantiene el tamaño; cambiar el tamaño nunca mejora. El campo opcional image.crop.aspectRatio define ancho/alto del contenido tras girarlo. El recorte se centra en la selección normalizada de cada imagen, incluso con tamaños distintos. Después se añaden bordes y pie. Editar los porcentajes elimina la regla de proporción.

Variables de texto: {filename} excluye la extensión; {fullname} lo incluye; {index} usa sequence.start y relleno; {label} utiliza record.label. Las variables de la cámara son {camera}, {lens}, {aperture}, {iso}, {shutter}, {focal}. Un CSV no completa automáticamente los registros SDK.

El ajuste preestablecido de fecha utiliza DateTimeOriginal o CreateDate de cada imagen. No se sustituye ninguna fecha de modificación del expediente. La fecha faltante tiene por defecto una etiqueta de fecha vacía; missing:error falla en esa imagen, missing:custom usa date.custom si se puede analizar. source:custom utiliza la fecha proporcionada directamente. Las fechas personalizadas no son marcas de tiempo certificadas. Las fechas no válidas pueden generar una etiqueta vacía o un error según esta política.

Una receta contiene configuraciones, no bytes de logotipo ni fuentes personalizadas. Suministre logotipos a través de options.assets codificados por layer.assetId y cierre los mapas de bits de logotipos decodificados después de su uso. Las fuentes personalizadas deben cargarse en document.fonts bajo su familia LocalFont. Los recursos faltantes fallan explícitamente.

El SDK genera recetas no válidas antes de la ejecución por lotes. Los errores de decodificación, renderizado, metadatos o codificación por imagen aparecen en failures, mientras que el entries exitoso permanece disponible. Actualmente, los errores contienen mensajes en chino legibles por humanos; los consumidores no deben extenderse en su texto. La cancelación se verifica entre salidas; el renderizado actual no se interrumpe. Con onResult, los entries se entregan a la devolución de llamada y no se retienen en la matriz entries devuelta.




## Límites y privacidad

Sin cuota de recuento de fotografías pagada, cuenta, clave API, suscripción ni marca de sitio agregada. Cada entrada está limitada a 150 MiB y 120 millones de píxeles; La salida ZIP está limitada a 450 MiB. Máximo 30 capas, 6 tamaños de salida adicionales, borde largo hasta 32768. Los límites del navegador Canvas, la memoria, el decodificador y el sistema de archivos pueden ser menores; dividir lotes grandes.

Las salidas son JPEG, PNG o WebP. JPEG y WebP con pérdida se vuelven a codificar. El modo de metadatos predeterminado es strip. Los modos safe y all requieren salida JPEG. El modo safe excluye el GPS; el modo all puede conservar metadatos de ubicación. Los perfiles ICC, HDR y firmas no se conservan. Los archivos originales nunca se modifican.

Opcionalmente, solo los recursos del programa se almacenan en caché para su uso sin conexión en /studio/.. Las nuevas páginas públicas necesitan una conexión de red para cargarse inicialmente. Las imágenes de usuario y los nombres de archivos no se envían al público API ni se almacenan en ajustes preestablecidos. Guarde/comparta solo recetas que no contengan texto privado.




## Locales MCP

Esta capacidad la proporciona el repositorio, no un punto final de Internet. Requisitos previos: instalación de Node.js, pnpm en el repositorio y Google Chrome instalado. Ejecute el servidor desde el repositorio, con un directorio permitido explícito. No infiera una ruta privada al sistema de archivos a partir de los resultados de búsqueda web.



```
node scripts/watermark-mcp.mjs --root /absolute/authorized/photo-folder
```

| Herramienta | Entrada y resultado |
| --- | --- |
| validate_recipe | {recipe} → {errors:string[]}. No lee imágenes. |
| inspect_images | {files:string[]} → {images:[{id,name,width,height,metadata,metadataWarning}],failures:[{id,name,index,stage,message}]}. |
| preview_watermark | {files,recipe,output?,logos?} → {files:[{path,width,height}],failures,cancelled}. Escribe solo la primera imagen, borde más largo ≤1400. |
| batch_watermark | {files,recipe,output?,logos?} → {files:[{path,width,height}],failures,cancelled}. Escribe imágenes individuales, no un ZIP. |
Las rutas de entrada en files se resuelven dentro de --root. El mapa logos vincula los ID de activos con rutas dentro de la misma raíz. El valor predeterminado "output" es "watermark-output" dentro de la raíz; Las rutas absolutas también deben permanecer dentro de esta raíz. Se rechazan las fugas de enlaces simbólicos. Los archivos existentes se conservan eligiendo nuevos nombres de archivo de salida. Los esquemas de vista previa y lote exigen recipe; inspect_images solo acepta files. Las imágenes no válidas se incluyen en failures y las válidas continúan. index empieza en 0 en el arreglo files original; stage es inspect o render. La vista previa solo procesa files[0], sin sustituirlo.  Las solicitudes no válidas devuelven "isError" con un mensaje de texto; Los errores de procesamiento individuales permanecen en failures. Las llamadas son de solicitud/respuesta y no existe una herramienta de cancelación.

MCP devuelve JSON serializado dentro de content[0].text, no structuredContent. Inspeccionar y validar son de sólo lectura; Vista previa y escritura por lotes de copias. Ninguna herramienta sube fotos. Un cliente debe configurar explícitamente este comando stdio local antes de usar las herramientas.