跳转到内容

谱面图片

接口通过 Cassiopeia 静态概览 renderer 呈现已发布谱面。Handler支持SVG和已注册PNG rasterizer,PNG部署包含匹配Fontsource manifest/files;下方应用显示实际公开Worker响应。

Terminal window
curl --fail-with-body \
'https://haneoka.org/api/v1/songs/100070/charts/expert/image.svg?server=intl&locale=en&height=720&download=1' \
-o chart.svg

把后缀换成 png 得到 PNG。显式形式为 /api/v1/servers/{server}/songs/{songId}/charts/{difficulty}/image.{format}。两者固定读取当前资料,不接受 release。难度应来自歌曲 DTO 已公布的 difficulty。

参数值含义
server活动 slug,alias 默认 intl资料服务器
difficultyeasy/normal/hard/expert/special/master路径参数,歌曲必须提供该难度
localeja/en/zh-TW/zh-CN/ko图中文字,省略时协商 Accept-Language
height360–1440 整数,默认720单个谱面段高度,不含页眉
download1/0,默认1attachment 或 inline
formatsvg/png文件后缀与 MIME

重复或空参数返回400。输入和输出受渲染预算约束,超预算返回413。

最终图片包含页眉和整曲所需段数;提高段高会影响段数及最终宽度。以 X-Haneoka-Image-Width/Height 为图片占位尺寸,与 SVG width/height 或 PNG IHDR 一致。height query 不是最终画布高度。

响应还包含 Content-Type、Content-Length、Content-Disposition、Content-Language、ETag、X-Haneoka-Server/Release-Id/Chart-Renderer。GET 返回图片,HEAD 只返回头,If-None-Match 可得到304且不带 Content-Length。公开端点支持匿名 CORS、OPTIONS204 和不支持方法的405/Allow。

const url = "https://haneoka.org/api/v1/songs/100070/charts/expert/image.png?locale=en&download=0";
const response = await fetch(url, { credentials: "omit" });
if (!response.ok) {
const failure = await response.json();
throw new Error(`${response.status}: ${failure.error.code}`);
}
const width = Number(response.headers.get("X-Haneoka-Image-Width"));
const height = Number(response.headers.get("X-Haneoka-Image-Height"));
const imageUrl = URL.createObjectURL(await response.blob());
console.log(width, height, imageUrl);
// 给 img 设置宽高与 src,卸载时 URL.revokeObjectURL(imageUrl)。

错误为 error.code/message/requestId,带 X-Request-Id 和 no-store。参数错误400,歌曲/难度/谱面缺失404,格式406,输入/渲染预算413,光栅失败502,当前发布不可用503。具体 code 见 OpenAPI。PNG 字体缺失或无效为 chart_image_failed,字体预算超限为 chart_render_budget;未接 rasterizer 的部署可返回501 png_renderer_unavailable。保留 requestId,根据参数或部署原因修复后重试。

修改server/song/difficulty/format/locale/段高/download,选择GET/HEAD/OPTIONS。点击才请求真实端点,成功GET按真实尺寸预览并下载同一响应bytes;错误显示真实status/body,不用本地图片替代不可用服务。

修改 JSON 再发送请求。响应显示真实状态、尺寸与缓存头;GET 成功后预览图片并提供原响应下载。

语言

正在准备示例…

查看实际示例代码

scoped选显式server路径,apiBase为兼容API,acceptLanguage/ifNoneMatch为header;ifNoneMatch:$last使用上一ETag,这些是应用transport字段。HEAD/OPTIONS/304无新图正文,正式cache应复用旧表示,检查器显示头。清理/替换/退出revoke BlobURL,不import GPU/SDK或预加载图片。

GET/HEAD alias /api/v1/songs/{songId}/charts/{difficulty}/image.{format},可选server;或 /api/v1/servers/{server}/songs/{songId}/charts/{difficulty}/image.{format}。公开无需账号;OPTIONS先204,不读源,其他方法405/Allow。

参数必填/默认校验/作用
songId必填string路径1–256位,首字母数字,其余可 . _ : ~ -,单段编码;非法/缺404 song_not_found。
difficulty必填小写路径easy/normal/hard/expert/special/master且DTO有,缺404 difficulty_not_found。
format必填后缀svg/png小写;匹配但不支持的小写后缀406,坏route可404。
serverscoped必填,alias intl活动1–40位小写字母数字/连字符,首尾字母数字。alias重复400 invalid_server,坏/未知404;scopedquery需匹配path。
locale可选,协商ja/en/zh-TW/zh-CN/ko,空/重复/不支持400 invalid_locale,与server独立。
height可选7201–4位十进制整数360–1440,空/小数/越界/重复400 invalid_height;单段不含header。
download可选1仅0/1一次,inline/attachment,空/其它/重复400 invalid_download。
release不支持任何值400 release_not_supported,current读取。

没有width/title/band/noteSpeed/jacket覆盖参数,来自实际song/score。query大小写精确;非空body400 body_not_allowed。

header方向/默认作用
Accept-Language可选request无locale时BCP47协商。
If-None-Match可选request强/弱etag或*匹配304,无Content-Length。
Content-TyperesponseSVGUTF8/PNG,错误JSON。
Content-Length200/HEAD真实编码bytes,304无。
Content-Dispositionresponse默认attachment或inline,文件名含server/song/difficulty/locale。
Content-Languageresponse选定语言。
ETagresponse表示bytes+server/release/song/locale/renderer identity。
X-Haneoka-Serverresponseregistry。
X-Haneoka-Release-Idresponse真实current版本。
X-Haneoka-Chart-Rendererresponserenderer版本。
X-Haneoka-Image-Width/Heightresponse含header/panels的最终画布。
Cache-Controlsuccess public/max-age300/must-revalidate错误no-store。
VaryAccept-Language协商缓存。
X-Request-Iddispatcher错误body也有requestId。
Allow405GET/HEAD/OPTIONS。

匿名CORS origin*,允许上述方法和Content-Type/Accept/Accept-Language/If-None-Match;暴露Disposition/Length、renderer/release/server/尺寸/ETag。浏览器只读允许暴露的头,header读不到时保留错误body.requestId。HEAD无正文,Range不是图片API字段,读取全图或ETag复验。

chart2MiB、可选jacket1MiB;缺/不支持jacket可省略仍渲染。最多256panels、12000000pixels、SVG8MiB;PNG验证signature/IHDR/尺寸及8MiB。预算不是query开关,PNG部署包括rasterizer和Fontsource manifest/files。

status/code原因恢复
400 invalid_height/locale/download/server坏/空/重复改参数。
400 release_not_supported/body_not_allowedrelease/bodycurrent无body读取。
404 server/song/difficulty/chart_not_found无可用源从catalog选已有。
405 method_not_allowed非readGET/HEAD/OPTIONS。
406 format_not_supported匹配但不支持后缀svg/png。
413 chart_too_large/chart_render_budgetinput/font/output预算选较小可用谱面/报告,不同参重复超限无效。
501 png_renderer_unavailable未部署PNG器SVG或部署。
502 chart_path_invalid/chart_invalid/release_invalid坏identity/path/score保留requestId报告。
502 png_invalid/chart_image_failedsignature/尺寸/font失败修部署/字体。
503 release_unavailable无current有界backoff重试。

公开dispatcher error为code/message/requestId,带X-Request-Id/no-store。fetch/CORS/abort在此envelope之前,独立展示。是否上线以实际Worker响应为准,页面示例记录它,不把docs部署当API部署。