Skip to content

Commit 75519f7

Browse files
CYGCYG
authored andcommitted
[Android]opt ktvapi and cloudapi
1 parent ad7e31a commit 75519f7

File tree

4 files changed

+61
-132
lines changed

4 files changed

+61
-132
lines changed

KTVAPI/Android/app/src/main/java/io/agora/ktvdemo/api/CloudApiManager.kt

Lines changed: 38 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -49,93 +49,48 @@ class CloudApiManager private constructor() {
4949
}))
5050
.build()
5151

52-
private fun fetchCloudToken(): String {
53-
var token = ""
54-
try {
55-
val acquireOjb = JSONObject()
56-
acquireOjb.put("instanceId", System.currentTimeMillis().toString() + "")
57-
//acquireOjb.put("testIp", testIp)
58-
val request: Request = Builder()
59-
.url(getTokenUrl(domain, BuildConfig.AGORA_APP_ID))
60-
.addHeader("Content-Type", "application/json")
61-
.addHeader("Authorization", basicAuth)
62-
.post(acquireOjb.toString().toRequestBody())
63-
.build()
64-
65-
val responseToken = okHttpClient.newCall(request).execute()
66-
if (responseToken.isSuccessful) {
67-
val body = responseToken.body!!
68-
val bodyString = body.string()
69-
val jsonToken = JSONObject(bodyString)
70-
if (jsonToken.has("tokenName")) {
71-
token = jsonToken.getString("tokenName")
72-
}
73-
}
74-
} catch (e: Exception) {
75-
Log.e(TAG, "getToken error " + e.message)
76-
}
77-
return token
78-
}
79-
8052
fun fetchStartCloud(mainChannel: String) {
81-
val token = fetchCloudToken()
82-
tokenName = token.ifEmpty {
83-
Log.e(TAG, "云端合流uid 请求报错 token is null")
84-
return
85-
}
8653
var taskId = ""
8754
try {
8855
val transcoderObj = JSONObject()
8956
val inputRetObj = JSONObject()
9057
.put("rtcUid", 0)
91-
.put("rtcToken", BuildConfig.AGORA_APP_ID)
9258
.put("rtcChannel", mainChannel)
93-
val intObj = JSONObject()
94-
.put("rtc", inputRetObj)
95-
transcoderObj.put("audioInputs", JSONArray().put(intObj))
96-
transcoderObj.put("idleTimeout", 300)
97-
val audioOptionObj = JSONObject()
98-
.put("profileType", "AUDIO_PROFILE_MUSIC_HIGH_QUALITY_STEREO")
99-
.put("fullChannelMixer", "native-mixer-weighted")
59+
60+
10061
val outputRetObj = JSONObject()
10162
.put("rtcUid", cloudRtcUid)
102-
.put("rtcToken", BuildConfig.AGORA_APP_ID)
10363
.put("rtcChannel", mainChannel + "_ad")
104-
val dataStreamObj = JSONObject()
105-
.put("source", JSONObject().put("audioMetaData", true))
106-
.put("sink", JSONObject())
107-
val outputsObj = JSONObject()
108-
.put("audioOption", audioOptionObj)
109-
.put("rtc", outputRetObj)
110-
.put("metaDataOption", dataStreamObj)
111-
transcoderObj.put("outputs", JSONArray().put(outputsObj))
112-
val postBody = JSONObject()
113-
.put(
114-
"services", JSONObject()
115-
.put(
116-
"cloudTranscoder", JSONObject()
117-
.put("serviceType", "cloudTranscoderV2")
118-
.put(
119-
"config", JSONObject()
120-
.put("transcoder", transcoderObj)
121-
)
122-
)
123-
)
64+
65+
transcoderObj.put("appId", BuildConfig.AGORA_APP_ID)
66+
transcoderObj.put("appCert", BuildConfig.AGORA_APP_CERTIFICATE)
67+
transcoderObj.put("src", "Android")
68+
transcoderObj.put("traceId", "12345")
69+
transcoderObj.put("instanceId", System.currentTimeMillis().toString())
70+
transcoderObj.put("basicAuth", "")
71+
transcoderObj.put("audioInputsRtc", inputRetObj)
72+
transcoderObj.put("outputsRtc", outputRetObj)
73+
12474
val request: Request = Builder()
125-
.url(startTaskUrl(domain, BuildConfig.AGORA_APP_ID, tokenName))
75+
.url(startTaskUrl())
12676
.addHeader("Content-Type", "application/json")
127-
.addHeader("Authorization", basicAuth)
128-
.post(postBody.toString().toRequestBody())
77+
.post(transcoderObj.toString().toRequestBody())
12978
.build()
13079

80+
Log.d(TAG, "fetchStartCloud: ${request.url}")
81+
13182
val responseStart = okHttpClient.newCall(request).execute()
13283
if (responseStart.isSuccessful) {
13384
val body = responseStart.body!!
13485
val bodyString = body.string()
135-
val jsonUid = JSONObject(bodyString)
86+
val jsonUid = JSONObject(bodyString).get("data") as JSONObject
87+
13688
if (jsonUid.has("taskId")) {
13789
taskId = jsonUid.getString("taskId")
13890
}
91+
if (jsonUid.has("builderToken")) {
92+
tokenName = jsonUid.getString("builderToken")
93+
}
13994
}
14095
} catch (e: Exception) {
14196
Log.e(TAG, "云端合流uid 请求报错 " + e.message)
@@ -151,11 +106,19 @@ class CloudApiManager private constructor() {
151106
return
152107
}
153108
try {
109+
val transcoderObj = JSONObject()
110+
transcoderObj.put("appId", BuildConfig.AGORA_APP_ID)
111+
transcoderObj.put("appCert", BuildConfig.AGORA_APP_CERTIFICATE)
112+
transcoderObj.put("src", "Android")
113+
transcoderObj.put("traceId", "12345")
114+
transcoderObj.put("basicAuth", "")
115+
transcoderObj.put("taskId", taskId)
116+
transcoderObj.put("builderToken", tokenName)
117+
154118
val request: Request = Builder()
155-
.url(deleteTaskUrl(domain, BuildConfig.AGORA_APP_ID, taskId, tokenName))
119+
.url(deleteTaskUrl())
156120
.addHeader("Content-Type", "application/json")
157-
.addHeader("Authorization", basicAuth)
158-
.delete()
121+
.delete(transcoderObj.toString().toRequestBody())
159122
.build()
160123
val response = okHttpClient.newCall(request).execute()
161124
if (response.isSuccessful) {
@@ -167,35 +130,13 @@ class CloudApiManager private constructor() {
167130
}
168131
}
169132

170-
private fun getTokenUrl(domain: String, appId: String): String {
171-
return String.format("%s/v1/projects/%s/rtsc/cloud-transcoder/builderTokens", domain, appId)
172-
}
173-
174-
private fun startTaskUrl(domain: String, appId: String, tokenName: String): String {
175-
return String.format("%s/v1/projects/%s/rtsc/cloud-transcoder/tasks?builderToken=%s", domain, appId, tokenName)
133+
private fun startTaskUrl(): String {
134+
val domain = BuildConfig.TOOLBOX_SERVER_HOST
135+
return String.format("%s/v1/cloud-transcoder/start", domain)
176136
}
177137

178-
private fun deleteTaskUrl(domain: String, appid: String, taskid: String, tokenName: String): String {
179-
return String.format(
180-
"%s/v1/projects/%s/rtsc/cloud-transcoder/tasks/%s?builderToken=%s",
181-
domain,
182-
appid,
183-
taskid,
184-
tokenName
185-
)
186-
}
187-
188-
private val basicAuth: String
189-
private get() {
190-
// 拼接客户 ID 和客户密钥并使用 base64 编码
191-
val plainCredentials = BuildConfig.RESTFUL_API_KEY + ":" + BuildConfig.RESTFUL_API_SECRET
192-
var base64Credentials: String? = null
193-
base64Credentials = String(Base64.getEncoder().encode(plainCredentials.toByteArray()))
194-
// 创建 authorization header
195-
return "Basic $base64Credentials"
196-
}
197-
198-
private fun getString(resId:Int):String{
199-
return MyApplication().getString(resId)
138+
private fun deleteTaskUrl(): String {
139+
val domain = BuildConfig.TOOLBOX_SERVER_HOST
140+
return String.format("%s/v1/cloud-transcoder/stop", domain)
200141
}
201142
}

KTVAPI/Android/app/src/main/java/io/agora/ktvdemo/ui/LivingFragment.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ class LivingFragment : BaseFragment<FragmentLivingBinding>() {
434434
}
435435
}
436436
)
437+
RtcEngineController.rtcEngine.setParametersEx("{\"rtc.use_audio4\": true}", RtcConnection(KeyCenter.channelId + "_ad", KeyCenter.localUid))
437438
}
438439

439440
// 加入频道后需要更新数据传输通道

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

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -348,15 +348,11 @@ class KTVApiImpl(
348348
apiReporter.reportFuncEvent("enableMulitpathing", mapOf("enable" to enable), mapOf())
349349
this.enableMultipathing = enable
350350

351-
// TODO 4.3.1 not ready
352-
// if (singerRole == KTVSingRole.LeadSinger || singerRole == KTVSingRole.CoSinger) {
353-
// subChorusConnection?.let {
354-
// mRtcEngine.updateChannelMediaOptionsEx(ChannelMediaOptions().apply {
355-
// parameters =
356-
// "{\"rtc.enableMultipath\": $enable, \"rtc.path_scheduling_strategy\": 0, \"rtc.remote_path_scheduling_strategy\": 0}"
357-
// }, subChorusConnection)
358-
// }
359-
// }
351+
if (singerRole == KTVSingRole.LeadSinger || singerRole == KTVSingRole.CoSinger) {
352+
subChorusConnection?.let {
353+
mRtcEngine.setParametersEx("{\"rtc.enableMultipath\": $enable, \"rtc.path_scheduling_strategy\": 0, \"rtc.remote_path_scheduling_strategy\": 0}", it)
354+
}
355+
}
360356
}
361357

362358
override fun switchAudioTrack(mode: AudioTrackMode) {
@@ -1011,11 +1007,6 @@ class KTVApiImpl(
10111007
channelMediaOption.enableAudioRecordingOrPlayout =
10121008
newRole != KTVSingRole.LeadSinger
10131009
channelMediaOption.clientRoleType = CLIENT_ROLE_BROADCASTER
1014-
// TODO 4.3.1 not ready
1015-
// if (enableMultipathing) {
1016-
// channelMediaOption.parameters =
1017-
// "{\"rtc.path_scheduling_strategy\":0, \"rtc.enableMultipath\": true, \"rtc.remote_path_scheduling_strategy\": 0}"
1018-
// }
10191010

10201011
val rtcConnection = RtcConnection()
10211012
rtcConnection.channelId = ktvApiConfig.chorusChannelName
@@ -1028,7 +1019,6 @@ class KTVApiImpl(
10281019
channelMediaOption,
10291020
null
10301021
)
1031-
mRtcEngine.setParameters("{\"rtc.use_audio4\": true}")
10321022
val handler = object : IRtcEngineEventHandler() {
10331023
override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
10341024
ktvApiLog("onJoinChannel2Success: channel:$channel, uid:$uid")
@@ -1076,6 +1066,7 @@ class KTVApiImpl(
10761066
}
10771067
handlerEx = handler
10781068
mRtcEngine.addHandlerEx(handler, rtcConnection)
1069+
mRtcEngine.setParametersEx("{\"rtc.path_scheduling_strategy\":0, \"rtc.enableMultipath\": true, \"rtc.remote_path_scheduling_strategy\": 0}", rtcConnection)
10791070

10801071
if (ret != 0) {
10811072
ktvApiLogError("joinChorus2ndChannel failed: $ret")

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

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -349,14 +349,11 @@ class KTVGiantChorusApiImpl(
349349
apiReporter.reportFuncEvent("enableMulitpathing", mapOf("enable" to enable), mapOf())
350350
this.enableMultipathing = enable
351351

352-
// TODO 4.3.1 not ready
353-
// if (singerRole == KTVSingRole.LeadSinger || singerRole == KTVSingRole.CoSinger) {
354-
// subChorusConnection?.let {
355-
// mRtcEngine.updateChannelMediaOptionsEx(ChannelMediaOptions().apply {
356-
// parameters = "{\"rtc.enableMultipath\": $enable, \"rtc.path_scheduling_strategy\": 0, \"rtc.remote_path_scheduling_strategy\": 0}"
357-
// }, subChorusConnection)
358-
// }
359-
// }
352+
if (singerRole == KTVSingRole.LeadSinger || singerRole == KTVSingRole.CoSinger) {
353+
subChorusConnection?.let {
354+
mRtcEngine.setParametersEx("{\"rtc.enableMultipath\": $enable, \"rtc.path_scheduling_strategy\": 0, \"rtc.remote_path_scheduling_strategy\": 0}", it)
355+
}
356+
}
360357
}
361358

362359
override fun renewToken(rtmToken: String, chorusChannelRtcToken: String) {
@@ -423,6 +420,7 @@ class KTVGiantChorusApiImpl(
423420
dealWithAudioMetadata(uid, data)
424421
}
425422
})
423+
mRtcEngine.setParametersEx("{\"rtc.use_audio4\": true}", RtcConnection(giantChorusApiConfig.audienceChannelName, giantChorusApiConfig.localUid))
426424

427425
singerRole = newRole
428426
ktvApiEventHandlerList.forEach { it.onSingerRoleChanged(oldRole, newRole) }
@@ -448,6 +446,7 @@ class KTVGiantChorusApiImpl(
448446
dealWithAudioMetadata(uid, data)
449447
}
450448
})
449+
mRtcEngine.setParametersEx("{\"rtc.use_audio4\": true}", RtcConnection(giantChorusApiConfig.audienceChannelName, giantChorusApiConfig.localUid))
451450

452451
singerRole = newRole
453452
ktvApiEventHandlerList.forEach { it.onSingerRoleChanged(oldRole, newRole) }
@@ -769,14 +768,7 @@ class KTVGiantChorusApiImpl(
769768
singChannelMediaOptions.autoSubscribeAudio = true
770769
singChannelMediaOptions.publishMicrophoneTrack = true
771770
singChannelMediaOptions.clientRoleType = CLIENT_ROLE_BROADCASTER
772-
//singChannelMediaOptions.parameters = "{\"che.audio.max_mixed_participants\": 8}" // TODO 4.3.1 not ready
773-
if (newRole == KTVSingRole.LeadSinger) {
774-
// 主唱不参加TopN
775-
singChannelMediaOptions.isAudioFilterable = false
776-
mRtcEngine.setParameters("{\"che.audio.filter_streams\":${KTVApi.routeSelectionConfig.streamNum}}")
777-
} else {
778-
mRtcEngine.setParameters("{\"che.audio.filter_streams\":${KTVApi.routeSelectionConfig.streamNum - 1}}")
779-
}
771+
singChannelMediaOptions.isAudioFilterable = newRole != KTVSingRole.LeadSinger // 主唱不参加TopN
780772

781773
// 加入演唱频道
782774
mRtcEngine.joinChannelEx(giantChorusApiConfig.chorusChannelToken, singChannelRtcConnection, singChannelMediaOptions, object :
@@ -884,16 +876,19 @@ class KTVGiantChorusApiImpl(
884876
}
885877
}
886878
})
887-
mRtcEngine.setParameters("{\"rtc.use_audio4\": true}")
879+
880+
mRtcEngine.setParametersEx("{\"che.audio.max_mixed_participants\": 8}", singChannelRtcConnection)
881+
mRtcEngine.setParametersEx("{\"rtc.use_audio4\": true}", singChannelRtcConnection)
882+
888883
// 选路策略处理
889884
if (KTVApi.routeSelectionConfig.type == GiantChorusRouteSelectionType.TOP_N || KTVApi.routeSelectionConfig.type == GiantChorusRouteSelectionType.BY_DELAY_AND_TOP_N) {
890885
if (newRole == KTVSingRole.LeadSinger) {
891-
mRtcEngine.setParameters("{\"che.audio.filter_streams\":${KTVApi.routeSelectionConfig.streamNum}}")
886+
mRtcEngine.setParametersEx("{\"che.audio.filter_streams\":${KTVApi.routeSelectionConfig.streamNum}}", singChannelRtcConnection)
892887
} else {
893-
mRtcEngine.setParameters("{\"che.audio.filter_streams\":${KTVApi.routeSelectionConfig.streamNum - 1}}")
888+
mRtcEngine.setParametersEx("{\"che.audio.filter_streams\":${KTVApi.routeSelectionConfig.streamNum - 1}}", singChannelRtcConnection)
894889
}
895890
} else {
896-
mRtcEngine.setParameters("{\"che.audio.filter_streams\": 0}")
891+
mRtcEngine.setParametersEx("{\"che.audio.filter_streams\": 0}", singChannelRtcConnection)
897892
}
898893
mRtcEngine.enableAudioVolumeIndicationEx(50, 10, true, singChannelRtcConnection)
899894

@@ -934,6 +929,7 @@ class KTVGiantChorusApiImpl(
934929
ktvApiLog("onMPKLeaveChannel")
935930
}
936931
})
932+
mRtcEngine.setParametersEx("{\"rtc.use_audio4\": true}", mpkConnection)
937933
}
938934
KTVSingRole.CoSinger -> {
939935
// 防止主唱和合唱听见mpk流的声音

0 commit comments

Comments
 (0)