Files
wzdj/lib/api/streamer-studio.ts
卡若 b95d1a94c6 feat(live): 直播与主播工作台 API、云厂商解析与文档调研
- 新增直播评论/上下文/礼物等 API 与回放组件
- 主播开播、云端推流配置与 streamer 校验
- 依赖与 Mongo 集合/种子更新
- 需求与调研文档补充

Made-with: Cursor
2026-04-14 16:24:17 +08:00

82 lines
2.6 KiB
TypeScript

/** 主播工作台:当前登录用户对应的主播档案与开/关播 */
export type StreamerSelfData = {
streamerId: string
name: string
title: string
game: string
isLive: boolean
room: {
id: string
title: string
status: string
pullPlaybackUrl: string
} | null
}
export async function fetchStreamerSelf(): Promise<{ ok: true; data: StreamerSelfData } | { ok: false; status: number; message: string }> {
const res = await fetch("/api/streamer/me", { credentials: "include", cache: "no-store" })
const json = (await res.json().catch(() => ({}))) as {
success?: boolean
data?: StreamerSelfData
message?: string
}
if (!res.ok || !json.success || !json.data) {
return { ok: false, status: res.status, message: json.message ?? "无法加载主播档案" }
}
return { ok: true, data: json.data }
}
export type LiveCloudVendorId = "tencent" | "aliyun" | "qiniu" | "volcengine" | "generic"
export type LiveCloudUrlsPayload = {
vendor: LiveCloudVendorId
configured: boolean
streamName: string
expiresAt: string
setupHint?: string
docs?: { label: string; href: string }[]
push?: { rtmp?: string; srt?: string; note?: string }
play?: { hls?: string; flv?: string; rtmp?: string; note?: string }
}
export async function fetchStreamerCloudUrls(
vendor: LiveCloudVendorId,
ttlSec = 7200,
): Promise<{ ok: true; data: LiveCloudUrlsPayload } | { ok: false; message: string }> {
const res = await fetch(
`/api/streamer/live/cloud?vendor=${encodeURIComponent(vendor)}&ttl=${encodeURIComponent(String(ttlSec))}`,
{ credentials: "include", cache: "no-store" },
)
const json = (await res.json().catch(() => ({}))) as {
success?: boolean
data?: LiveCloudUrlsPayload
message?: string
}
if (!res.ok || !json.success || !json.data) {
return { ok: false, message: json.message ?? "无法获取云厂商地址" }
}
return { ok: true, data: json.data }
}
export async function postStreamerLiveAction(
action: "start" | "stop",
payload?: { title?: string; pullPlaybackUrl?: string | null },
): Promise<{ ok: boolean; message?: string; data?: Record<string, unknown> }> {
const res = await fetch("/api/streamer/live", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "include",
body: JSON.stringify({ action, ...payload }),
})
const json = (await res.json().catch(() => ({}))) as {
success?: boolean
message?: string
data?: Record<string, unknown>
}
if (!res.ok || !json.success) {
return { ok: false, message: json.message ?? "操作失败" }
}
return { ok: true, data: json.data }
}