文章须自出机杼,成一家风骨。 —— 魏收
近年来,在线语音聊天的用户量持续上升。语音可承载的信息密度比文字图片丰富,同时又比视频更简单;不失为一种抓住新时代用户和实现流量变现的有效途径。在陌生人社交领域,为了满足用户的情感需要、娱乐需求等,晓宇公司也在自己的应用中推出了语音房的功能。
语音房是一款基于一对一的语音电话,语音聊天基础之上的一个多人聊天交流场景;能够同时支撑多人在一个房间的语音互动,这里的语音交互与发语音消息不同,而是类似于多人语音电话,能够实时进行交互沟通。
社交中的语音房最核心的目的一定是促进用户之间的交流,快速提升用户间的关系;语音房能够通过多人同时通话的方式;要比文字,语音消息的方式更富有情感,更直接的让用户之间进行情感交流。可以实现:纯语音聊天、游戏互动、情感电台、线上 KTV 等场景。
语音房功能可以比较契合生活中的 KTV 场景,在实际应用中也确实可以实现线上歌房。
首先需要玩语音房,我们需要创建一个房间,创建房间需要设置房间的一些基本信息,如下图所示:
创建房间的时候可以自定义房间的名称,或者根据系统提供的名称进行随机获取。
在进行房间信息填写完成之后,还需要最后一步就可以创建成功了;点击创建,客户端请求服务端接口房间创建完成。服务端内部主要流程如下:
初始化房间流程中,服务端只是进行存储用户设置的数据及初始化房间麦位信息;以及生成对应房间的靓号及对应的 rtc 频道 id 返回给客户端,客户端进行创建频道信息等操作。
SQL
-- ----------------------------
-- Table structure for room
-- ----------------------------
DROP TABLE IF EXISTS `room`;
CREATE TABLE `room` (
`room_id` bigint(20) NOT NULL,
`app_id` bigint(20) NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '更新时间',
`administrators` varchar(1000) DEFAULT NULL COMMENT '房间管理员信息',
`last_close_time` bigint(20) DEFAULT NULL COMMENT 'unix时间戳, 上次打烊时间',
`last_open_time` bigint(20) DEFAULT NULL COMMENT 'unix时间戳, 上次营业时间',
`mic_mode` varchar(255) NOT NULL COMMENT '上麦模式 (自由上麦/申请上麦模式)',
`roomIcon` varchar(255) DEFAULT NULL COMMENT '房间外部展示图片',
`room_desc` varchar(1000) DEFAULT NULL COMMENT '房间公告',
`room_layout` int(11) DEFAULT 8 COMMENT '房间麦位数量',
`room_name` varchar(255) DEFAULT NULL COMMENT '房间名字',
`room_number` int(11) NOT NULL COMMENT '房间号(过滤靓号)',
`room_source` varchar(255) NOT NULL COMMENT '房间创建的渠道, 也可以认为是房间的归属主体',
`room_type` varchar(255) NOT NULL COMMENT '文字房: ROOM_TYPE_TEXT, 语音房: ROOM_TYPE_VOICE',
`room_status` varchar(255) NOT NULL COMMENT '开启: ROOM_STATUS_OPEN, 关闭: ROOM_STATUS_CLOSE, 被禁: ROOM_STATUS_BANNED',
`room_tag` varchar(255) DEFAULT NULL COMMENT '房间标识',
`room_owner_user_id` bigint(20) DEFAULT NULL COMMENT '房主id',
`room_owner_organization_id` bigint(20) DEFAULT NULL COMMENT '组织id',
`channel_id` bigint(20) DEFAULT NULL COMMENT '房间对应第三方的唯一频道信息',
PRIMARY KEY (`room_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
Java
api: /api/room/room-message //优先根据房间id获取房间信息 (无房间信息,返回默认参数值)
/* 传入参数
(根据调用者id以及房间类型获取是否创建过房间以及房间信息,如果没有创建过该类型房间返回默认参数(图片为创建者头像、房间展示类型为普通房、标签默认为相亲交友房))
房间没有头像默认使用房主在应用中头像
默认展示方式位普通房
默认房间类型为相亲交友 */
Long roomId
api: /api/room/operation-room //操作房间(创建/编辑)
/* 传入参数
房间id(不传为创建,传参为打开)*/
Long roomId
/* (RoomTag 房间标签 ROOM_TAG_FRIEND 相亲交友 ROOM_TAG_TALK 闲聊唠嗑 ROOM_TAG_AUCTION 心动拍卖)*/
String tag
/* 房间名称 */
String name
/* 房间公告 */
String announcement
/* 房间背景图 */
String coverUrl
/* 排麦模式 MIC_MODE_FREEDOM 自由麦 MIC_MODE_QUEUE 排麦 */
String mode
/* 房间展示类型 SECRET_ROOM 私密房 GENERAL_ROOM 普通房间 */
String subType
/* 卡座位置数量 默认8位 范围[4,12] */
Integer boothSize
首先,如下图所示,上麦的模式分为自由模式上麦,以及排队模式上麦;自由模式上麦顾名思义就是只要房间的麦位上没有用户占有,点击之后即可上麦;排队模式上麦则是针对普通用户(管理员/房主除外),无法直接上麦,点击上麦按钮之后会进入到排麦队列中,等待管理员/房主的同意(拍麦队列中只有管理员/房主才有同意的权限)才能够按照上麦的规则进行上麦。
其次,上麦类型分为主动上麦和被动上麦,该概念是从开发角度来区分出来的;用户主动点击上麦操作称为主动上麦;用户被管理员/房主邀请上麦,再由用户点击确认上麦动作为被动上麦。被动上麦的图如下所示:
上麦流程中需要针对用户的权限进行校验,及根据当前房间的模式及业务方选择的策略方式(根据角色位置上麦/根据位置倒序上麦等)进行上麦或者排队操作;最后需要发送房间麦位上的数据发送 rtm 到客户端进行渲染。
-- ----------------------------
-- Table structure for room_booth
-- ----------------------------
DROP TABLE IF EXISTS `room_booth`;
CREATE TABLE `room_booth` (
`room_booth_id` bigint(20) NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '更新时间',
`booth_abilities` varchar(255) NOT NULL COMMENT '主持麦位: BOOTH_ABILITIES_HOST, 普通麦位: BOOTH_ABILITIES_NORMAL',
`booth_index` int(11) NOT NULL COMMENT '卡座位置',
`room_id` bigint(20) NOT NULL,
`user_id` bigint(20) DEFAULT NULL COMMENT '当前在卡座的用户',
`booth_status` varchar(50) DEFAULT NULL COMMENT '卡座声音状态',
`status` varchar(50) DEFAULT NULL COMMENT '数据状态',
PRIMARY KEY (`room_booth_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
麦位的信息是以房间维度,不是用户的维度,业务方调用初始化房间的时候,房间初始化多少个麦为数据一般由业务方来控制。
api: /api/room/set-seat //上麦/排麦(上麦相关的都调用该接口,根据当前房间上麦模式,进行对应逻辑操作)
/* 传入参数
语音房id */
Long roomId
/* 所上的麦位 如果不传 默认按照倒叙上麦,序号从0开始,0表示第一个位置 */
Integer seatNum
api: /api/room/invite-set-seat 将用户抱上麦(该接口由房主/管理员调用用户邀请用户上麦,被邀请的用户将弹出是否同意上麦的弹框)
/* 传入参数
被抱上麦用户id*/
Long userId
/* 语音房id */
Long roomId
允许单人/多人在一个房间频道内进行语音聊天或者进行一些娱乐活动的语音交流玩法。
通过类似于房间内打字互动的方式,服务端与客户端采用一种约定好的格式,实现对应指令的互通,从而达到客户端根据具体指令实现对应的动作。
可以理解为一个语音房对应一个 RTC 频道,在语音房内需要听到声音、发出声音,首先都需要加入到该频道中;类似于双方互相打电话
根据语音房内提供的麦位数量进行加入聊天、退出聊天;没有上麦的用户无法将声音传输入该频道内,使得语音房内其他用户听见。
上麦后的用户提供了开启/关闭自己的麦克风,选择是否将声音传入频道内。
主动行为可以理解为,触发某个动作,用户自己进行处罚即可完成;例如:自由上下麦模式下的上麦/下麦、开麦/闭麦、加入/离开频道等。
被动行为可以理解为,该动作用户无法自己完成,需要通知到相应用户,由另一用户自己去触发才可以完成的动作;例如:抱上麦/抱下麦、禁麦/解除禁麦等。
本次建设语音房功能并非只是简单的实现该能力,而是需要将语音房功能做成一个新的中台模块,便于后续新产品的快速且服务端 0 工作量的接入,从而降低新产品功能上线的成本及提高功能接入的效率。
架构流程客户端需要先调用到业务方,由业务方再调用到语音房服务,语音房服务返回相关的结果以及发送指定模版化的 rtm 通知给客户端;图中涉及到送礼相关功能由金币送礼相关的服务处理。
原因:由于整套逻辑涉及到,客户端、服务端、声网三方,会涉及到服务端的数据与声网的数据不同步问题;幽灵麦问题出现的几个原因主要有:
方案:整体下来,由于麦位上有假用户数据;当房间管理员或者房主发现用户为幽灵麦位的时候,会进行抱下麦,抱下麦会有频率相关的策略,服务端根据策略与声网校验用户与当前频道的关系,不在当前频道进行清理。
目前市面上的各种社交软件有非常多的都具有多人语音聊天的功能,体现出了该功能在陌生人社交领域是比较能够让陌生人之间进行更深体验交流并且快速升温的功能;在完成该功能所具有的基本能力之上,可以继续提升丰富语音房的玩法,可以是游戏,可以是各种具有流程化的互动;相信在未来的一段时间之内,多人语音房间的玩法会得到更多用户的认可。后续,我们也会不断推出语音房的玩法,来丰富用户的体验。