Android

最近更新时间:2026-01-16 20:16:32

我的收藏
Karaoke 组件是 TUILiveKit 的标准化 K 歌功能模块,可快速集成至视频直播语音房场景。组件支持本地与在线音乐接入,内置歌词滚动、音准检测、实时打分及多种音效设置。为用户提供低延迟、高保真的实时 K 歌体验。

功能概览

多端人声和音乐同步对齐: 基于 NTP 时间戳对齐技术,确保跨设备间人声与伴奏的精准同步,有效解决网络抖动带来的音画不同步问题。
实时打分与音准曲线:曲库歌曲可实时展示标准音高与用户个人音准曲线,唱歌得分同步广播给全房观众;本地导入歌曲暂不支持打分和音准显示。
毫秒级歌词滚动:支持 VTT、LRC 格式歌词,随音乐进度精准滚动。
多样化音乐源支持: 全面支持在线曲库点播与本地音乐(MP3/M4A)上传和播放。


快速接入

步骤1:开通服务

参考 开通服务 文档开通「体验版」或「大规模直播版」套餐。

步骤2:代码集成

参考 准备工作 接入 TUILiveKit

步骤3:集成 KTV 功能

布局选择与接入

我们提供了两种不同交互的布局模式,您可以根据直播间的业务侧重点(例如:专业 K 歌房、社交娱乐房)选择最合适的集成方案。
标准 KTV 模式
悬浮球模式 KTV 接入
该模式主要通过 KaraokeControlView 实现,视图通常固定置于房间顶部。它提供了完整的歌词滚动、音高曲线评分以及播放控制功能。您可以根据业务需求,通过 XML 声明或代码动态构建的方式将该组件集成到应用中。

方式1:通过 XML 布局文件集成(推荐)
适用于 UI 布局相对固定的场景。通过在布局 XML 中直接定义,可以精确控制其在房间顶部的层次关系。
<io.trtc.tuikit.atomicx.karaoke.view.KaraokeControlView
android:id="@+id/karaoke_control_view"
android:layout_width="match_parent"
android:layout_height="170dp"
android:layout_marginTop="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
方式2:通过代码动态构建
对于使用 Kotlin 语言开发的工程,集成逻辑如下。
import android.view.ViewGroup
import io.trtc.tuikit.atomicx.karaoke.view.KaraokeControlView

fun initKaraokeView(container: ViewGroup, roomId: String, isOwner: Boolean) {
// 1. 实例化组件
val karaokeView = KaraokeControlView(context)

// 3. 设置布局参数并添加到容器
// 标准模式通常占据屏幕顶部固定高度
val layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
500 // 对应高度约 170dp
)
container.addView(karaokeView, layoutParams)
}
该模式主要通过 KaraokeFloatingView 实现,支持手动拖拽。提供了歌词滚动、音准打分曲线及播放控制功能。您可以根据业务需求,通过 XML 声明或代码动态构建的方式将该组件集成到应用中。

方式1:通过 XML 布局文件集成
这是最推荐的集成方式,适用于布局相对固定的场景。通过在布局 XML 中直接定义,可以方便地配合 ConstraintLayout 等容器进行 UI 适配。
<io.trtc.tuikit.atomicx.karaoke.view.KaraokeFloatingView
android:id="@+id/karaoke_floating_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
方式2:通过代码动态构建
对于使用 Kotlin 语言开发的工程,集成逻辑如下。我们建议将 KaraokeFloatingView 添加到页面的根布局中,以确保其悬浮层级。
import android.view.ViewGroup
import android.widget.FrameLayout
import io.trtc.tuikit.atomicx.karaoke.view.KaraokeFloatingView

fun setupKaraokeFloatingView(container: ViewGroup, roomId: String, isOwner: Boolean) {
// 1. 实例化组件
val floatingView = KaraokeFloatingView(context)

// 2. 将组件挂载到父容器并设置悬浮模式
// FloatingMode.RIGHT_HALF_MOVE 表示允许在屏幕右侧半屏区域内上下拖动
floatingView.attachAsFloating(container, KaraokeFloatingView.FloatingMode.RIGHT_HALF_MOVE)
}

添加音乐

Karaoke 组件提供了灵活的数据源适配机制,支持集成本地音乐资源商业版权曲库。您可以通过继承 MusicSourceService 类来实现不同场景下的音乐加载逻辑。

