Skip to content

Commit 5663904

Browse files
CYGCYG
authored andcommitted
[Android]add needPrelude
1 parent 6879058 commit 5663904

File tree

2 files changed

+121
-54
lines changed

2 files changed

+121
-54
lines changed

KTVAPI/Android/lib_ktvapi/src/main/java/io/agora/ktvapi/KTVApi.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ enum class KTVSingRole(val value: Int) {
5353
enum class KTVLoadMusicFailReason(val value: Int) {
5454
NO_LYRIC_URL(0),
5555
MUSIC_PRELOAD_FAIL(1),
56-
CANCELED(2)
56+
CANCELED(2),
57+
GET_SIMPLE_INFO_FAIL(3)
5758
}
5859

5960
/**
@@ -323,11 +324,13 @@ data class KTVGiantChorusApiConfig constructor(
323324
* @param songIdentifier 歌曲 id,通常由业务方给每首歌设置一个不同的SongId用于区分
324325
* @param mainSingerUid 主唱的 Uid,如果是伴唱,伴唱需要根据这个信息 mute 主频道主唱的声音
325326
* @param mode 歌曲加载的模式,默认为音乐和歌词均加载
327+
* @param needPrelude 播放切片歌曲情况下,是否播放
326328
*/
327329
data class KTVLoadMusicConfiguration(
328330
val songIdentifier: String,
329331
val mainSingerUid: Int,
330-
val mode: KTVLoadMusicMode = KTVLoadMusicMode.LOAD_MUSIC_AND_LRC
332+
val mode: KTVLoadMusicMode = KTVLoadMusicMode.LOAD_MUSIC_AND_LRC,
333+
val needPrelude: Boolean = false
331334
)
332335

333336
/**

KTVAPI/Android/lib_ktvapi/src/main/java/io/agora/ktvapi/KTVApiImpl.kt

Lines changed: 116 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class KTVApiImpl(
4444
private val lyricCallbackMap =
4545
mutableMapOf<String, (songNo: Long, lyricUrl: String?) -> Unit>() // (requestId, callback)
4646
private val lyricSongCodeMap = mutableMapOf<String, Long>() // (requestId, songCode)
47+
private val simpleInfoCallbackMap = mutableMapOf<String, (songNo: Long, success: Boolean) -> Unit>() // (requestId, callback)
4748
private val loadMusicCallbackMap =
4849
mutableMapOf<String, (songCode: Long,
4950
percent: Int,
@@ -88,6 +89,9 @@ class KTVApiImpl(
8889
private var audioRouting = 0
8990
private var isPublishAudio = false // 通过是否发音频流判断
9091

92+
// 抢唱模式下是否需要prelude
93+
private var needPrelude = false
94+
9195
// 开始播放歌词
9296
private var mStopDisplayLrc = true
9397
private var displayLrcFuture: ScheduledFuture<*>? = null
@@ -275,6 +279,7 @@ class KTVApiImpl(
275279
loadMusicCallbackMap.clear()
276280
musicChartsCallbackMap.clear()
277281
musicCollectionCallbackMap.clear()
282+
simpleInfoCallbackMap.clear()
278283
lrcView = null
279284

280285
mRtcEngine.removeHandler(this)
@@ -344,7 +349,8 @@ class KTVApiImpl(
344349
if (singerRole == KTVSingRole.LeadSinger || singerRole == KTVSingRole.CoSinger) {
345350
subChorusConnection?.let {
346351
mRtcEngine.updateChannelMediaOptionsEx(ChannelMediaOptions().apply {
347-
parameters = "{\"rtc.enableMultipath\": $enable, \"rtc.path_scheduling_strategy\": 0, \"rtc.remote_path_scheduling_strategy\": 0}"
352+
parameters =
353+
"{\"rtc.enableMultipath\": $enable, \"rtc.path_scheduling_strategy\": 0, \"rtc.remote_path_scheduling_strategy\": 0}"
348354
}, subChorusConnection)
349355
}
350356
}
@@ -568,13 +574,12 @@ class KTVApiImpl(
568574
) {
569575
reportCallScenarioApi("loadMusic", JSONObject().put("songCode", songCode).put("config", config))
570576
ktvApiLog("loadMusic called: songCode $songCode")
571-
if (this.ktvApiConfig.type == KTVType.SingBattle) {
572-
mMusicCenter.getSongSimpleInfo(songCode)
573-
}
577+
574578
// 设置到全局, 连续调用以最新的为准
575579
this.songCode = songCode
576580
this.songIdentifier = config.songIdentifier
577581
this.mainSingerUid = config.mainSingerUid
582+
this.needPrelude = config.needPrelude
578583
mLastReceivedPlayPosTime = null
579584
mReceivedPlayPosition = 0
580585

@@ -600,7 +605,17 @@ class KTVApiImpl(
600605
// 加载歌词成功
601606
ktvApiLog("loadMusic success")
602607
lrcView?.onDownloadLrcData(lyricUrl)
603-
musicLoadStateListener.onMusicLoadSuccess(song, lyricUrl)
608+
if (this.ktvApiConfig.type != KTVType.SingBattle) {
609+
musicLoadStateListener.onMusicLoadSuccess(song, lyricUrl)
610+
} else {
611+
getSongSimpleInfo(songCode) { code, success ->
612+
if (success) {
613+
musicLoadStateListener.onMusicLoadSuccess(song, lyricUrl)
614+
} else {
615+
musicLoadStateListener.onMusicLoadFail(code, KTVLoadMusicFailReason.GET_SIMPLE_INFO_FAIL)
616+
}
617+
}
618+
}
604619
}
605620
}
606621
return
@@ -635,14 +650,34 @@ class KTVApiImpl(
635650
ktvApiLog("loadMusic success")
636651
lrcView?.onDownloadLrcData(lyricUrl)
637652
musicLoadStateListener.onMusicLoadProgress(song, 100, MusicLoadStatus.COMPLETED, msg, lrcUrl)
638-
musicLoadStateListener.onMusicLoadSuccess(song, lyricUrl)
653+
if (this.ktvApiConfig.type != KTVType.SingBattle) {
654+
musicLoadStateListener.onMusicLoadSuccess(song, lyricUrl)
655+
} else {
656+
getSongSimpleInfo(songCode) { code, success ->
657+
if (success) {
658+
musicLoadStateListener.onMusicLoadSuccess(song, lyricUrl)
659+
} else {
660+
musicLoadStateListener.onMusicLoadFail(code, KTVLoadMusicFailReason.GET_SIMPLE_INFO_FAIL)
661+
}
662+
}
663+
}
639664
}
640665
}
641666
} else if (config.mode == KTVLoadMusicMode.LOAD_MUSIC_ONLY) {
642667
// 不需要加载歌词
643668
ktvApiLog("loadMusic success")
644669
musicLoadStateListener.onMusicLoadProgress(song, 100, MusicLoadStatus.COMPLETED, msg, lrcUrl)
645-
musicLoadStateListener.onMusicLoadSuccess(song, "")
670+
if (this.ktvApiConfig.type != KTVType.SingBattle) {
671+
musicLoadStateListener.onMusicLoadSuccess(song, "")
672+
} else {
673+
getSongSimpleInfo(songCode) { code, success ->
674+
if (success) {
675+
musicLoadStateListener.onMusicLoadSuccess(song, "")
676+
} else {
677+
musicLoadStateListener.onMusicLoadFail(code, KTVLoadMusicFailReason.GET_SIMPLE_INFO_FAIL)
678+
}
679+
}
680+
}
646681
}
647682
} else if (status == 2) {
648683
// 预加载歌曲加载中
@@ -674,6 +709,7 @@ class KTVApiImpl(
674709
this.songIdentifier = config.songIdentifier
675710
this.songUrl = url
676711
this.mainSingerUid = config.mainSingerUid
712+
this.needPrelude = config.needPrelude
677713
}
678714

679715
override fun load2Music(url1: String, url2: String, config: KTVLoadMusicConfiguration) {
@@ -682,6 +718,7 @@ class KTVApiImpl(
682718
this.songUrl = url1
683719
this.songUrl2 = url2
684720
this.mainSingerUid = config.mainSingerUid
721+
this.needPrelude = config.needPrelude
685722
}
686723

687724
override fun switchPlaySrc(url: String, syncPts: Boolean) {
@@ -966,7 +1003,8 @@ class KTVApiImpl(
9661003
newRole != KTVSingRole.LeadSinger
9671004
channelMediaOption.clientRoleType = CLIENT_ROLE_BROADCASTER
9681005
if (enableMultipathing) {
969-
channelMediaOption.parameters = "{\"rtc.path_scheduling_strategy\":0, \"rtc.enableMultipath\": true, \"rtc.remote_path_scheduling_strategy\": 0}"
1006+
channelMediaOption.parameters =
1007+
"{\"rtc.path_scheduling_strategy\":0, \"rtc.enableMultipath\": true, \"rtc.remote_path_scheduling_strategy\": 0}"
9701008
}
9711009

9721010
val rtcConnection = RtcConnection()
@@ -982,50 +1020,50 @@ class KTVApiImpl(
9821020
)
9831021
mRtcEngine.setParameters("{\"rtc.use_audio4\": true}")
9841022
val handler = object : IRtcEngineEventHandler() {
985-
override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
986-
ktvApiLog("onJoinChannel2Success: channel:$channel, uid:$uid")
987-
if (isRelease) return
988-
super.onJoinChannelSuccess(channel, uid, elapsed)
989-
if (newRole == KTVSingRole.LeadSinger) {
990-
mainSingerHasJoinChannelEx = true
991-
}
992-
onJoinChorus2ndChannelCallback(0)
993-
mRtcEngine.enableAudioVolumeIndicationEx(50, 10, true, rtcConnection)
1023+
override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
1024+
ktvApiLog("onJoinChannel2Success: channel:$channel, uid:$uid")
1025+
if (isRelease) return
1026+
super.onJoinChannelSuccess(channel, uid, elapsed)
1027+
if (newRole == KTVSingRole.LeadSinger) {
1028+
mainSingerHasJoinChannelEx = true
9941029
}
1030+
onJoinChorus2ndChannelCallback(0)
1031+
mRtcEngine.enableAudioVolumeIndicationEx(50, 10, true, rtcConnection)
1032+
}
9951033

996-
override fun onLeaveChannel(stats: RtcStats?) {
997-
ktvApiLog("onLeaveChannel2")
998-
if (isRelease) return
999-
super.onLeaveChannel(stats)
1000-
if (newRole == KTVSingRole.LeadSinger) {
1001-
mainSingerHasJoinChannelEx = false
1002-
}
1034+
override fun onLeaveChannel(stats: RtcStats?) {
1035+
ktvApiLog("onLeaveChannel2")
1036+
if (isRelease) return
1037+
super.onLeaveChannel(stats)
1038+
if (newRole == KTVSingRole.LeadSinger) {
1039+
mainSingerHasJoinChannelEx = false
10031040
}
1041+
}
10041042

1005-
override fun onError(err: Int) {
1006-
super.onError(err)
1007-
if (isRelease) return
1008-
if (err == ERR_JOIN_CHANNEL_REJECTED) {
1009-
ktvApiLogError("joinChorus2ndChannel failed: ERR_JOIN_CHANNEL_REJECTED")
1010-
onJoinChorus2ndChannelCallback(ERR_JOIN_CHANNEL_REJECTED)
1011-
} else if (err == ERR_LEAVE_CHANNEL_REJECTED) {
1012-
ktvApiLogError("leaveChorus2ndChannel failed: ERR_LEAVE_CHANNEL_REJECTED")
1013-
}
1043+
override fun onError(err: Int) {
1044+
super.onError(err)
1045+
if (isRelease) return
1046+
if (err == ERR_JOIN_CHANNEL_REJECTED) {
1047+
ktvApiLogError("joinChorus2ndChannel failed: ERR_JOIN_CHANNEL_REJECTED")
1048+
onJoinChorus2ndChannelCallback(ERR_JOIN_CHANNEL_REJECTED)
1049+
} else if (err == ERR_LEAVE_CHANNEL_REJECTED) {
1050+
ktvApiLogError("leaveChorus2ndChannel failed: ERR_LEAVE_CHANNEL_REJECTED")
10141051
}
1052+
}
10151053

1016-
override fun onTokenPrivilegeWillExpire(token: String?) {
1017-
super.onTokenPrivilegeWillExpire(token)
1018-
ktvApiEventHandlerList.forEach { it.onTokenPrivilegeWillExpire() }
1019-
}
1054+
override fun onTokenPrivilegeWillExpire(token: String?) {
1055+
super.onTokenPrivilegeWillExpire(token)
1056+
ktvApiEventHandlerList.forEach { it.onTokenPrivilegeWillExpire() }
1057+
}
10201058

1021-
override fun onAudioVolumeIndication(
1022-
speakers: Array<out AudioVolumeInfo>?,
1023-
totalVolume: Int
1024-
) {
1025-
super.onAudioVolumeIndication(speakers, totalVolume)
1026-
ktvApiEventHandlerList.forEach { it.onChorusChannelAudioVolumeIndication(speakers, totalVolume) }
1027-
}
1059+
override fun onAudioVolumeIndication(
1060+
speakers: Array<out AudioVolumeInfo>?,
1061+
totalVolume: Int
1062+
) {
1063+
super.onAudioVolumeIndication(speakers, totalVolume)
1064+
ktvApiEventHandlerList.forEach { it.onChorusChannelAudioVolumeIndication(speakers, totalVolume) }
10281065
}
1066+
}
10291067
handlerEx = handler
10301068
mRtcEngine.addHandlerEx(handler, rtcConnection)
10311069

@@ -1137,6 +1175,16 @@ class KTVApiImpl(
11371175
loadMusicCallbackMap[songNo.toString()] = onLoadMusicCallback
11381176
}
11391177

1178+
private fun getSongSimpleInfo(songNo: Long, onSongSimpleInfoResult: (songCode: Long, success: Boolean) -> Unit) {
1179+
ktvApiLog("getSongSimpleInfo: $songNo")
1180+
val requestId = mMusicCenter.getSongSimpleInfo(songNo)
1181+
if (requestId == null || requestId.isEmpty()) {
1182+
onSongSimpleInfoResult.invoke(songNo, false)
1183+
return
1184+
}
1185+
simpleInfoCallbackMap[requestId] = onSongSimpleInfoResult
1186+
}
1187+
11401188
private fun getNtpTimeInMs(): Long {
11411189
val currentNtpTime = mRtcEngine.ntpWallTimeInMs
11421190
return if (currentNtpTime != 0L) {
@@ -1438,14 +1486,30 @@ class KTVApiImpl(
14381486
errorCode: Int
14391487
) {
14401488
if (this.ktvApiConfig.type == KTVType.Normal) return
1441-
val jsonMsg = JSONObject(simpleInfo)
1442-
val format = jsonMsg.getJSONObject("format")
1443-
val highPart = format.getJSONArray("highPart")
1444-
val highStartTime = JSONObject(highPart[0].toString())
1445-
val time = highStartTime.getLong("highStartTime")
1446-
val endTime = highStartTime.getLong("highEndTime")
1447-
this.highStartTime = time
1448-
lrcView?.onHighPartTime(time, endTime)
1489+
val callback = simpleInfoCallbackMap[requestId] ?: return
1490+
if (errorCode != 0) {
1491+
ktvApiLogError("onSongSimpleInfoResult failed, requestId: $requestId, songCode: $songCode, errorCode: $errorCode")
1492+
callback.invoke(songCode, false)
1493+
return
1494+
}
1495+
try {
1496+
val jsonMsg = JSONObject(simpleInfo)
1497+
val format = jsonMsg.getJSONObject("format")
1498+
val highPart = format.getJSONArray("highPart")
1499+
val highStartTime = JSONObject(highPart[0].toString())
1500+
val time = highStartTime.getLong("highStartTime")
1501+
val endTime = highStartTime.getLong("highEndTime")
1502+
val preludeDuration = highStartTime.getLong("preludeDuration")
1503+
this.highStartTime = time
1504+
if (needPrelude) {
1505+
this.highStartTime -= preludeDuration
1506+
}
1507+
lrcView?.onHighPartTime(time, endTime)
1508+
callback.invoke(songCode, true)
1509+
} catch (e: JSONException) {
1510+
ktvApiLogError("onSongSimpleInfoResult: ${e.message}")
1511+
callback.invoke(songCode, false)
1512+
}
14491513
}
14501514

14511515
// ------------------------ AgoraRtcMediaPlayerDelegate ------------------------

0 commit comments

Comments
 (0)