文档

GetWebP CLI JSON 输出参考

每个 GetWebP CLI 命令的机器可读输出架构。

GetWebP CLI JSON 输出参考

每个 GetWebP CLI 命令的机器可读输出架构。在任何命令上使用 --json 以在 stdout 上发出结构化 JSON(人类消息转到 stderr)。

另请参阅: 命令参考 | 退出代码 | CI 集成


概述#

每个 JSON 响应都遵循一个公共信封:

interface BaseResponse {
  success: boolean       // 如果操作完成无错误则为 true
  status?: string        // "success" | "error" | "partial"
  error?: string         // 机器可读的错误代码(失败时)
  message?: string       // 人类可读的描述(失败或部分时)
  data?: object          // 命令特定的负载(auth、status、logout)
  upgrade?: UpgradeHint  // 存在于免费计划(仅转换)
}
 
interface UpgradeHint {
  url: string               // "https://getwebp.com/pricing"
  activateCommand: string   // "getwebp auth <your-key>"
}

关键约定:

  • JSON 始终是以 \n 终止的单行(无美观打印)。
  • 警告和进度消息写入 stderr,永远不会混入 JSON 流。
  • 每个命令都以数字 退出代码 退出,无论是否使用 --json

getwebp convert --json#

convert 命令在所有文件处理完毕后输出单个摘要对象。它不是流式事件格式。

架构#

// 完全成功或部分失败(某些文件出错)
interface ConvertResponse {
  success: boolean        // 仅当所有文件都成功时为 true
  status: "success" | "error"
  total: number           // 尝试的总文件数
  successCount: number    // 成功转换的文件
  failedCount: number     // 出错的文件
  results: FileResult[]   // 每个文件的详情
  upgrade?: UpgradeHint   // 当计划为 "free" 且 results.length > 0 时存在
}
 
// 免费计划限制已达(skipped > 0)
interface ConvertPartialResponse {
  success: true
  status: "partial"
  message: string         // 带升级 CTA 的人类可读摘要
  data: {
    processed: number     // 实际转换的文件
    skipped: number       // 因免费计划限制而跳过的文件
  }
  upgrade: UpgradeHint
}

FileResult 联合#

results 数组中的每个元素都是以下三种形状之一:

// 成功转换
interface SuccessResult {
  file: string            // 输入文件路径
  originalSize: number    // 字节
  newSize: number         // 字节
  savedRatio: number      // 0 到 1(如果 WebP 更大则为负)
  saved: string           // 人类友好的百分比,例如 "35.0%"
  status: "success"
}
 
// 转换失败
interface ErrorResult {
  file: string
  status: "error"
  error: string           // 例如 "Decode failed: Unsupported format"
}
 
// 已跳过(--skip-existing 或 WebP 自覆盖)
interface SkipResult {
  file: string
  status: "skipped"
  reason: "existing"
}

注意: saved 字段(字符串)仅添加到 JSON 输出中的成功结果。它从 savedRatio 派生为 (savedRatio * 100).toFixed(1) + "%"

示例#

所有文件成功(Pro 计划):

{
  "success": true,
  "status": "success",
  "total": 3,
  "successCount": 3,
  "failedCount": 0,
  "results": [
    { "file": "photos/hero.jpg", "originalSize": 204800, "newSize": 133120, "savedRatio": 0.35, "saved": "35.0%", "status": "success" },
    { "file": "photos/logo.png", "originalSize": 51200, "newSize": 20480, "savedRatio": 0.6, "saved": "60.0%", "status": "success" },
    { "file": "photos/banner.bmp", "originalSize": 921600, "newSize": 184320, "savedRatio": 0.8, "saved": "80.0%", "status": "success" }
  ]
}

混合成功和失败:

{
  "success": false,
  "status": "error",
  "total": 2,
  "successCount": 1,
  "failedCount": 1,
  "results": [
    { "file": "photo.jpg", "originalSize": 204800, "newSize": 133120, "savedRatio": 0.35, "saved": "35.0%", "status": "success" },
    { "file": "corrupt.png", "status": "error", "error": "Decode failed: Invalid PNG header" }
  ]
}

免费计划,带跳过的文件(限制已达):

{
  "success": true,
  "status": "partial",
  "message": "Processed 20 images. Free plan limit reached (5 remaining). Upgrade at getwebp.com/pricing, then run: getwebp auth <your-key>",
  "data": {
    "processed": 20,
    "skipped": 5
  },
  "upgrade": {
    "url": "https://getwebp.com/pricing",
    "activateCommand": "getwebp auth <your-key>"
  }
}

免费计划,所有文件已处理(在限制以下):

{
  "success": true,
  "status": "success",
  "total": 3,
  "successCount": 3,
  "failedCount": 0,
  "results": [
    { "file": "a.jpg", "originalSize": 102400, "newSize": 71680, "savedRatio": 0.3, "saved": "30.0%", "status": "success" }
  ],
  "upgrade": {
    "url": "https://getwebp.com/pricing",
    "activateCommand": "getwebp auth <your-key>"
  }
}

在免费计划上,当至少处理了一个文件时,upgrade 对象始终存在,即使未达到文件限制。

缺少输入路径:

{
  "success": false,
  "status": "error",
  "error": "missing_input",
  "message": "Please specify an input path"
}

getwebp auth --json#

架构#

// 成功
interface AuthSuccessResponse {
  success: true
  data: {
    message: string   // 例如 "Activated — Pro plan unlocked"
  }
}
 
// 失败
interface AuthErrorResponse {
  success: false
  status: "error"
  error: "unknown_error"
  message: string         // 服务器提供的错误描述
}

示例#

成功激活:

{
  "success": true,
  "data": {
    "message": "Activated — Pro plan unlocked"
  }
}

激活失败:

{
  "success": false,
  "status": "error",
  "error": "unknown_error",
  "message": "Invalid license key"
}

getwebp status --json#

data 对象的形状根据许可证状态而变化。

架构#

// 免费计划(从未激活)
interface StatusFreeResponse {
  success: true
  data: {
    version: string       // 例如 "1.0.1"
    mode: "free"
  }
}
 
// 活跃许可证,在线(来自服务器的完整状态)
interface StatusOnlineResponse {
  success: true
  data: {
    version: string
    mode: "pro"
    licenseKeySuffix: string    // 最后 4 个字符,例如 "A1B2"
    expiresAt: string           // ISO 8601,例如 "2027-04-01T00:00:00.000Z"
    devicesUsed: number
    devicesLimit: number
  }
}
 
// 活跃许可证,服务器缓存(服务器返回数据带有缓存标志)
interface StatusCachedResponse {
  success: true
  data: {
    version: string
    mode: "pro"
    licenseKeySuffix: string
    expiresAt: string
    cached: true                // 指示数据来自本地缓存
  }
}
 
// 令牌存在但服务器无法访问且无状态缓存(仅 JWT 回退)
interface StatusOfflineResponse {
  success: true
  data: {
    version: string
    mode: "pro"
    cached: true
    expiresAt?: string          // ISO 8601(来自 JWT exp 声明)
  }
}

关于 cached 的注意: cached 字段仅在数据来自本地缓存而不是实时服务器响应时存在(并设置为 true)。当服务器成功响应时,cached 被省略,devicesUsed/devicesLimit 被包含。

示例#

免费计划:

{
  "success": true,
  "data": {
    "version": "1.0.1",
    "mode": "free"
  }
}

活跃 Pro 许可证(在线):

{
  "success": true,
  "data": {
    "version": "1.0.1",
    "mode": "pro",
    "licenseKeySuffix": "A1B2",
    "expiresAt": "2027-04-01T00:00:00.000Z",
    "devicesUsed": 1,
    "devicesLimit": 3
  }
}