场景一:添加本地音乐
若您希望播放应用内置或本地沙盒中的音乐文件,请在您的工程中新建 KaraokeLocalSource.kt 文件。该类继承自 MusicSourceService 基类。在本地音乐模式下,KaraokeLocalSource 核心承担以下两项职责:
1. 管理音乐列表:负责检索本地资源(例如 Assets 或沙盒路径),并将其映射为组件可识别的 MusicInfo 标准列表。
2. 实现播放鉴权:KTV 场景下需要合唱机器人进入房间协同播放音乐,因此该类需负责获取 UserSig 签名,以确保播放流程的鉴权通过。
说明:
实时评分与音准检测功能需配合版权曲库的标准音轨数据实现。因此,本地音乐目前仅支持歌词展示与同步播放,不支持打分和计算用户的实时音准。
package io.trtc.tuikit.atomicx.karaoke.store

import android.content.Context
import androidx.core.content.ContextCompat
import com.tencent.qcloud.tuikit.debug.GenerateTestUserSig
import io.trtc.tuikit.atomicx.karaoke.store.utils.MusicInfo
import java.io.File

/**
* 本地音乐数据源实现类
* 负责加载本地存储的演示歌曲,并处理基础鉴权逻辑
*/
class KaraokeLocalSource(private val context: Context) : MusicSourceService() {

/**
* 步骤 1:获取本地歌曲列表
* 将本地文件路径封装为 MusicInfo 对象并返回
*/
override fun getSongList(callback: GetSongListCallBack) {
// 1. 获取本地存储的绝对路径。
// 确保在调用此方法前,相关 mp3/vtt 文件已通过 copyAssetToFile 拷贝至该路径。
val localPath = ContextCompat.getExternalFilesDirs(context, null)[0].absolutePath + File.separator

// 2. 配置 MusicInfo 核心字段。
// musicId: 歌曲唯一标识;musicName: 歌曲名称;artist: 歌手名列表。
val demoMusic = MusicInfo().apply {
musicId = " local_demo_01" // LiveKit中,本地音乐的musicId前缀是local_demo.
musicName = "后来"
artist = "刘若英"
lyricUrl = "lyricUrl.vtt" // 对应歌词文件的 URL
originalUrl = "originalUrl.mp3" // 对应原唱文件的 URL
accompanyUrl = "accompanyUrl.mp3" // 对应伴奏文件的 URL
}

// 4. 构建列表并通过回调返回。
val musicList = arrayListOf(demoMusic)
callback.onSuccess(musicList)
}

/**
* 步骤 2:生成用户签名
* 为当前用户生成合法的业务签名,用于初始化组件和鉴权
*/
override fun generateUserSig(userId: String, callback: ActionCallback) {
// 调用测试环境工具生成 UserSig
val userSig = GenerateTestUserSig.genTestUserSig(userId)
if (userSig.isNotEmpty()) {
callback.onSuccess(userSig)
} else {
callback.onError(-1, "Generate UserSig failed")
}
}
}
场景二:添加曲库音乐
如果您已购买版权曲库服务(例如音速达曲库),可以通过继承 MusicSourceService 实现云端资源的集成。请在工程中新建 KaraokeOnlineSource.kt 文件。在曲库模式下,该类核心承担以下三项职责:
1. 管理云端列表:对接业务后台或腾讯云接口,获取在线歌曲元数据并映射为组件可识别的 MusicInfo 标准列表。
2. 实现播放鉴权:KTV 场景下需要合唱机器人进入房间协同播放。该职责负责获取合法的 UserSig 签名,确保机器人具备进房播放权限。
3. 获取播放凭证:针对受版权保护的数字音乐,需根据 musicId 向服务器换取 playTokenLicense 授权,这是在线流媒体正常解密播放的核心凭证。

package io.trtc.tuikit.atomicx.karaoke.store

import io.trtc.tuikit.atomicx.karaoke.store.utils.MusicInfo

/**
* 在线曲库数据源实现类
* 职责:1. 检索云端歌曲;2. 提供机器人进房鉴权;3. 获取版权播放凭证
*/
class KaraokeOnlineSource : MusicSourceService() {

/**
* 职责一:获取云端歌曲列表
* 此处通常调用您的业务后端接口,将返回的 JSON 解析为 MusicInfo 列表
*/
override fun getSongList(callback: GetSongListCallBack) {
// 示例:此处模拟网络请求成功后构建的在线歌曲对象
val onlineMusic = MusicInfo().apply {
musicId = "online_id_1001" // 云端歌曲唯一 ID
musicName = "在线歌曲示例"
artist = mutableListOf("歌手名")
coverUrl = "https://example.com/cover.jpg" // 在线封面 URL
}
callback.onSuccess(arrayListOf(onlineMusic))
}

/**
* 职责二:鉴权播放
* 建议由您的业务后端生成 UserSig,确保合唱机器人安全入会
*/
override fun generateUserSig(userId: String, callback: ActionCallback) {
// 示例:此处应发起网络请求从您的服务器获取 UserSig
val userSig = "YOUR_SERVER_GENERATED_USERSIG"
callback.onSuccess(userSig)
}

/**
* 职责三:获取播放凭证 (在线模式核心)
* 根据 musicId 获取播放 Token、License 等版权信息
*/
override fun queryPlayToken(musicId: String, userId: String, callback: QueryPlayTokenCallBack) {
// 示例:此处应向服务器请求该音乐的播放许可
val playToken = "YOUR_PLAY_TOKEN"
val licenseKey = "YOUR_LICENSE_KEY"
val licenseUrl = "YOUR_LICENSE_URL"
// 验证成功后返回凭证
callback.onSuccess(musicId, playToken, licenseKey, licenseUrl)
}
}

