/** * 在线播放器的会话存储。 * * 用户在解析面板里选了带弹幕的那一档之后,视频**不再发到群里**,而是登记成一个 * 「播放会话」,再把公网链接回给用户,点开就是播放页。一个会话对应一个目录: * * <数据目录>/koishi-plugin-kkk/player//video.mp4 * <数据目录>/koishi-plugin-kkk/player//danmaku.json * * 会话本身放在内存的 Map 里,同时把索引写一份 sessions.json —— 宿主重启后 * 还没过期的会话照常能看,不会因为重启就全部 404。到期由定时器统一清理 * (删视频 + 删弹幕 + 删索引),所以链接是有寿命的。 * * 注意:本文件**不要**在模块顶层 import karin 的业务模块(Common / Config 之类), * 那些模块在 import 时就会去读兼容层运行时状态,而插件入口是 * bindRuntime 之前就 require 本模块的,顶层引入会直接抛异常把插件带崩。 * 需要用到它们时一律在函数里动态 import。 */ import crypto from 'node:crypto' import fs from 'node:fs' import path from 'node:path' import { logger } from 'node-karin' /** 播放页里的一条弹幕(已折算成统一格式) */ export interface PlayerDanmakuItem { /** 出现时间(毫秒) */ time: number /** 类型:1/2/3 滚动,4 底部,5 顶部 */ mode: number /** 字号:18 小 / 25 标准 / 36 大 */ size: number /** 颜色(十进制 RGB888) */ color: number /** 内容 */ text: string } /** 一个播放会话 */ export interface PlayerSession { /** 播放令牌(链接里的那一段) */ token: string /** 作品标题(播放页显示用) */ title: string /** 来源平台:bilibili / douyin */ platform: string /** 会话目录 */ dir: string /** 视频文件绝对路径 */ filePath: string /** 视频大小(字节) */ sizeBytes: number /** * **单独的音轨文件**(可选)。 * * 用户要求「默认不要服务器合并音频,浏览器里同时播放就行」:B站是分离的音视频流, * 以前要先用 ffmpeg 合成一条 mp4(慢、吃 CPU),现在**默认不合成** —— * 视频流和音频流各存一份,播放页用 `