npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kne/fastify-trtc-conference

v1.0.25

Published

基于腾讯云TRTC的Fastify视频会议插件,提供会议创建、成员管理、录像、AI转写等功能

Readme

fastify-trtc-conference

描述

基于腾讯云TRTC的Fastify视频会议插件,提供会议创建、成员管理、录像、AI转写等功能

安装

npm i --save @kne/fastify-trtc-conference

概述

项目概述

fastify-trtc-conference 是一个基于 Fastify 框架的腾讯云 TRTC 视频会议插件。它封装了会议生命周期管理、成员邀请与控制、云端录像、AI 语音转写等核心功能,通过 Fastify 插件机制提供开箱即用的视频会议后端服务。

核心架构与流程

Fastify 应用
  ↓
fastify-trtc-conference(插件注册)
  ↓
  ├─→ @kne/fastify-trtc(TRTC 房间管理、录像、AI转写)
  ├─→ @kne/fastify-shorten(短链接/邀请码签名)
  ├─→ @kne/fastify-namespace(模块命名空间组织)
  └─→ fastify-cron(定时任务:强制结束过期会议)
        ↓
  Controllers(路由层)
    ├─ main.js(用户接口)
    └─ open-api.js(开放API接口)
        ↓
  Services(业务逻辑层)
    └─ main.js
        ↓
  Models(数据模型层)
    ├─ conference(会议)
    ├─ member(参会人)
    └─ ai-transcription-content(AI转写内容)

会议生命周期

创建会议 → 邀请成员 → 加入会议 → 进入会议(获取TRTC签名)
                                      ↓
                              会议进行中(录像/AI转写)
                                      ↓
                    结束会议 ←── 到期自动结束(cron定时检查)
                        ↓
              录像文件回调处理(异步任务轮询)

核心概念详解

会议(Conference)

会议是系统的核心实体,包含名称、开始时间、时长、最大人数等基础信息,以及通过 options 字段存储的扩展配置(录像设置、AI转写、文档等)。

| 属性 | 说明 | | ------------ | -------------------------------------------------------------- | | 会议状态 | 0 正常、1 已结束、2 已取消 | | 主持人 | 会议创建者自动成为主持人,拥有邀请、移除、结束会议等特权 | | 邀请机制 | 支持主持人邀请和创建者邀请两种方式,通过 shorten 签名实现 | | 来源标识 | origin 字段区分会议来源,如 system-createdco-interview |

关键设计:会议使用 shorten(短链接签名)机制进行身份认证,而非传统的 token 认证。成员加入会议后会获得一个包含其身份信息的 shorten 码,用于后续接口认证。

参会人(Member)

参会人隶属于某个会议,包含邮箱、昵称、头像等个人信息。

| 属性 | 说明 | | ------------ | ----------------------- | | isMaster | 标识是否为会议主持人 | | shorten | 参会人的邀请码/身份凭证 |

AI 语音转写(AI Transcription)

基于腾讯云 TRTC 的 AI 语音转写能力,将会议中的语音实时转为文字内容。

| 属性 | 说明 | | ------------ | ------------------------------------------------------ | | 触发条件 | 需在会议 options.setting.speech 中启用 | | 记录方式 | 通过 recordAITranscription 接口逐步追加转写记录 | | 内容存储 | 独立的 aiTranscriptionContent 模型,与会议一对一关联 |

关键设计:AI 转写的启动和停止由主持人控制,转写内容由客户端实时上报并持久化存储。

云端录像

会议支持自动云端录像,录像文件在会议结束后异步获取。

| 属性 | 说明 | | ------------ | -------------------------------------------------- | | 触发方式 | 主持人进入会议时自动开始录像 | | 结束处理 | 会议结束后创建 record-video 异步任务轮询录像结果 | | 文件分类 | 录像文件按参会人 ID 分类存储,同时保留全量文件列表 |

主要特性

| 特性 | 说明 | | ---------------------- | -------------------------------------------------- | | 会议全生命周期管理 | 创建、修改、取消、结束,以及过期自动强制结束 | | 双认证体系 | 用户认证(用户系统)+ shorten 码认证(会议参会人) | | 成员管理 | 邀请、加入、移除,区分主持人与普通成员权限 | | 云端录像 | 自动录像 + 异步任务获取录像文件 | | AI 语音转写 | 实时语音转文字,支持自定义热词和语言 | | 开放 API | 提供独立的 OpenAPI 接口,支持第三方系统集成 | | 定时任务 | 自动检测并结束过期会议,防止资源泄漏 |

使用方法

插件注册

// 在 Fastify 应用中注册插件
await fastify.register(require('@kne/fastify-trtc-conference'), {
  appId: 'your-trtc-appId',
  appSecret: 'your-trtc-appSecret',
  tencentcloud: {
    credential: {
      secretId: 'your-secret-id',
      secretKey: 'your-secret-key'
    },
    cos: {
      region: 'ap-guangzhou',
      bucket: 'your-bucket'
    }
  }
});