核心 UI 组件

歌词组件(LyricView)

LyricViewKaraoke 组件中负责文本表现的核心视图。它能够根据音乐播放进度,实现毫秒级的歌词平滑滚动与逐字颜色填充,为演唱者提供精准的节奏指引。

组件能力:
1. 高精度对齐:支持 VTT、LRC 等标准歌词格式,确保歌词的逐字染色进度与伴奏精准同步。
2. 自适应排版:内置长句拆行与缩减逻辑,当歌词过长时会自动进行排版优化,防止 UI 溢出。
3. 双行渲染模式:默认采用“当前行+下一行”的双行显示策略,帮助演唱者提前预判歌词内容。

自定义歌词 UI 样式

为了适配不同风格的直播间布局,LyricView 提供了丰富的自定义接口。您无需修改组件源码,通过简单的 API 调用即可调整歌词的颜色、大小及对齐方式。
1. 设置歌词颜色。您可以分别设置第一行(当前行)的两种状态颜色,以及第二行(等待行)的颜色。
// 设置歌词颜色
lyricView.setLyricColors(
currentLineNormalColor = Color.WHITE, // 第一行:尚未唱到的底色
currentLineHighlightedColor = Color.BLUE, // 第一行:已经唱到的高亮色
nextLineColor = Color.GRAY // 第二行:等待演唱行的颜色
)
2. 调整字体与间距您可以为“当前正在演唱行”和“后续等待行”分别设置不同的字体大小,以增强视觉层级感。
// 设置歌词字体:参数1为高亮行大小,参数2为次行大小 (单位:sp)
lyricView.setLyricTextSize(18f, 12f)
3. 变换对齐方式根据 UI 设计需求,您可以灵活切换歌词的水平对齐模式。
// 支持居中对齐 (LyricAlign.CENTER) 或 居右对齐 (LyricAlign.RIGHT)
lyricView.setLyricAlign(LyricAlign.CENTER)
4. 实时驱动进度LyricView 的状态由进度数据驱动。您只需将音乐播放器返回的毫秒级进度注入组件,即可实现丝滑的滚动效果。
// 在进度监听器中调用,驱动歌词染色与滚动
lyricView.setPlayProgress(currentProgressMs)

音准组件 (PitchView)

PitchView 是 Karaoke 组件中实现专业级打分功能的核心视图。它通过波形化的视觉反馈,将演唱者的实时音高(Pitch)与歌曲标准音轨进行对比,为用户提供极具趣味性与挑战性的“音准校对”体验。

组件能力:
1. 实时音准反馈:毫秒级呈现演唱者的音高动态,通过移动的“音准粒子”实时反馈音准偏移情况。
2. 标准基准线对比:自动加载歌曲的官方标准音高数据,形成可视化的音高参考矩形块,方便演唱者找准音调。
3. 视觉命中反馈:当演唱音高进入标准范围内时,组件会自动触发高亮染色与“蝴蝶点缀”等动效,强化演唱成就感。
4. 多端状态同步:支持将房主的演唱得分与音高曲线实时广播给全房观众,实现跨端的视觉同步。

自定义音准 UI 样式

PitchView 提供了深度的自定义配置接口,允许开发者根据直播间的视觉调性,调整曲线的外观、命中判定规则以及动画效果。
1. 开启/关闭打分模式:您可以动态控制打分功能的开关。关闭后,组件将不再显示评分标签。
// 开启打分显示逻辑
pitchView.setScoringEnabled(true)
2. 设置标准音轨数据:在歌曲开始播放前,需要将标准音高序列注入组件,用于生成参考背景。pitchList 数据来自合唱回调 onChorusMusicLoadSucceed 中的 pitchList 字段。
// 注入来自 TXChorusMusicPlayer 的标准音高列表
pitchView.setPitchList(pitchList)
3. 实时驱动播放进度:PitchView 需要实时进度来驱动音轨的横向滚动。
// 在进度监听器中调用,驱动音轨随音乐进度平滑滚动
pitchView.setPlayProgress(currentProgressMs)
4. 注入演唱者当前音高:将人声检测到的实时音高注入组件,用于绘制当前演唱的粒子位置。
// 注入演唱者当前的实时音高值(通常为 0-100)
pitchView.setUserPitch(userPitch)
5. 实时更新分数:显示当打分逻辑计算出最新得分时,可以调用此接口更新界面顶部的分数标签。
// 设置当前实时得分,视图会自动更新分数的冒泡显示
pitchView.setScore(85)
6. 配置核心颜色:通过代码接口,您可以自定义标准音轨、命中高亮以及背景分割线的颜色。
// 注:PitchView 内部默认集成了以下视觉属性的配置逻辑
// 您可以通过 XML 或自定义属性扩展来调整:
// 标准音轨色:lineColor (默认灰色)
// 命中填充色:highlightColor (默认红色)
// 引导粒子色:dotColor (默认白色)

