OGKit

OG 图片工程:尺寸、体积、格式、重定向

  • open-graph
  • og-image
  • 图片工程

有人把发布会链接丢进 WhatsApp:Slack 里卡片完整,WhatsApp 却完全没图。View Source 里 meta 看起来没问题,别的平台 debugger 也还能出图。于是你再导出一张更「清晰」的 1200×630 PNG,再发——WhatsApp 依然空白。

这不是品牌审美问题,而是 图片工程:真实爬虫视角下,og:image 的字节、MIME、跳转跳数与鉴权模型。

故障树:四种不同的「没图」

症状要分枝处理,混在一起会白耗几天。

现象 更可能的分支 先查什么
所有平台都没图 标签 / URL / 可达性 原始 HTML 是否有绝对 https://…og:imagecurl -sI 是否 200
换了文件仍是旧图 缓存 / cache key URL 未变 → 平台沿用上次抓取(见重新抓取;系列缓存篇)
图糊、裁切怪、构图崩 尺寸 / 宽高比 / 声明尺寸 真实像素 ≥ ~1200×630,约 1.91:1,安全区留白
只有某一端失败(常见 WhatsApp / IM) 字节 / 格式 / 跳转 体积、JPEG vs 巨型 PNG、重定向深度、Content-Type 与文件魔数

空白卡片清单会覆盖相对路径、纯 JS 注入标签、爬虫被挡。本文只谈:标签已在时,图片资源本身为何挂

尺寸与宽高比(必要,但不充分)

大型链接预览的行业默认仍是约 1200×630(约 1.91:1)。Facebook / Meta、LinkedIn、X 公布的推荐高度都在这一带(630 / 627 / 628)。工程上当作同一横幅槽位:按 1.91:1 设计,关键人脸与文案放在距边缘约 10% 的安全区内,并接受居中裁切。

<meta property="og:image" content="https://cdn.example.com/share/launch.jpg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="深色背景上的产品控制台截图" />

与扫描器打分一致的经验法则:

如果你的导出只有 400×400 logo,再调 JPEG 质量也撑不起大横幅卡。

体积与格式(IM 静默丢图的主因)

像素讲设计故事;字节决定聊天客户端愿不愿意处理。

@vercel/og、Satori 以及很多「动态 OG」路径默认出 PNG。1200×630 的 PNG 动辄 数百 KB 到数 MB。当网站 hero 没问题,对某些 unfurl 路径却很不友好。

格式 何时合适 何时翻车
JPEG 照片、渐变、产品图;最稳妥的默认分享图 文字 + 扁平 UI 在质量过低时发糊
WebP 同等观感下通常更小(在支持的地方) 客户端支持并不整齐;要最大化兼容时保留 JPEG 路径
PNG 锐利 UI、logo、硬边截图 体积爆炸;聊天预览往往最先丢
GIF 偶发动效 / 遗留 大、能力有限;不适合当默认发布图

字节预算因平台而异,且经常不是官方硬性文档。 在 OGKit 的平台档案里,WhatsApp 建模为约 300KB 硬上限 / 200KB 软目标,来源标注为 实测 / 社区共识——不是官方保证。其他档案允许数 MB 量级(Meta/Facebook 一类约 8MB,若干平台约 5MB),并列出偏好格式。所有硬数字都应视为运维向指引,不是合同。客户端行为变了就重新量。

若分享必须在聊天里稳:

  1. 导出 1200×630
  2. JPEG 质量约 80(或在你能控回退时用 WebP)。
  3. 在意 WhatsApp / IM 时,整体目标 约 100–300KB
  4. 若边缘函数默认出 PNG,写进 og:image 之前先转码

扫描里对应规则:og-image-bytes-exceeds-platform-budget

Content-Type 必须与字节一致

爬虫讨厌说谎的响应头。文件是 JPEG 魔数,却返回 Content-Type: image/png(或反过来),浏览器 <img> 可能仍能显示,部分客户端会直接拒收。

# 爬虫看到的头
curl -sI "https://cdn.example.com/share/launch.jpg" | rg -i 'HTTP/|content-type|content-length|location'

# 可选:对照魔数与扩展名
curl -sL "https://cdn.example.com/share/launch.jpg" | head -c 16 | xxd

