# 歌词强同步 (/zh-CN/solutions/online-ktv/ktv-scenario/build/extend-karaoke/lyrics-syncing)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

<_PlatformTabsGroup>
<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="android" platform="android" />
歌词强同步功能指演唱者将歌词的播放进度等信息作为音频的附属信息（Metadata）发送到频道内，频道内的听众接收后可直接渲染歌词进度。相较于通过数据流来实现歌词同步，该功能可确保即便在弱网情况下，歌词和音乐也能保持完全同步。

## 前提条件 [#前提条件]

在使用歌词强同步功能前，请按照以下要求准备开发环境：

- Android Studio 4.0.0 或以上版本。

- Android 4.1 或以上版本的设备。

- 集成 4.1.1.24 版本的 SDK。

<Accordions type="multiple">
<Accordion title="通过 Maven Central 集成">

1. 打开你的项目根目录下的 `settings.gradle` 文件，添加 Maven Central 依赖 (如果已有可忽略)：

   ```java
      repositories {
          ...
          mavenCentral()
          ...
      }
   ```

2. 打开 `/app/build.gradle` 文件，在 `dependencies` 中添加声网实时互动 SDK 的依赖。

   ```java
   implementation "io.agora.rtc:agora-special-full:4.1.1.24"
   ```

</Accordion>
</Accordions>


## 实现流程 [#实现流程]

本节介绍如何通过发送、接收音频附属信息来实现歌词强同步功能。

### 演唱者发送歌词进度信息 [#演唱者发送歌词进度信息]