API 参考

合唱相关

TXChorusMusicPlayer 是合唱功能的核心控制单元,封装在 TRTC SDK 中。该组件基于 NTP 时间戳对齐技术,确保跨设备间人声与伴奏的精准同步,并提供了完整的音乐播放控制能力 。
注意:
TXChorusMusicPlayer 主要负责音频流的加载、同步与播放控制 。音准检测与实时评分功能是由版权曲库实现的。

核心控制方法

方法名
说明
调用权限
start()
开始播放合唱音乐。
仅限主唱
stop()
停止合唱播放。
仅限主唱
pause()
暂停合唱播放。
仅限主唱
resume()
恢复合唱播放。
仅限主唱
seek(long progressMs)
跳转到指定播放进度。
仅限主唱
setChorusRole(ChorusRole role, TRTCParams params)
设置合唱角色(例如主唱、副唱、观众等)。
所有角色
switchMusicTrack(MusicTrack track)
切换原唱与伴奏。主唱设置会同步影响观众。
主唱/副唱

音乐加载与配置

方法名
说明
loadMusic(ChorusMusicParams params)
加载版权曲库(例如音速达)音乐。
loadExternalMusic(ExternalParams params)
加载本地或自定义 URL 音乐文件。
setPublishVolume(int volume)
设置主唱推流到远端的 BGM 音量 (0-100)。
setPlayoutVolume(int volume)
设置本地播放的 BGM 音量 (0-100)。

事件回调 (ITXChorusPlayerListener)

回调方法
触发时机
onChorusStarted()
合唱正式开始播放时触发。
onMusicProgressUpdated(long progress, long duration)
毫秒级播放进度更新。
onVoicePitchUpdated(int pitch, boolean hasVoice, long progressMs)
演唱音高实时更新(-1 表示间奏/无人声)。
onVoiceScoreUpdated(int current, int average)
每一句歌词唱完后的实时得分反馈。
onChorusRequireLoadMusic(String musicId)
主唱发起点播后,通知其他角色同步加载歌曲。

点歌台相关

TUISongListManager 负责管理直播间的点唱队列,包括添加歌曲、删除歌曲、歌曲置顶及自动切歌逻辑。
方法名
说明
addSong(List<SongInfo> list, callback)
将歌曲添加至待播列表。
removeSong(List<String> ids, callback)
从队列中移除指定歌曲。
setNextSong(String songId, callback)
置顶某首歌曲,使其成为下一首播放的曲目。
playNextSong(callback)
立即切换至下一首歌曲。
getWaitingList(cursor, count, callback)
分页获取当前待播列表。
getPlayedList(cursor, count, callback)
分页获取已播放的历史列表。

常见问题

是否有推荐的曲库供应商?

国内建议优先选择音速达曲库。它具备丰富的正版曲目授权,且与组件的音准打分系统深度适配。您可以访问 音速达帮助中心 获取更多接入支持。

为什么演唱时没有音高曲线或实时评分?

音准检测与打分功能高度依赖版权曲库(例如音速达)提供的标准音高基准文件。如果您使用的是本地音乐(External Source),由于缺少标准的参考数据,系统将无法触发 onVoicePitchUpdated(音高更新)和 onVoiceScoreUpdated(分数更新)回调。

本地音乐加载失败,报错“Music load failed (-5)”如何处理?

请确认传入 loadExternalMusic 的文件路径是否合法且具备读取权限。如果音乐资源存放在工程的 Assets 目录中,必须先将其拷贝至应用的沙盒路径(例如 getExternalFilesDir)下,方可被底层播放引擎成功识别并加载。

如何解决合唱时人声被伴奏掩盖的问题?

您可以使用 setPublishVolume 接口动态调整推流中伴奏的音量(建议范围 30-60),同时通过 TRTC SDK 的 setAudioCaptureVolume 调大人声采集音量 。此外,建议主唱使用 Music 音质模式(TRTCAudioQualityMusic)以获得更好的音频效果 。