基本流程

// 1. 创建会议
const conference = await fetch('/api/conference/create', {
  method: 'POST',
  body: JSON.stringify({
    name: '项目周会',
    startTime: '2026-06-06T10:00:00.000Z',
    duration: 3600,
    maxCount: 10,
    isInvitationAllowed: true,
    members: [{ nickname: '张三', isMaster: true }]
  })
});

// 2. 邀请参会人(主持人邀请)
const invite = await fetch('/api/conference/inviteMember', {
  method: 'POST',
  headers: { 'x-trtc-conference-code': '<shorten>' }
});
// 返回邀请链接 shorten

// 3. 参会人加入会议
const join = await fetch('/api/conference/join', {
  method: 'POST',
  headers: { 'x-trtc-conference-code': '<invite-shorten>' },
  body: JSON.stringify({ nickname: '李四' })
});

// 4. 进入会议(获取 TRTC 签名)
const enter = await fetch('/api/conference/enter', {
  method: 'POST',
  headers: { 'x-trtc-conference-code': '<member-shorten>' }
});
// 返回 { member, conference, sign } - sign 为 TRTC 用户签名

高级配置

// 创建支持录像和AI转写的会议
await fetch('/api/conference/create', {
  method: 'POST',
  body: JSON.stringify({
    name: '面试会议',
    maxCount: 5,
    options: {
      setting: {
        record: true, // 开启云端录像
        speech: true // 开启AI语音转写
      },
      document: [{ url: 'https://example.com/resume.pdf' }],
      documentVisibleAll: true
    }
  })
});

示例

API

配置项

插件注册时传入的配置选项:

| 属性名 | 类型 | 必填 | 默认值 | 说明 | | ---------------------------------- | ---------------- | ---- | ------------------------ | ------------------------------------------------------------------------ | | name | string | 否 | trtcConference | 命名空间名称 | | shortenName | string | 否 | trtcConferenceShorten | shorten 插件命名空间 | | shortenHeaderName | string | 否 | x-trtc-conference-code | shorten 认证请求头名称 | | prefix | string | 否 | /api/conference | 路由前缀 | | dbTableNamePrefix | string | 否 | t_conference_ | 数据库表名前缀 | | trtcName | string | 否 | trtc | TRTC 插件命名空间 | | appId | string | 是 | - | 腾讯云 TRTC 应用 ID | | appSecret | string | 是 | - | 腾讯云 TRTC 应用密钥 | | expire | number | 否 | 10800 | TRTC 签名有效期(秒),默认3小时 | | forceEndExpiredConferencesCronTime | string / false | 否 | */5 * * * * | 强制结束过期会议的 cron 表达式,设为 false 禁用 | | getOpenApiAuthenticate | function | 否 | - | 获取 OpenAPI 认证函数,默认使用 fastify.signature.authenticate.openApi | | getUserAuthenticate | function | 否 | - | 获取用户认证函数,默认使用 fastify.account.authenticate.user | | getUserInfo | function | 否 | - | 从请求中提取用户信息,默认返回 request.userInfo | | getUserModel | function | 否 | - | 获取用户模型,默认使用 fastify.account.models.user | | tencentcloud | object | 是 | - | 腾讯云配置,包含 credential 和 cos 子项 |

关键设计getOpenApiAuthenticategetUserAuthenticate 支持自定义认证逻辑,当未配置时会尝试从已注册的 fastify-signaturefastify-account 插件获取。

接口

用户接口(需用户认证)

| 方法 | 路径 | 说明 | | ---- | ------------------------------------------- | ------------------ | | GET | /api/conference/list | 获取会议列表 | | GET | /api/conference/getAiTranscriptionContent | 获取会议AI转写内容 | | GET | /api/conference/getTrtcRoomEventsSummary | 获取房间事件聚合摘要 | | POST | /api/conference/create | 创建会议 | | POST | /api/conference/save | 修改会议 | | POST | /api/conference/delete | 删除会议 | | GET | /api/conference/getMemberShorten | 获取会议成员短链接 | | POST | /api/conference/inviteMemberFromUser | 用户邀请参会人 |

参会人接口(需 shorten 码认证)

| 方法 | 路径 | 说明 | | ---- | --------------------------------------- | -------------- | | GET | /api/conference/detail | 获取会议信息 | | POST | /api/conference/saveMember | 修改参会人信息 | | POST | /api/conference/inviteMember | 邀请参会人 | | POST | /api/conference/join | 加入会议 | | POST | /api/conference/removeMember | 移除参会人 | | POST | /api/conference/enter | 进入会议 | | POST | /api/conference/startAITranscription | 开启AI转写 | | POST | /api/conference/stopAITranscription | 停止AI转写 | | POST | /api/conference/recordAITranscription | 记录AI转写内容 | | POST | /api/conference/end | 结束会议 | | POST | /api/conference/cancel | 取消会议 |

