# 本地照片水印API參考

免費的本地照片工具：大量浮水印、檔案名稱標籤和日期戳記。

## 選擇執行面

發現 API 是公開的、免費的、唯讀的，並且不需要 API 金鑰。它描述了工具和設定；它從不接受圖像。沒有 POST /浮水印、雲端處理服務或託管 MCP 端點。

使用瀏覽器 SDK 來明確選擇此來源上的檔案。對於具有本機檔案系統存取權限的助手，請明確連接儲存庫的 stdio MCP 伺服器並授權根目錄。找到此文件的模型無法存取裝置或其文件。



| 表面 | 目的 |
| --- | --- |
| 取得 JSON / 降價 | 發現功能、配置、約束和本地工具簽名。 |
| 瀏覽器 ESM SDK | 本地解碼並渲染檔案；需要 Canvas、DOM、createImageBitmap 和 File/Blob。不是 Node 或遠端 HTTP 處理 API。 |
| 本地 CLI/stdio MCP | 使用已安裝的 Google Chrome 和儲存庫依賴項明確連接本地自動化。 |


## 公共資源

GET 和 HEAD 傳回靜態資源。沒有身份驗證、請求正文、查詢參數或使用者資料。未知資源路徑返回404。將版本1視為合約版本；為規範路徑添加書籤，而不是散列構建塊。不承諾跨域瀏覽器存取；使用同源SDK進口。

- [能力目錄](/api/v1/capabilities.json)
- [完整的預設配置和支援的文字變量](/api/v1/templates.json)
- [食譜 JSON Schema (2020-12)](/api/v1/recipe.schema.json)
- [本地 MCP 輸入模式](/api/v1/mcp-tools.json)
- [OpenAPI 3.1 發現規範](/openapi.json)
- [可選的發現目錄](/llms.txt)

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


## 瀏覽器 SDK

在本網站的來源匯入 /sdk/watermark.js。這是一個穩定的ESM入口網址；實現區塊可能會改變。以下範例需要多個檔案輸入，並在使用者選擇本機檔案後執行。它創建了 ZIP 的成功副本；呼叫者必須檢查 failures 和 cancelled，而不是將部分匯出視為完成。



```
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));
}
```

| 功能 | 輸入→結果 |
| --- | --- |
| createRecipe(mode) | watermark \| filename \| date \| frame → 獨立的v1配置。 |
| validateRecipe(recipe) | 配置 → string[] 錯誤；空表示配置有效。語義驗證還檢查唯一 ID 和裁剪範圍。 |
| inspectImage(file) | File → Promise<Record> 帶有 id、名稱、檔案、寬度、高度、縮圖物件 URL、覆蓋、元資料、元資料警告。完成後撤銷縮圖。 `{id,name,file,width,height,thumbnail,overrides,metadata,metadataWarning}` |
| renderImage(record, recipe, options?) | → Promise<{blob, geometry}>; preview:true 回傳 {canvas, geometry}。選項：資產：Map <assetId，ImageBitmap \| Canvas>，索引：數字，最大尺寸：數字，畫布：Canvas。 missingMetadataText?:string. `{blob,geometry} \| {canvas,geometry}` |
| processBatch(records, recipe, options?) | → Promise<{entries,failures,cancelled}>。條目：{name,blob,width,height,sourceId}；故障：{id,name,longEdge,message}。選項：資產，訊號：AbortSignal、onProgress({done,total,failed})、onResult(入場)。 missingMetadataText?:string. `{entries:[{name,blob,width,height,sourceId}],failures:[{id,name,longEdge,message}],cancelled}` |
| packageResults(entries) | → Promise<Blob> ZIP;當組合輸出超過 450 MiB 時拒絕。 |
| decodeImage(blob) | → Promise<ImageBitmap>;完成後 close() 。 HEIC 使用第一個解碼影像。 |
| parseLabelCsv(text) | filename,text CSV → Map<字串,字串>;精確名稱匹配，重複名稱拒絕。加工前自行設定record.label。 |
| imageRecipe(recipe, record) | 合併 record.overrides.image 和 record.overrides.layers[id] 而不改變共享配置。 |
| renderStudioImage / cleanLogo | 低階 Canvas 助理；請參閱儲存庫套件/watermark-core/src/studio.js 以取得簽名。優選 renderImage 進行編碼輸出。 |


## 配置規則和錯誤

