UNPKG

@bililive-tools/douyin-recorder

Version:
98 lines (97 loc) 2.96 kB
import { getRoomInfo, selectRandomAPI } from "./douyin_api.js"; import { globalLoadBalancer } from "./loadBalancer/loadBalancer.js"; export async function getInfo(channelId, opts) { let info; // 如果使用 balance 模式,使用负载均衡器 if (opts?.api === "balance") { info = await globalLoadBalancer.callWithLoadBalance(channelId, { auth: opts.auth, uid: opts.uid, }); } else { info = await getRoomInfo(channelId, opts ?? {}); } const startTime = new Date(); return { living: info.living, owner: info.owner, title: info.title, roomId: info.roomId, avatar: info.avatar, cover: info.cover, liveId: info.liveId, uid: info.uid, api: info.api, liveStartTime: startTime, recordStartTime: startTime, area: info.area ?? "", }; } export async function getStream(opts) { let api = opts.api ?? "web"; if (api === "userHTML") { // userHTML 接口只能用于状态检测 api = "web"; } else if (api === "random") { api = selectRandomAPI(["userHTML"]); } const info = await getRoomInfo(opts.channelId, { doubleScreen: opts.doubleScreen ?? true, auth: opts.auth, api: api, uid: opts.uid, }); if (!info.living) { throw new Error("It must be called getStream when living"); } // 抖音为自动cdn,所以指定选择第一个 const sources = info.sources[0]; const formatPriorities = opts.formatPriorities || ["flv", "hls"]; // 查找指定质量的流 let targetStream = sources.streams.find((s) => s.quality === opts.quality); let qualityName = targetStream?.name ?? "未知"; if (!targetStream && opts.strictQuality) { throw new Error("Can not get expect quality because of strictQuality"); } // 如果找不到指定质量的流,按照流顺序选择第一个可用的流 if (!targetStream) { targetStream = sources.streams.find((stream) => stream.flv || stream.hls); if (targetStream) { qualityName = targetStream.name; } } if (!targetStream) { throw new Error("未找到对应的流"); } // 根据格式优先级选择 URL let url; for (const format of formatPriorities) { url = targetStream[format]; if (url) break; } if (!url) { throw new Error("未找到对应的流"); } let onlyAudio = false; try { const urlObj = new URL(url); if (urlObj.searchParams.get("only_audio") == "1") { onlyAudio = true; } } catch (error) { console.warn("解析流 URL 失败", error); } return { ...info, currentStream: { name: qualityName, source: "自动", url: url, onlyAudio, }, }; }