开放API接口(需 OpenAPI 认证)

| 方法 | 路径 | 说明 | | ---- | ------------------------------------------------- | -------------- | | GET | /api/conference/open-api/health | 健康检查 | | POST | /api/conference/open-api/create | 创建会议 | | GET | /api/conference/open-api/detail | 获取会议信息 | | POST | /api/conference/open-api/cancel | 取消会议 | | GET | /api/conference/open-api/aiTranscriptionContent | 获取AI转写内容 | | GET | /api/conference/open-api/roomEventsSummary | 获取房间事件聚合摘要 |

接口详情

POST /api/conference/create

创建新会议并添加成员。

请求体:

| 属性名 | 类型 | 必填 | 默认值 | 说明 | | ------------------- | --------- | ---- | ------ | ----------------------- | | name | string | 是 | - | 会议名称 | | startTime | string | 否 | - | 开始时间,ISO 8601 格式 | | duration | number | 否 | - | 会议时长(秒) | | isInvitationAllowed | boolean | 否 | - | 是否允许邀请 | | maxCount | number | 否 | - | 最大参会人数 | | members | array | 否 | [] | 成员列表 | | options | object | 否 | - | 会议选项 |

members 子项:

| 属性名 | 类型 | 必填 | 说明 | | -------- | --------- | ---- | ------------ | | name | string | 否 | 用户名称 | | nickname | string | 否 | 用户昵称 | | email | string | 否 | 用户邮箱 | | isMaster | boolean | 否 | 是否是主持人 |

options 子项:

| 属性名 | 类型 | 必填 | 默认值 | 说明 | | ------------------ | --------- | ---- | ------- | ---------------------------------- | | setting | object | 否 | - | TRTC 房间设置(record、speech 等) | | document | array | 否 | - | 会议输入文档 | | documentVisibleAll | boolean | 否 | false | 是否允许所有人查看文档 |

返回:会议对象及成员列表(含 shorten 码)

{
  "id": "1",
  "name": "项目周会",
  "startTime": "2026-06-06T10:00:00.000Z",
  "duration": 3600,
  "status": 0,
  "maxCount": 10,
  "isInvitationAllowed": true,
  "options": {},
  "members": [
    {
      "id": "1",
      "nickname": "张三",
      "isMaster": true,
      "shorten": "abc123"
    }
  ]
}
POST /api/conference/save

修改会议信息。注意:时长和最大人数只能增大不能减小。

请求体:

| 属性名 | 类型 | 必填 | 说明 | | ------------------- | --------- | ---- | ----------------------------- | | id | string | 是 | 会议 ID | | name | string | 是 | 会议名称 | | duration | number | 否 | 会议时长(秒),不可小于原值 | | isInvitationAllowed | boolean | 否 | 是否允许邀请 | | maxCount | number | 否 | 最大参会人数,不可小于原值 | | options | object | 否 | 会议选项(与原 options 合并) |

POST /api/conference/enter

参会人进入会议,获取 TRTC 用户签名。如果是主持人首次进入且会议开启了录像,将自动开始录像。

返回:

{
  "member": {
    "id": "1",
    "nickname": "张三",
    "isMaster": true
  },
  "conference": {
    "id": "1",
    "name": "项目周会",
    "status": 0
  },
  "sign": "userSigString"
}
POST /api/conference/join

通过邀请码加入会议。

请求体:

| 属性名 | 类型 | 必填 | 说明 | | -------- | -------- | ---- | ---------------------------- | | avatar | string | 否 | 头像 | | nickname | string | 否 | 昵称 | | name | string | 否 | 名称(作为 nickname 的别名) | | email | string | 否 | 邮箱 |

返回:

{
  "shorten": "newMemberShortenCode"
}
GET /api/conference/list

获取当前用户的会议列表。

查询参数:

| 属性名 | 类型 | 必填 | 默认值 | 说明 | | ----------- | -------- | ---- | ------ | -------- | | perPage | number | 否 | 20 | 每页数量 | | currentPage | number | 否 | 1 | 当前页码 |

返回:

{
  "pageData": [
    {
      "id": "1",
      "name": "项目周会",
      "members": []
    }
  ],
  "totalCount": 15
}

程序化 API

通过 fastify[options.name].services 访问服务方法:

| 方法签名 | 说明 | | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | | createConference(authenticatePayload, { name, startTime, duration, isInvitationAllowed, origin, maxCount, options, members }) | 创建会议 | | saveConference(authenticatePayload, { id, name, duration, isInvitationAllowed, maxCount, options }) | 修改会议 | | deleteConference(authenticatePayload, { id }) | 删除会议 | | getConferenceList(authenticatePayload, { perPage, currentPage, keyword, date }) | 获取会议列表 | | getConferenceDetail(authenticatePayload) | 获取会议详情(含成员和邀请人) | | getConferenceDetailById(authenticatePayload, { id }) | 按 ID 获取会议详情 | | getAiTranscriptionContentById(authenticatePayload, { id }) | 获取AI转写内容 | | getTrtcRoomEventsSummaryById(authenticatePayload, { id }) | 获取房间事件聚合摘要(用户态) | | getTrtcRoomEventsSummaryForOpenApi(authenticatePayload, { id }) | 获取房间事件聚合摘要(OpenAPI) | | enterConference(authenticatePayload) | 进入会议(获取 TRTC 签名) | | saveMember(authenticatePayload, data) | 修改参会人信息 | | inviteMember(authenticatePayload) | 主持人邀请参会人 | | inviteMemberFromUser(authenticatePayload, { id }) | 创建者邀请参会人 | | getMemberShorten(authenticatePayload, { id }) | 获取成员短链接 | | joinConference(authenticatePayload, data) | 加入会议 | | removeMember(authenticatePayload, { id }) | 移除参会人 | | endConference(authenticatePayload, { id }) | 结束会议 | | cancelConference(authenticatePayload, { id }) | 取消会议 | | forceEndExpiredConferences() | 强制结束所有过期会议 | | startAITranscription(authenticatePayload) | 开启AI转写 | | stopAITranscription(authenticatePayload) | 停止AI转写 | | recordAITranscription(authenticatePayload, { records, messages }) | 记录AI转写内容 | | saveRecordVideo({ conferenceId, roomId, results }) | 保存录像文件信息 |

数据模型

Conference(会议)

| 属性名 | 类型 | 说明 | | ------------------- | --------- | ---------------------------------------------------- | | id | number | 主键,自增 | | name | string | 会议名称 | | startTime | Date | 开始时间 | | duration | number | 会议时长(秒) | | isInvitationAllowed | boolean | 是否允许邀请 | | origin | string | 来源标识,默认 system-created | | maxCount | number | 最大参会人数,默认 2 | | status | number | 会议状态:0 正常,1 已结束,2 已取消,默认 0 | | options | object | 扩展信息(录像、AI转写、文档等配置) | | userId | number | 创建者 ID(外键关联 User 模型) |

关联关系:Conference.hasMany(Member)Conference.belongsTo(User)

Member(参会人)

| 属性名 | 类型 | 说明 | | ------------ | --------- | ------------------- | | id | number | 主键,自增 | | email | string | 邮箱 | | nickname | string | 昵称 | | avatar | string | 头像 | | isMaster | boolean | 是否是会议主持人 | | shorten | string | 进入系统的邀请码 | | conferenceId | number | 所属会议 ID(外键) |

关联关系:Member.belongsTo(Conference)

AiTranscriptionContent(AI转写内容)

| 属性名 | 类型 | 说明 | | ------------ | -------- | ----------------------------- | | id | number | 主键,自增 | | content | array | 语音转文字内容数据,默认 [] | | result | object | 语音转文字内容处理结果 | | status | number | 语音转文字状态,默认 0 | | options | object | 附属信息,默认 {} | | conferenceId | number | 所属会议 ID(外键) |

关联关系:AiTranscriptionContent.belongsTo(Conference)

机制说明

认证机制

系统采用双认证体系:

| 认证类型 | 适用接口 | 认证方式 | 说明 | | -------------- | ------------------------ | ---------------------------------------- | -------------- | | 用户认证 | 创建、修改、删除、列表等 | fastify.account.authenticate.user | 面向会议创建者 | | shorten 码认证 | 进入、邀请、加入等 | fastify-shorten 通过请求头认证 | 面向参会人 | | OpenAPI 认证 | 开放API接口 | fastify.signature.authenticate.openApi | 面向第三方系统 |

会议过期自动结束机制

插件注册后,会通过 fastify-cron 创建定时任务,默认每5分钟执行一次:

  1. 查询所有状态为正常(status=0)的会议
  2. 判断是否已过结束时间(startTime + duration < now
  3. 依次调用 forceEndConference 结束过期会议
  4. 结束流程:停止 AI 转写 → 解散 TRTC 房间 → 停止录像 → 创建录像获取任务 → 更新状态为已结束

录像异步处理机制

会议结束 → 停止录像任务 → 创建 record-video 异步任务
                                      ↓
                         轮询检查录像文件(polling机制)
                                      ↓
                         录像文件就绪 → 获取文件信息
                                      ↓
                         按参会人分类保存到 conference.options.recordFiles

录像文件名格式为 {前缀}_{RoomId}_UserId_s_{UserId}_UserId_e_{结尾},通过 base64 解码获取参会人 ID 进行分类。