在调用相关 API 前，你需要在初始化 [`rtcEngine`](/zh-CN/api-reference/rtc/android/rtc-interface-class#class_irtcengine) 后调用 [`setParameters`](/zh-CN/api-reference/rtc/android/network#api_irtcengine_setparameters) 设置下列私有参数，才可以发送、接收音频附属信息。

```kotlin
mRtcEngine.setParameters("{\"rtc.enable_nasa2\": true}")
mRtcEngine.setParameters("{\"rtc.use_audio4\": true}")
```

1. 打包歌词信息。为降低数据量，提高歌词解析速度，建议将歌词信息序列化成 Protobuf 格式，下面是一个示例：

   ```protobuf
   syntax = "proto3";

   enum MsgType {
       UNKNOWN_TYPE = 0;
       LRC_TIME = 1001;
   }

   message LrcTime {
       MsgType type = 1;
       bool forward = 2;
       int64 ts = 3;
       string songId = 4;
       int32 uid = 5;
   }
   ```

2. 主唱调用 `sendAudioMetadata` 将歌词及播放进度等信息作为音频附属信息发送到主频道内。

   ```kotlin
   val lrcTime = LrcTimeOuterClass.LrcTime.newBuilder()
       .setTypeValue(LrcTimeOuterClass.MsgType.LRC_TIME.number)
       .setForward(true)
       .setSongId(songIdentifier)
       .setTs(curTs)
       .setUid(ktvApiConfig.localUid)
       .build()

   mRtcEngine.sendAudioMetadata(lrcTime.toByteArray())
   ```

### 听众接收歌词进度信息 [#听众接收歌词进度信息]

当主唱在频道中调用 `sendAudioMetadata` 发送歌词及歌词进度等信息后，SDK 会触发 `onAudioMetadataReceived` 回调报告接收到的歌词相关信息及发送端的用户 ID。听众端可以直接通过该回调来获取歌词的播放进度并同步给歌词组件来渲染。

```kotlin
override fun onAudioMetadataReceived(uid: Int, data: ByteArray?) {
    super.onAudioMetadataReceived(uid, data)
    val messageData = data ?: return
    try {
        // 解析 metadata
        val lrcTime = LrcTimeOuterClass.LrcTime.parseFrom(messageData)
        if (lrcTime.type == LrcTimeOuterClass.MsgType.LRC_TIME) { //同步歌词
            val realPosition = lrcTime.ts
            runOnMainThread {
                // 拿到收到的进度传给歌词组件
                lrcView?.onUpdateProgress(realPosition)
            }
        }
    } catch (exp: Exception) {
        Log.e(TAG, "onAudioMetadataReceived:$exp")
    }
}
```

## 注意事项 [#注意事项]

1. 调用 `sendAudioMetadata` 方法发送的信息长度最长为 64 字节。为降低数据量，提高解析速度，声网建议将歌词信息序列化成 Protobuf 格式。
2. 为使歌词进度和音乐同步，主唱需要将歌词信息发送到音乐流所在的频道内。在不同场景下，发送歌词信息的方式略有不同：
  - 小合唱场景：主唱通过 `joinChannel` 加入频道，并在主频道发送麦克风和音乐的混流，可直接调用 `sendAudioMetadata` 发送歌词进度到频道内。
  - 大合唱场景：主唱通过 `joinChannelEx` 在频道内发布音乐流，需调用 `sendAudioMetadataEx` 发送歌词进度。调用 `sendAudioMetadataEx` 时使用的 `RtcConnection` 需与调用 `joinChannelEx` 发布音乐流时使用的 `RtcConnection` 一致。
3. 大合唱场景中同步歌词进度还涉及云端合流方案，需要在合流侧也转发 audioMetadata，相关配置方法请联系[技术支持](https://ticket.shengwang.cn/)。
<_PlatformProcessedMarker close="true" />

<_PlatformProcessedMarker groupMode="structured" canonicalPlatform="android" platform="ios" />
歌词强同步功能指演唱者将歌词的播放进度等信息作为音频的附属信息（Metadata）发送到频道内，频道内的听众接收后可直接渲染歌词进度。相较于通过数据流来实现歌词同步，该功能可确保即便在弱网情况下，歌词和音乐也能保持完全同步。

## 前提条件 [#前提条件-1]

在使用歌词强同步功能前，请按照以下要求准备开发环境：

- Xcode 13.0 或以上版本。

- 已安装 [CocoaPods](https://guides.cocoapods.org/using/getting-started.html#getting-started)。

- iOS 13.0 或以上版本的设备。

- 集成 4.1.1.24 版本的 SDK。

<Accordions type="multiple">
<Accordion title="集成步骤">

1. 在终端里进入项目根目录，并运行 `pod init` 命令。项目文件夹下会生成一个 `Podfile` 文本文件。

2. 打开 `Podfile` 文件，修改文件为如下内容。注意将 Your App 替换为你的 Target 名称。

   ```ruby
   platform :ios, '9.0'
   target 'Your App' do
     pod 'AgoraRtcEngine_Special_iOS', '4.1.1.24'
   end
   ```

3. 在终端内运行 `pod install` 命令安装声网 SDK。成功安装后，Terminal 中会显示 `Pod installation complete!`。

</Accordion>
</Accordions>


## 实现流程 [#实现流程-1]

本节介绍如何通过发送、接收音频附属信息来实现歌词强同步功能。

### 演唱者发送歌词进度信息 [#演唱者发送歌词进度信息-1]

在调用相关 API 前，你需要在初始化 [`AgoraRtcEngineKit`](/zh-CN/api-reference/rtc/ios/rtc-interface-class#class_irtcengine) 后调用 [`setParameters`](/zh-CN/api-reference/rtc/ios/network#api_irtcengine_setparameters) 设置下列私有参数，才可以发送、接收音频附属信息。

```swift
engine?.setParameters("{\"rtc.enable_nasa2\": true}")
engine?.setParameters("{\"rtc.use_audio4\": true}")
```

1. 打包歌词信息。为降低数据量，提高歌词解析速度，建议将歌词信息序列化成 Protobuf 格式，下面是一个示例：

   ```protobuf
   syntax = "proto3";

   enum MsgType {
       UNKNOWN_TYPE = 0;
       LRC_TIME = 1001;
   }

   message LrcTime {
       MsgType type = 1;
       bool forward = 2;
       int64 ts = 3;
       string songId = 4;
       int32 uid = 5;
   }
   ```

2. 主唱调用 `sendAudioMetadata` 将歌词及播放进度等信息作为音频附属信息发送到主频道内。

   ```swift
   var time: LrcTime = LrcTime()
   time.forward = true
   time.ts = (your current time)
   time.songID = songIdentifier
   time.type = .lrcTime
   time.uid = Int32(Int(apiConfig?.localUid ?? 0))

   let data: Data? = try? time.serializedData()
   let code = apiConfig?.engine?.sendAudioMetadata(data ?? Data())
   ```

### 听众接收歌词进度信息 [#听众接收歌词进度信息-1]

当主唱在频道中调用 `sendAudioMetadata` 发送歌词及歌词进度等信息后，SDK 会触发 `onAudioMetadataReceived` 回调报告接收到的歌词相关信息及发送端的用户 ID。听众端可以直接通过该回调来获取歌词的播放进度并同步给歌词组件来渲染。

```swift
func audioMetadataReceived(uid: UInt, metadata: Data) {
    guard let time: LrcTime = try? LrcTime(serializedData: metadata) else {return}
    if time.type == .lrcTime {
        self.setProgress(with: Int(time.ts))
    }
}
```

## 注意事项 [#注意事项-1]

1. 调用 `sendAudioMetadata` 方法发送的信息长度最长为 64 字节。为降低数据量，提高解析速度，声网建议将歌词信息序列化成 Protobuf 格式。
2. 为使歌词进度和音乐同步，主唱需要将歌词信息发送到音乐流所在的频道内。在不同场景下，发送歌词信息的方式略有不同：
  - 小合唱场景：主唱通过 `joinChannelByToken` 加入频道，并在主频道发送麦克风和音乐的混流，可直接调用 `sendAudioMetadata` 发送歌词进度到频道内。
  - 大合唱场景：主唱通过 `joinChannelExByToken` 在频道内发布音乐流，需调用 `sendAudioMetadataEx` 发送歌词进度。调用 `sendAudioMetadataEx` 时使用的 `RtcConnection` 和需和调用 `joinChannelEx` 发布音乐流时使用的 `RtcConnection` 一致。
3. 大合唱场景中同步歌词进度还涉及云端合流方案，需要在合流侧也转发 audioMetadata，相关配置方法请联系[技术支持](https://ticket.shengwang.cn/)。
<_PlatformProcessedMarker close="true" />
</_PlatformTabsGroup>
