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

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

111 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { LiveCloudUrlsResult, LiveCloudVendor } from "./types"
import { tryTencentFromEnv } from "./tencent"
import { tryAliyunFromEnv } from "./aliyun"
import { tryQiniuFromEnv } from "./qiniu"
const VENDORS: LiveCloudVendor[] = ["tencent", "aliyun", "qiniu", "volcengine", "generic"]
export function parseVendor(v: string | null): LiveCloudVendor | null {
if (!v) return null
const x = v.toLowerCase().trim() as LiveCloudVendor
return VENDORS.includes(x) ? x : null
}
function notConfigured(
vendor: LiveCloudVendor,
streamName: string,
hint: string,
docs: { label: string; href: string }[],
): LiveCloudUrlsResult {
return {
vendor,
configured: false,
streamName,
expiresAt: new Date().toISOString(),
setupHint: hint,
docs,
}
}
export function resolveLiveCloudUrls(
vendor: LiveCloudVendor,
streamName: string,
ttlSeconds: number,
): LiveCloudUrlsResult {
const ttl = Math.min(Math.max(ttlSeconds || 3600, 300), 86400 * 7)
if (vendor === "tencent") {
const r = tryTencentFromEnv(streamName, ttl)
if (r) return r
return notConfigured(
"tencent",
streamName,
"请在服务端环境变量配置TENCENT_LIVE_PUSH_DOMAIN、TENCENT_LIVE_PLAY_DOMAIN、TENCENT_LIVE_APP_NAME可选默认 live、TENCENT_LIVE_PUSH_AUTH_KEY、TENCENT_LIVE_PLAY_AUTH_KEY可同推流密钥。",
[
{ label: "腾讯云直播控制台", href: "https://console.cloud.tencent.com/live" },
{ label: "鉴权计算说明", href: "https://cloud.tencent.com/document/product/267/32735" },
],
)
}
if (vendor === "aliyun") {
const r = tryAliyunFromEnv(streamName, ttl)
if (r) return r
return notConfigured(
"aliyun",
streamName,
"请配置ALIYUN_LIVE_PUSH_DOMAIN、ALIYUN_LIVE_PLAY_DOMAIN、ALIYUN_LIVE_APP_NAME可选、ALIYUN_LIVE_PUSH_PRIVATE_KEY、ALIYUN_LIVE_PLAY_PRIVATE_KEY可同推流 KEY。",
[
{ label: "阿里云视频直播", href: "https://help.aliyun.com/zh/live/user-guide/url-signing" },
{ label: "控制台", href: "https://live.console.aliyun.com/" },
],
)
}
if (vendor === "qiniu") {
const r = tryQiniuFromEnv(streamName, ttl)
if (r) return r
return notConfigured(
"qiniu",
streamName,
"请配置QINIU_LIVE_PUSH_DOMAIN、QINIU_LIVE_HUB、QINIU_LIVE_ACCESS_KEY、QINIU_LIVE_SECRET_KEY可选 QINIU_LIVE_PLAY_DOMAIN。",
[{ label: "七牛 Pili RTMP 地址", href: "https://developer.qiniu.com/pili/2767/the-rtmp-push-flow-address" }],
)
}
if (vendor === "volcengine") {
return notConfigured(
"volcengine",
streamName,
"火山引擎直播推拉流签名与域名策略与控制台配置强相关,本仓库暂未内置生成器。可在控制台生成 OBS 地址后,粘贴到「拉流预览 URL」或自建微服务签名后对接。",
[
{ label: "火山引擎视频直播", href: "https://www.volcengine.com/docs/6469" },
{ label: "控制台", href: "https://console.volcengine.com/live" },
],
)
}
// generic
const base = process.env.LIVE_GENERIC_RTMP_BASE?.trim()
if (base) {
const normalized = base.endsWith("/") ? base : `${base}/`
const rtmp = `${normalized}${streamName}`
return {
vendor: "generic",
configured: true,
streamName,
expiresAt: new Date(Date.now() + ttl * 1000).toISOString(),
docs: [{ label: "OBS 官方文档", href: "https://obsproject.com/wiki/" }],
push: { rtmp, note: "无鉴权模板:仅适合内网/测试;生产请改用腾讯云/阿里云等签名推流。" },
play: { note: "播放地址请从 CDN/云厂商控制台复制后填「拉流预览 URL」。" },
}
}
return notConfigured(
"generic",
streamName,
"可配置 LIVE_GENERIC_RTMP_BASE如 rtmp://push.example.com/live/)生成无鉴权推流前缀;或配置腾讯云/阿里云环境变量。",
[{ label: "腾讯云直播", href: "https://console.cloud.tencent.com/live" }],
)
}