從 /api/v1/recipes/watermark.json、filename.json、date.json 或 frame.json 下載完整食譜。首先驗證 JSON Schema，然後驗證 validateRecipe 進行語意檢查。層 ID 必須是唯一的。裁切 x + 寬度和 y + 高度必須保留在影像內。大小、邊距、邊框和頁腳使用裁切和旋轉影像的短邊的百分比。輸出 longEdge:0 保持大小；調整大小永遠不會升級。 可選的 image.crop.aspectRatio 表示旋轉後內容的寬高比。每張圖片在各自的歸一化選區內置中裁剪，混合尺寸批次維持相同比例；隨後加入邊框與底欄。手動編輯裁剪百分比會清除比例規則。

文字變數：{filename} 不包括副檔名；{fullname} 包括它；{index}使用sequence.start和填充；{label} 使用 record.label。相機變數為 {camera}、{lens}、{aperture}、{iso}、{shutter}、{focal}。 CSV 不會自動填入 SDK 記錄。

日期預設使用每個影像的 DateTimeOriginal 或 CreateDate。不替換文件修改日期。缺少日期預設為空日期標籤； missing:error 使該圖像失敗，missing:custom 如果可解析則使用 date.custom。 source:custom 直接使用提供的日期。自訂日期不是經過認證的時間戳記。根據此政策，無效日期可能會產生空白標籤或錯誤。

配置包含設置，而不是徽標位元組或自訂字體。透過由 layer.assetId 鍵入的 options.assets 提供徽標，並在使用後關閉解碼的徽標點陣圖。自訂字體必須載入到 LocalFont 系列下的 document.fonts 中。缺少資源會明確失敗。

SDK 在批量執行之前拋出無效配置。每個影像的解碼、渲染、元資料或編碼錯誤出現在 failures 中，而成功的 entries 仍然可用。錯誤目前包含人類可讀的中文訊息；消費者不應該在他們的文字上分支。在輸出之間檢查取消；目前渲染不會中斷。對於 onResult，entries 將傳遞給回調，並且不會保留在傳回的 entries 陣列中。




## 限制和隱私

無需付費照片計數配額、帳戶、API 金鑰、訂閱或新增網站品牌。每個輸入限制為 150 MiB 和 1.2 億像素； ZIP 輸出限制為 450 MiB。最大 30 層，6 個附加輸出尺寸，長邊可達 32768。瀏覽器 Canvas、記憶體、解碼器和檔案系統限制可以更低；分割大批次。

輸出為 JPEG、PNG 或 WebP。 JPEG 和有損 WebP 被重新編碼。預設元資料模式為“strip”。 「safe」和「all」模式需要 JPEG 輸出。 safe模式不包括GPS； all模式可以保留位置元資料。不保留 ICC 設定檔、HDR 和簽名。原始文件永遠不會改變。

在 /studio/ 中，僅可選擇快取程式資源以供離線使用。新的公共頁面最初需要網路連線才能載入。使用者圖像和檔案名稱不會傳送到公眾 API 或儲存在預設中。僅儲存/分享不包含私人文字的食譜。




## 本地 MCP

此功能由儲存庫提供，而不是網路端點。先修條件：Node.js、pnpm安裝在儲存庫中，並安裝了Google Chrome。從儲存庫運行伺服器，並使用明確允許的目錄。不要從 Web 搜尋結果推斷私有檔案系統路徑。



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

| 工具 | 輸入和結果 |
| --- | --- |
| validate_recipe | {recipe} → {errors:string[]}。不讀取影像。 |
| 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}。僅寫入第一張影像，最長邊緣≤1400。 |
| batch_watermark | {files,recipe,output?,logos?} → {files:[{path,width,height}],failures,cancelled}。寫入單一影像，而不是 ZIP。 |
“files”中的輸入路徑在“--root”內解析。 「logos」對應將資產 ID 連結到同一根中的路徑。預設的「output」是根目錄中的「watermark-output」；絕對路徑也必須保留在該根目錄內。符號連結轉義被拒絕。透過選擇新的輸出檔案名稱來保留現有檔案。 預覽和批次工具的輸入契約均要求 recipe；inspect_images 只接受 files。壞圖記錄在 failures 中，有效圖片繼續處理。失敗的 index 是原始 files 陣列中從 0 開始的索引，stage 為 inspect 或 render。預覽只處理 files[0]，不會替換成其他圖片。 無效請求返回「isError」並帶有簡訊；個別處理錯誤仍保留在「failures」中。呼叫是請求/回應，沒有中止工具。

MCP 傳回在 content[0].text 內部序列化的 JSON，而不是 structuredContent。檢查和驗證是唯讀的；預覽和批次寫入副本。沒有工具上傳照片。在使用這些工具之前，用戶端必須明確配置此本機 stdio 命令。