@aishorty/ sdk (英语)
官方类型SDK 短长 公开 API
(单位:千美元)https://aishorty.com/v1) (中文(简体) ). 转录媒体,总结录像和网页,
生成字幕,以及民意合成工作——有打出错误,自动重复,
光标 pagination, 以及标准- Webhooks 签名验证 .
- 零运行时间依赖关系. 土著
fetch, (中文(简体) ),node:crypto, (中文(简体) ),AbortSignal。 。 。 . - 节点.js 20. 无害环境管理和共同JS建立完整的申报类型.
- 仅服务器侧 -你的API密钥是个秘密 如果是客户扔出去了 检测浏览器环境.
安装
npm install @aishorty/sdk
# or: pnpm add @aishorty/sdk / yarn add @aishorty/sdk
快速启动
import { Shorty } from '@aishorty/sdk'
const shorty = new Shorty({ apiKey: process.env.SHORTY_API_KEY })
// Start a summary job for a YouTube video…
const job = await shorty.summaries.create({
source: 'youtube',
url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
})
// …then wait for it to finish.
const finished = await shorty.jobs.waitFor(job.job_id)
console.log(finished.status, finished.output)
认证
Shorty 完全接受一个认证形式: a Bearer API 密钥 (单位:千美元)shk_live_…),发送
以下列方式处理每项请求: Authorization: Bearer <key>中创建密钥
操纵台.
// Explicit:
const shorty = new Shorty({ apiKey: 'shk_live_…' })
// Or omit it and the SDK reads process.env.SHORTY_API_KEY:
const shorty = new Shorty()
钥匙是用闭合的——它从未出现在 JSON.stringify(client), (中文(简体) ),
util.inspect(client)或调试日志.
客户选项
| 选项 | 默认 | 说明 |
|---|---|---|
apiKey | process.env.SHORTY_API_KEY | shk_live_… 键。 落地时抛出. |
baseUrl | https://aishorty.com | API 来源( 路径已包含 /v1) (中文(简体) ). |
timeoutMs | 60000 | 潜入暂停. |
maxRetries | 2 | 第一次尝试后再重复. |
fetch | globalThis.fetch | 覆盖获取执行 . |
debug | false | true 日志为 stderr; 函数接收已编辑的日志行. |
dangerouslyAllowBrowser | false | 允许在 window 存在(不建议). |
资源
await shorty.usage.get()
const page = await shorty.articles.list({ limit: 20 })
await shorty.articles.search({ q: 'transformers', article_type: 'YOUTUBE_ARTICLE' })
await shorty.articles.get(articleId)
await shorty.transcriptions.list()
await shorty.transcriptions.get(id)
await shorty.transcriptions.create({ url: 'https://example.com/audio.mp3' })
await shorty.summaries.create({ source: 'url', url: 'https://example.com/post' })
await shorty.summaries.create({ source: 'text', content: 'Long text to summarize…' })
await shorty.subtitles.create({ url: 'https://example.com/clip.mp4', style: 'TIKTOK' })
await shorty.subtitles.download(jobId, { kind: 'srt' })
await shorty.jobs.get(jobId)
await shorty.jobs.waitFor(jobId)
每一个方法都有一个跟踪 opts? 与 { signal, timeoutMs, headers }
(和 idempotencyKey (关于创建方法).
倾斜
list() 返回 a Page标注 for await 走路时 每个 项目
横跨所有页( SDK 遵循您的不透明光标, 重用您的
原始过滤器),或手动页.
// Auto-iterate all items:
for await (const article of await shorty.articles.list({ limit: 50 })) {
console.log(article.id, article.title)
}
// Manual page control:
let page = await shorty.articles.list({ limit: 50 })
while (page) {
console.log(page.data.length, 'items; hasMore =', page.hasMore)
page = (await page.nextPage()) ?? null
if (!page) break
}
光标是 过滤带: 在一个查询下刻出光标不能为 在不同的过滤器上重放 。 SDK从不变异你的配方 拨号,所以这是自动处理的,只是不要把光标交给一个 不同
list()电话.
任务( I) waitFor
写作( A)transcriptions.create, (中文(简体) ), summaries.create, (中文(简体) ), subtitles.create返回时
(单位:千美元) 202 { job_id, status, tracking_url }。通过 jobs.get(id),或使用
方便传票人:
try {
const done = await shorty.jobs.waitFor(job.job_id, {
pollIntervalMs: 2000, // default
timeoutMs: 600_000, // default
// signal: abortController.signal,
})
console.log('done:', done.output)
} catch (err) {
if (err instanceof JobFailedError) {
// The job ended in ERROR/CANCELLED — err.jobError has the reason.
}
if (err instanceof APITimeoutError) {
// The deadline elapsed before the job finished.
}
}
waitFor 是一个 客户端循环 ——不是服务器功能. 它决定了
SUCCESS掷出 JobFailedError 打开 ERROR编号 :CANCELLED,以及 APITimeoutError
在最后期限.
错误
每个非-2xx响应都会丢出一个打出的错误. 课由问题决定
code 首先,返回到 HTTP 状态类,用于任何未知/缺位代码
(所以一个新的服务器代码从不突破) instanceof 处理).
import {
APIError,
AuthenticationError,
PermissionDeniedError,
NotFoundError,
ConflictError,
ValidationError,
RateLimitError,
QuotaExhaustedError,
APIServerError,
APIConnectionError,
APITimeoutError,
} from '@aishorty/sdk'
try {
await shorty.usage.get()
} catch (err) {
if (err instanceof QuotaExhaustedError) {
// Period allowance spent — back off until the next window.
} else if (err instanceof RateLimitError) {
console.log('retry after', err.retryAfterSeconds, 's')
} else if (err instanceof APIError) {
console.log(err.status, err.code, err.title, err.detail, err.requestId)
console.log(err.errors) // field-level validation errors, when present
}
}
每个 APIError 携带 status, (中文(简体) ), code, (中文(简体) ), problemType, (中文(简体) ), title, (中文(简体) ), detail, (中文(简体) ),
requestId, (中文(简体) ), errors?, (中文(简体) ), headers,和(关于429s) retryAfterSeconds编辑
.message 实值 title: detail (request_id) 并且从不包含您的 API 密钥.
错误代码引用
| 代码 | 状态 | SDK 错误类 |
|---|---|---|
unauthorized | 401 (中文(简体) ) | AuthenticationError |
invalid_api_key | 401 (中文(简体) ) | AuthenticationError |
insufficient_scope | 403 (韩语) | PermissionDeniedError |
feature_not_enabled | 403 (韩语) | PermissionDeniedError |
resource_not_found | 404 (韩语) | NotFoundError |
idempotency_conflict | 409个 | ConflictError |
idempotency_in_progress | 409个 | ConflictError |
resource_not_ready | 409个 | ConflictError |
validation_failed | 400个 | ValidationError |
idempotency_key_reused | 422个 | ValidationError |
request_too_large | 413号 | ValidationError |
rate_limited | 429个 | RateLimitError |
quota_exhausted | 429个 | QuotaExhaustedError |
internal_error | 500个 | APIServerError |
service_unavailable | 第503条 | APIServerError |
运输级别失败 APIConnectionError (与 cause)或(或)
APITimeoutError。 。 。 .
检讨和公正
SDK 自动重试瞬间故障至 maxRetries 时间
第一次尝试后( 默认 2) .
复试: 连接出错 ^ 每一次超时 408 • 妇女 429
rate_limited (或 a 个) 429 没有可解析代码)- 500 编号 : 502 编号 : 503 编号 :
504。 。 。 .
从未重复过 : 429 quota_exhausted (支出期间津贴——重试)
有别的吗 4xx 请求您通过自己的程序中止 signal。 。 。 .
备份 : (单位:千美元) Retry-After 标题在出现时是荣耀的(均为三角秒)
和 HTTP 日期表,上限为60s;否则全速回转,
random(0, min(0.5 · 2^attempt, 8)) 秒数.
邮政安全: 一个不安全的 POST 被重审 仅限 当它携带一个
Idempotency-Key。这三种方法是自动生成和再利用
页:1 不变 每次重试都按键,所以重试被复制
服务器侧 。 自己通过 opts.idempotencyKey 做一个调用独能
整个进程重新启动 :
await shorty.summaries.create(
{ source: 'text', content: '…' },
{ idempotencyKey: 'my-stable-key-123' },
)
client.request(...) 邮递员是 没有 重审,除非你通过一个
idempotencyKey 你自己来.
网络呼号
校验进入的短网 verifyWebhookSignature它执行
标准网络呼号 v1计划(HMAC-SHA256,
webhook-id 编号 : webhook-timestamp 编号 : webhook-signature 信头,旋转通过
多个空间分隔的签名,5分钟的回放容受度,恒定时间
页:1.
import { verifyWebhookSignature } from '@aishorty/sdk'
// Express example — note express.raw(), NOT express.json():
app.post('/webhooks/shorty', express.raw({ type: '*/*' }), (req, res) => {
const result = verifyWebhookSignature({
payload: req.body, // the RAW body (Buffer/Uint8Array or string)
headers: req.headers, // Headers object or lowercase-keyed record
secret: process.env.SHORTY_WEBHOOK_SECRET!, // whsec_…
})
if (!result.valid) {
return res.status(400).json({ error: result.reason })
}
// Safe to handle. Parse the body only AFTER verifying.
const event = JSON.parse(Buffer.from(req.body).toString('utf8'))
res.sendStatus(200)
})
仅限生身. 你必须核实 精确字节 你收到了吗? 别
JSON.parse再来..JSON.stringify在核实之前 重排序列化重排序按键并更改白空格, 而白空格 将 失败 核查。 在自动解析JSON的框架中,首先抓取生体 (例如:.express.raw(),或await request.text()在Next.js路线中.
verifyWebhookSignature 返回歧视性结果 :
type WebhookVerifyResult =
| { valid: true }
| {
valid: false
reason:
| 'missing_headers'
| 'malformed_timestamp'
| 'timestamp_out_of_tolerance'
| 'no_matching_signature'
}
许可证
麻省理工学院