GetWebP CLI JSON 输出参考
每个 GetWebP CLI 命令的机器可读输出架构。
GetWebP CLI JSON 输出参考
每个 GetWebP CLI 命令的机器可读输出架构。在任何命令上使用 --json 以在 stdout 上发出结构化 JSON(人类消息转到 stderr)。
概述#
每个 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 // 人类可读的描述
}错误代码#
error 值 | message | 可重试 |
|---|---|---|
network_unreachable | Cannot reach server. Retry later or unbind via dashboard. | 是 |
not_activated | No active license on this device. | 否 |
device_not_found | Device not found. It may have already been unbound. | 否 |
invalid_token | Token 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_input | convert | 未指定输入路径 | 否 |
unknown_error | auth | 未分类的激活失败 | 因情况而异 |
network_unreachable | logout | 无法访问 API 服务器 | 是 |
not_activated | logout | 设备上无活跃许可证 | 否 |
device_not_found | logout | 设备已解绑 | 否 |
invalid_token | logout | 令牌已过期或已撤销 | 否 |
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'