稳定规则:og-image-content-type-mismatch。修源站或 CDN 映射,不要只改 meta。

重定向、签名 URL,以及「浏览器正常、分享 403」

浏览器会带 cookie、跟多跳 302、点营销短链。社交图片抓取是未登录、跳数有限的客户端。

常见翻车:

  1. 短链 → 鉴权墙 → CDN
    og:image 指向 https://link.example/x,302 经过追踪再落到签名对象 URL。慢爬虫赶到时签名过期 → 403,空白卡。规则:og-image-forbidden

  2. 跳数过多
    部分爬虫对图片 URL 几乎不跟跳转(即便 HTML 页会跟)。规则:og-image-redirects

  3. Cookie / IP 白名单
    团队 VPN 下正常的 staging CDN,对所有公网 unfurl 失败。

做法:最终、公开、HTTPS、匿名 200、长期或不可变的 CDN 对象 URL 直接写进 og:image。别让爬虫替你跑完重定向图。

# 看跳转链,别无限跟随
curl -sI -L --max-redirs 5 -A "facebookexternalhit/1.1" \
  "https://example.com/og/launch.png"

最终 URL 与 meta 不一致就改 meta;任何一跳要鉴权,就别再用这条链做分享图。

同时保持绝对 HTTPS:og-image-relative-urlog-image-not-https

可执行排查顺序(按序做,硬失败就停)

卡片「有时」没图时,按这个序列走:

  1. 原始 HTML 有标签吗?
    curl -sL URL | rg -i 'og:image'
    没有 → SSR / 注入问题(系列其他篇)。

  2. 绝对 HTTPS?
    相对路径或 http:// → 先修 URL,再谈设计。

  3. 用爬虫 UA 直接 GET 图片
    curl -sI -A "facebookexternalhit/1.1" IMAGE_URL
    期望 200、正确 Content-Type、无鉴权。

  4. 重定向预算
    Location 跳数。图片 URL 最好 零跳

  5. 像素
    解码真实宽高;对照 1200×630 与 1.91:1;若写了声明尺寸就对齐。

  6. 字节
    Content-Length(或实际体积)对比你最在意的最严客户端。聊天权重高时,与其争论理论数 MB 上限,不如重新编码到几百 KB 以内。

  7. 格式诚实
    魔数、Content-Type、扩展名三者一致。

  8. 仅某一平台仍是旧图
    1–7 全绿仍旧 → 缓存,不是图片工程——走官方 rescrape。

扫描器已经写成规则的检查项

规则 id 典型严重级别 抓住什么
og-image-missing error 没有图片字段
og-image-relative-url error 相对路径
og-image-not-https error 非 HTTPS
og-image-forbidden error 401 / 403 / 鉴权
og-image-content-type-mismatch error MIME ≠ 魔数
og-image-redirects warn 图片 URL 会跳转
og-image-dimensions-too-small warn 小于约 1200×630
og-image-aspect-ratio-crop-risk warn 远离 1.91:1
og-image-declared-size-mismatch warn meta 尺寸 ≠ 像素
og-image-bytes-exceeds-platform-budget warn 超过平台字节预算
og-image-alt-missing warn 缺少 alt

完整目录见规则参考;各平台偏好与备注见平台档案

分享图上线清单

  • 专用导出 ≥ 1200×630,约 1.91:1,关键内容在安全区内
  • JPEG(或经过验证的 WebP)压在最严相关字节预算内;聊天场景避免数 MB 的 PNG
  • og:image最终、匿名 200 的 HTTPS CDN URL
  • Content-Type 与魔数一致;若写了 og:image:width / height 必须真实
  • og:image:alt 是简短白话描述
  • 换图后,对仍显示旧图的平台做 rescrape

用线上 URL 试一次

把生产页贴进首页扫描。图片相关发现会按规则 id 拆开——尺寸、预算、重定向、鉴权失败——而不是一张「看起来还行」的模拟卡。用报告驱动上面的排查顺序,在源站修一次,而不是无限重导 PNG。

系列下一篇: 缓存 TTL 与官方 rescrape(为什么图片 URL 正确仍显示上周活动图),以及动态 OG 路径里 PNG 默认值如何再次坑你。