android歌词同步源码,Android KTV歌房歌词同步实现流程
歌詞同步實現流程
1 功能實現流程圖
目前運用最廣的歌詞文件LRC文件內容如下。
[00:02.37] 即構KTV
[00:03.12]
[00:03.80] 作詞:即構
[00:04.55] 作曲:即構
[00:05.18] 演唱:即構
[00:06.43] 出品:深圳即構科技
這種格式文件小,容易解析,歌詞的精度控制到一行。
當觀眾、合唱、主唱都存在此歌詞文件時,此時只需要知道當前音樂進度時間戳,就能達到歌詞同步。
即構 SDK 支持將非媒體信息注入媒體流中。歌詞信息和音視頻信息是在同一個媒體通道傳輸的,這樣可以保障歌詞和音視頻同步。歌詞進度由主唱端發送,觀眾跟合唱端接收到時間戳后,再根據時間戳把關鍵歌詞行高亮。達到歌詞同步展示的效果。
具體實現流程圖請參考:
內部約定主唱端與觀眾、合唱的歌詞同步信息通信格式即可。
2 接收歌詞時間戳數據
即構 SDK 拉流解碼提取出媒體次要信息,會將其通過 onRecvMediaSideInfo 回調給應用開發者。合唱者、觀眾需要關注這個回調接口。
2.1 設置回調,接收媒體次要信息
ZEGO SDK 提供了相關接口,用于設置回調,接收媒體次要信息。
/**
* 設置回調,接收媒體次要信息
*/
mZegoLiveRoom.setZegoMediaSideCallback(new IZegoMediaSideCallback() {
@Override
public void onRecvMediaSideInfo(String streamID, ByteBuffer byteBuffer, int dataLen) {
}
});
其中,當用戶端收到媒體次要信息時,SDK 會調用之。
2.2 實現回調函數,處理媒體次要信息
媒體次要信息會作為 onRecvMediaSideInfo 的入參傳遞進去,開發者需要在該函數內,根據業務要求,處理媒體次要信息。
主唱向觀眾、合唱端發送的數據格式為時間戳。KTV App 中處理媒體次要信息的示例代碼如下:
/**
* 設置回調,接收媒體次要信息
*/
mZegoLiveRoom.setZegoMediaSideCallback(new IZegoMediaSideCallback() {
@Override
public void onRecvMediaSideInfo(String streamID, ByteBuffer byteBuffer, int dataLen) {
if (dataLen == 0) {
return;
}
int offset = 4;
// 偏移offset字節轉換成int
int timeStamp = ((byteBuffer.get(offset) & 0xff) | ((byteBuffer.get(offset + 1) & 0xff) << 8) |
((byteBuffer.get(offset + 2) & 0xff) << 16) | (byteBuffer.get(offset + 3) & 0xff) << 24);
// 此處拿到時間戳數據 timeStamp
// 拿到timeStamp后根據時間戳的值展示歌詞信息
}
});
當拿到timeStamp后,解析歌詞展示timeStamp時間段的歌詞數據就OK了。
3 主唱端發送歌詞信息
3.1 發送媒體次要信息
即構 SDK 提供了相關接口,用于發送媒體次要信息。在 KTV 場景中,歌詞信息就作為媒體次要信息注入媒體流中,連同音視頻數據一同發送到拉流端。觀眾、合唱者等拉流端接受到媒體次要信息后,得到應用進度時間戳。
如果要發送媒體次要信息,首先需要開啟媒體次要信息開關。接口如下所示:
ZegoLiveRoom
/**
發送媒體次要信息開關
@param start 開啟媒體次要信息傳輸,true 開啟媒體次要信息傳輸, false 關閉媒體次要信息傳輸。start 為 true 時,onlyAudioPublish 開關才有效
@param onlyAudioPublish 是否純音頻直播,true 純音頻直播,不傳輸視頻數據,false 音視頻直播,傳輸視頻數據。默認為 false。如果本次只有音頻直播,必須將 onlyAudioPublish 置為 true,此時將會由音頻來驅動次要信息的傳輸,同時忽略視頻流傳輸
@discussion 初始化 SDK 后,開始推流前調用。
*/
(ZegoLiveRoom)setMediaSideFlags(boolean start , boolean onlyAudioPublish);
開啟媒體次要信息開關后,才能使用以下接口進行發送媒體次要信息。
ZegoLiveRoom
/**
發送媒體次要信息
@param inData 需要傳輸的音視頻次要信息數據,外部輸入
@param dataLen 傳入的 inData 總長度,不能大于 1000 Bytes
@param packet 是否外部已經打包好包頭,true 已打包, false 未打包。如果沒有特殊情況,建議用戶使用內部打包
@discussion 主播端開啟媒體次要信息開關,開始推流后調用。調用此 API 發送媒體次要信息后,觀眾端在
(ZegoLiveRoom)setZegoMediaSideCallback() 設置的回調中獲取媒體次要信息。不需要發送媒體次要信息時,可調用 (ZegoLiveRoom)setMediaSideFlags(false,false) 關閉通道
*/
(void)sendMediaSideInfo(ByteBuffer inData, int dataLen, boolean packet);
3.2 使用發送媒體次要信息接口,如何進行媒體次要信息發送
媒體次要信息會作為 inData 的參傳入到SDK,開發者調用該函數,根據業務要求,傳入媒體次要信息。
演示 Demo 中發送媒體次要信息的示例代碼如下:
int timeStamp = // 獲取播放進度時間戳
byte[] mediaSide = new byte[4];
mediaSide[0] = (byte) (timeStamp & 0xff); // 低位(右邊)的8個bit位
mediaSide[1] = (byte) ((timeStamp >> 8) & 0xff); //第二個8 bit位
mediaSide[2] = (byte) ((timeStamp >> 16) & 0xff); //第三個 8 bit位
mediaSide[3] = (byte) ((timeStamp >> 24) & 0xff); //第4個 8 bit位
ByteBuffer inData = ByteBuffer.allocateDirect(mediaSide.length);
inData.mediaSideInfoBuf.put(mediaSide, 0, mediaSide.length);
inData.mediaSideInfoBuf.flip();
mZegoLiveRoom.sendMediaSideInfo(inData, mediaSide.length, false);
timeStamp,是當前播放的進度時間戳,需要通過播放器SDK MediaPlayer播放器的函數,去獲取該伴奏播放的進度時間戳。
關于媒體次要信息功能的詳細說明,可參考文檔:媒體次要信息
3.3 使用MediaPlayer播放器拿到當前播放的時間戳數據
知道怎么發送媒體次要信息了,接下來使用ZEGO SDK MediaPlayer提供的函數拿到時間戳
示例代碼如下:
ZegoMediaPlayer player = new ZegoMediaPlayer();
player.init(ZegoMediaPlayer.PlayerTypeAux);
// 通過該函數獲取到播放伴奏進度時間戳
int timeStamp = player.getCurrentDuration();
拿到timeStamp 后,主唱端需要做一個定時器循環去取這個時間戳使用SDK媒體次要信息接口發送出去。
每秒循環取一次,直到該首歌播放完畢, 讓觀眾、合唱歌詞展示達到同步狀態。
總結
以上是生活随笔為你收集整理的android歌词同步源码,Android KTV歌房歌词同步实现流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MSTAR数据转换成图片
- 下一篇: android 创建帧动画,Androi