Skip to content

Commit b25ce43

Browse files
committed
Updating Small WebRTC transport to Pipecat Client v1.1.0
1 parent 35dd91b commit b25ce43

12 files changed

Lines changed: 123 additions & 59 deletions

File tree

README.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The following RTVI transports are available in this repository:
1313
Add the following dependency to your `build.gradle` file:
1414

1515
```
16-
implementation "ai.pipecat:daily-transport:1.0.3"
16+
implementation "ai.pipecat:daily-transport:1.1.0"
1717
```
1818

1919
Instantiate from your code:
@@ -32,7 +32,7 @@ val options = PipecatClientOptions(callbacks = callbacks)
3232

3333
val client: PipecatClientDaily = PipecatClient(DailyTransport(context), options)
3434

35-
client.startBotAndConnect(startBotParams).withCallback {
35+
client.startBotAndConnect(apiRequest).withCallback {
3636
// ...
3737
}
3838
```
@@ -125,23 +125,26 @@ client.connect().withCallback {
125125
Add the following dependency to your `build.gradle` file:
126126

127127
```
128-
implementation "ai.pipecat:small-webrtc-transport:0.3.7"
128+
implementation "ai.pipecat:small-webrtc-transport:1.1.0"
129129
```
130130

131131
Instantiate from your code:
132132

133133
```kotlin
134-
val options = RTVIClientOptions(
135-
params = RTVIClientParams(baseUrl = null),
136-
enableMic = true,
137-
enableCam = true
138-
)
134+
val callbacks = object : PipecatEventCallbacks() {
139135

140-
val connectionUrl = "http://localhost:7860/api/offer"
136+
override fun onBackendError(message: String) {
137+
Log.e(TAG, "Error from backend: $message")
138+
}
141139

142-
val client = RTVIClient(SmallWebRTCTransport.Factory(context, connectionUrl), callbacks, options)
140+
// ...
141+
}
143142

144-
client.connect().withCallback {
143+
val options = PipecatClientOptions(callbacks = callbacks)
144+
145+
val client: PipecatClientSmallWebRTC = PipecatClient(SmallWebRTCTransport(context), options)
146+
147+
client.startBotAndConnect(apiRequest).withCallback {
145148
// ...
146149
}
147-
```
150+
```

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ dokka = "1.9.20"
1010
androidxTest = "1.6.1"
1111
ktor = "2.3.5"
1212
okhttp = "4.12.0"
13-
pipecatClient = "1.0.2"
13+
pipecatClient = "1.1.0"
1414

1515
[libraries]
1616
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }

pipecat-client-android-daily/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
val libraryVersion = "1.0.3"
1+
val libraryVersion = "1.1.0"
22

33
plugins {
44
alias(libs.plugins.android.library)

pipecat-client-android-daily/src/main/java/ai/pipecat/client/daily/DailyTransport.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import ai.pipecat.client.transport.MsgClientToServer
99
import ai.pipecat.client.transport.MsgServerToClient
1010
import ai.pipecat.client.transport.Transport
1111
import ai.pipecat.client.transport.TransportContext
12+
import ai.pipecat.client.types.APIRequest
1213
import ai.pipecat.client.types.MediaDeviceId
1314
import ai.pipecat.client.types.MediaDeviceInfo
1415
import ai.pipecat.client.types.Participant
@@ -238,7 +239,10 @@ class DailyTransport(
238239
thread = ctx.thread
239240
}
240241

241-
override fun deserializeConnectParams(json: String): DailyTransportConnectParams {
242+
override fun deserializeConnectParams(
243+
json: String,
244+
startBotRequest: APIRequest
245+
): DailyTransportConnectParams {
242246
val authBundle: DailyTransportAuthBundle = JSON_INSTANCE.decodeFromString(json)
243247

244248
val room = authBundle.actualRoom() ?: throw Exception("dailyRoom not set")

pipecat-client-android-small-webrtc-transport/build.gradle.kts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
val libraryVersion = "1.1.0"
2+
13
plugins {
24
alias(libs.plugins.android.library)
35
alias(libs.plugins.jetbrains.kotlin.android)
@@ -9,11 +11,12 @@ plugins {
911

1012
android {
1113
namespace = "ai.pipecat.client.small_webrtc_transport"
12-
compileSdk = 34
14+
compileSdk = 35
1315

1416
defaultConfig {
1517
minSdk = 24
1618
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
19+
buildConfigField("String", "VERSION_NAME", "\"$libraryVersion\"")
1720
}
1821

1922
buildTypes {
@@ -27,16 +30,20 @@ android {
2730
}
2831

2932
compileOptions {
30-
sourceCompatibility = JavaVersion.VERSION_1_8
31-
targetCompatibility = JavaVersion.VERSION_1_8
33+
sourceCompatibility = JavaVersion.VERSION_11
34+
targetCompatibility = JavaVersion.VERSION_11
3235
}
3336

3437
lint {
3538
targetSdk = 35
3639
}
3740

3841
kotlinOptions {
39-
jvmTarget = "1.8"
42+
jvmTarget = "11"
43+
}
44+
45+
buildFeatures {
46+
buildConfig = true
4047
}
4148

4249
sourceSets {
@@ -56,8 +63,7 @@ dependencies {
5663
implementation(libs.ktor.client.content.negotiation)
5764
implementation(libs.ktor.serialization.kotlinx.json)
5865

59-
// Temporary override until transport is updated to 1.0.0
60-
api("ai.pipecat:client:0.3.4")
66+
api(libs.pipecat.client)
6167

6268
androidTestImplementation(libs.androidx.runner)
6369
androidTestImplementation(libs.androidx.rules)
@@ -76,7 +82,7 @@ publishing {
7682
register<MavenPublication>("release") {
7783
groupId = "ai.pipecat"
7884
artifactId = "small-webrtc-transport"
79-
version = "0.3.7"
85+
version = libraryVersion
8086

8187
pom {
8288
name.set("Small WebRTC Transport")

pipecat-client-android-small-webrtc-transport/src/main/java/ai/pipecat/client/small_webrtc_transport/OfferRequestBody.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package ai.pipecat.client.small_webrtc_transport
22

3+
import ai.pipecat.client.types.Value
34
import kotlinx.serialization.SerialName
45
import kotlinx.serialization.Serializable
56

@@ -10,5 +11,7 @@ internal data class OfferRequestBody(
1011
@SerialName("pc_id")
1112
val pcId: String?,
1213
@SerialName("restart_pc")
13-
val restartPc: Boolean
14+
val restartPc: Boolean,
15+
@SerialName("request_data")
16+
val requestData: Value
1417
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package ai.pipecat.client.small_webrtc_transport
2+
3+
import ai.pipecat.client.PipecatClient
4+
5+
typealias PipecatClientSmallWebRTC = PipecatClient<SmallWebRTCTransport, SmallWebRTCTransportConnectParams>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package ai.pipecat.client.small_webrtc_transport
2+
3+
import ai.pipecat.client.types.Value
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
internal data class SmallWebRTCStartBotResult(
8+
val sessionId: String,
9+
val iceConfig: Value = Value.Null
10+
)

pipecat-client-android-small-webrtc-transport/src/main/java/ai/pipecat/client/small_webrtc_transport/SmallWebRTCTransport.kt

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@ import ai.pipecat.client.result.RTVIError
55
import ai.pipecat.client.result.resolvedPromiseErr
66
import ai.pipecat.client.result.resolvedPromiseOk
77
import ai.pipecat.client.result.withPromise
8-
import ai.pipecat.client.transport.AuthBundle
98
import ai.pipecat.client.transport.MsgClientToServer
109
import ai.pipecat.client.transport.MsgServerToClient
1110
import ai.pipecat.client.transport.Transport
1211
import ai.pipecat.client.transport.TransportContext
13-
import ai.pipecat.client.transport.TransportFactory
12+
import ai.pipecat.client.types.APIRequest
1413
import ai.pipecat.client.types.MediaDeviceId
1514
import ai.pipecat.client.types.MediaDeviceInfo
1615
import ai.pipecat.client.types.Participant
1716
import ai.pipecat.client.types.ParticipantId
1817
import ai.pipecat.client.types.TransportState
18+
import ai.pipecat.client.types.Value
19+
import ai.pipecat.client.utils.ThreadRef
1920
import android.annotation.SuppressLint
2021
import android.content.Context
2122
import android.media.AudioManager
@@ -37,11 +38,9 @@ private val LOCAL_PARTICIPANT = Participant(
3738
local = true
3839
)
3940

40-
class SmallWebRTCTransport internal constructor(
41-
private val transportContext: TransportContext,
42-
androidContext: Context,
43-
private val serverUrl: String,
44-
) : Transport() {
41+
class SmallWebRTCTransport(
42+
context: Context,
43+
) : Transport<SmallWebRTCTransportConnectParams>() {
4544

4645
companion object {
4746
private const val TAG = "SmallWebRTCTransport"
@@ -64,30 +63,30 @@ class SmallWebRTCTransport internal constructor(
6463
val Rear = MediaDeviceInfo(id = MediaDeviceId("cam-rear"), name = "Rear Camera")
6564
}
6665

67-
class Factory(
68-
private val androidContext: Context,
69-
private val serverUrl: String
70-
) : TransportFactory {
71-
override fun createTransport(context: TransportContext): Transport {
72-
return SmallWebRTCTransport(context, androidContext, serverUrl)
73-
}
74-
}
66+
private lateinit var transportContext: TransportContext
67+
private lateinit var thread: ThreadRef
7568

7669
private var state = TransportState.Disconnected
7770

78-
private val appContext = androidContext.applicationContext
79-
private val thread = transportContext.thread
71+
private val appContext = context.applicationContext
8072

8173
private var client: WebRTCClient? = null
8274
private var selectedCam = CameraMode.Front
8375

76+
override fun initialize(ctx: TransportContext) {
77+
transportContext = ctx
78+
thread = ctx.thread
79+
}
80+
8481
override fun initDevices(): Future<Unit, RTVIError> = resolvedPromiseOk(thread, Unit)
8582

8683
@SuppressLint("MissingPermission")
87-
override fun connect(authBundle: AuthBundle?): Future<Unit, RTVIError> =
84+
override fun connect(
85+
transportParams: SmallWebRTCTransportConnectParams
86+
): Future<Unit, RTVIError> =
8887
thread.runOnThreadReturningFuture {
8988

90-
Log.i(TAG, "connect(${authBundle})")
89+
Log.i(TAG, "connect(${transportParams})")
9190

9291
if (client != null) {
9392
return@runOnThreadReturningFuture resolvedPromiseErr(
@@ -114,7 +113,7 @@ class SmallWebRTCTransport internal constructor(
114113
disconnect()
115114
}
116115

117-
"renegotiate" -> negotiate()
116+
"renegotiate" -> negotiate(transportParams)
118117
}
119118

120119
} else {
@@ -139,7 +138,8 @@ class SmallWebRTCTransport internal constructor(
139138
} else {
140139
null
141140
},
142-
initialMicEnabled = transportContext.options.enableMic
141+
initialMicEnabled = transportContext.options.enableMic,
142+
rtviProtocolVersion = transportContext.protocolVersion
143143
)
144144
} catch (e: Exception) {
145145
return@runOnThreadReturningFuture resolvedPromiseErr(
@@ -148,18 +148,17 @@ class SmallWebRTCTransport internal constructor(
148148
)
149149
}
150150

151-
negotiate()
151+
negotiate(transportParams)
152152
}
153153

154-
private fun negotiate() = withPromise<Unit, RTVIError>(thread) { promise ->
154+
private fun negotiate(
155+
connectParams: SmallWebRTCTransportConnectParams
156+
) = withPromise<Unit, RTVIError>(thread) { promise ->
155157

156158
MainScope().launch {
157159

158160
try {
159-
client?.negotiateConnection(
160-
url = serverUrl,
161-
restartPc = false
162-
)
161+
client?.negotiateConnection(connectParams)
163162

164163
val cb = transportContext.callbacks
165164
setState(TransportState.Connected)
@@ -174,6 +173,24 @@ class SmallWebRTCTransport internal constructor(
174173
}
175174
}
176175

176+
override fun deserializeConnectParams(
177+
json: String,
178+
startBotRequest: APIRequest
179+
): SmallWebRTCTransportConnectParams {
180+
val startBotResult = JSON_INSTANCE.decodeFromString<SmallWebRTCStartBotResult>(json)
181+
182+
return SmallWebRTCTransportConnectParams(
183+
webrtcRequestParams = APIRequest(
184+
endpoint = startBotRequest.endpoint.replace(
185+
"/start",
186+
"/sessions/${startBotResult.sessionId}/api/offer"
187+
),
188+
requestData = Value.Object(),
189+
headers = startBotRequest.headers
190+
)
191+
)
192+
}
193+
177194
override fun disconnect(): Future<Unit, RTVIError> = thread.runOnThreadReturningFuture {
178195
withPromise(thread) { promise ->
179196

@@ -185,6 +202,7 @@ class SmallWebRTCTransport internal constructor(
185202
if (clientRef != null) {
186203
clientRef.dispose()
187204
setState(TransportState.Disconnected)
205+
transportContext.onConnectionEnd()
188206
transportContext.callbacks.onDisconnected()
189207
}
190208
promise.resolveOk(Unit)
@@ -256,8 +274,6 @@ class SmallWebRTCTransport internal constructor(
256274
override fun enableMic(enable: Boolean): Future<Unit, RTVIError> = client?.setMicEnabled(enable)
257275
?: resolvedPromiseErr(thread, RTVIError.TransportNotInitialized)
258276

259-
override fun expiry() = null
260-
261277
override fun enableCam(enable: Boolean): Future<Unit, RTVIError> =
262278
client?.setCamMode(if (enable) selectedCam else null)
263279
?: resolvedPromiseErr(thread, RTVIError.TransportNotInitialized)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package ai.pipecat.client.small_webrtc_transport
2+
3+
import ai.pipecat.client.types.APIRequest
4+
5+
data class SmallWebRTCTransportConnectParams(
6+
val webrtcRequestParams: APIRequest
7+
)

0 commit comments

Comments
 (0)