缓存状态(离线):

{
  "success": true,
  "data": {
    "version": "1.0.1",
    "mode": "pro",
    "licenseKeySuffix": "X9Z7",
    "expiresAt": "2027-04-01T00:00:00.000Z",
    "cached": true
  }
}

仅 JWT 回退(离线,无状态缓存):

{
  "success": true,
  "data": {
    "version": "1.0.1",
    "mode": "pro",
    "cached": true,
    "expiresAt": "2027-04-01T00:00:00.000Z"
  }
}

getwebp logout --json#

使用 --json 时,交互式确认提示会自动跳过(与 --force 的行为相同)。

架构#

// 成功
interface LogoutSuccessResponse {
  success: true
  data: {
    message: "Device unbound. Switched to Free plan."
  }
}
 
// 失败
interface LogoutErrorResponse {
  success: false
  status: "error"
  error: string       // 机器可读的代码(见下表)
  message: string     // 人类可读的描述
}

错误代码#

errormessage可重试
network_unreachableCannot reach server. Retry later or unbind via dashboard.
not_activatedNo active license on this device.
device_not_foundDevice not found. It may have already been unbound.
invalid_tokenToken is invalid or expired.
其他从服务器传入因情况而异

示例#

成功注销:

{
  "success": true,
  "data": {
    "message": "Device unbound. Switched to Free plan."
  }
}

网络失败:

{
  "success": false,
  "status": "error",
  "error": "network_unreachable",
  "message": "Cannot reach server. Retry later or unbind via dashboard."
}

无活跃许可证:

{
  "success": false,
  "status": "error",
  "error": "not_activated",
  "message": "No active license on this device."
}

错误代码摘要#

所有命令中的机器可读错误代码:

代码命令含义可重试
missing_inputconvert未指定输入路径
unknown_errorauth未分类的激活失败因情况而异
network_unreachablelogout无法访问 API 服务器
not_activatedlogout设备上无活跃许可证
device_not_foundlogout设备已解绑
invalid_tokenlogout令牌已过期或已撤销

jq 配方#

CI 脚本和自动化的常见管道。

convert 命令#

# 检查所有转换是否成功
getwebp convert ./images --json | jq '.success'
 
# 获取总字节节省
getwebp convert ./images --json | jq '[.results[] | select(.status == "success") | (.originalSize - .newSize)] | add'
 
# 列出失败的文件
getwebp convert ./images --json | jq '[.results[] | select(.status == "error") | .file]'
 
# 获取平均压缩比率
getwebp convert ./images --json | jq '[.results[] | select(.status == "success") | .savedRatio] | add / length'
 
# 如果任何文件失败则以错误退出
getwebp convert ./images --json | jq -e '.success' > /dev/null
 
# 检查是否击中免费计划限制
getwebp convert ./images --json | jq 'select(.status == "partial") | .data.skipped'
 
# 将文件名和大小提取为 CSV
getwebp convert ./images --json | jq -r '.results[] | select(.status == "success") | [.file, .originalSize, .newSize, .saved] | @csv'

status 命令#

# 获取当前计划
getwebp status --json | jq -r '.data.mode'
 
# 检查许可证是否活跃(非免费)
getwebp status --json | jq '.data.mode != "free"'
 
# 获取过期日期
getwebp status --json | jq -r '.data.expiresAt // "N/A"'
 
# 检查设备使用情况
getwebp status --json | jq '"\(.data.devicesUsed // "?") / \(.data.devicesLimit // "?")"'
 
# 检查状态是否缓存(离线)
getwebp status --json | jq '.data.cached // false'

auth 和 logout#

# 激活并检查结果
getwebp auth XXXX-XXXX-XXXX-XXXX --json | jq -e '.success'
 
# 注销(--json 自动跳过确认)
getwebp logout --json | jq -e '.success'