Skip to main content

Real-time Transcript Updates

Overview

During AI Assistant conversations, the SDK provides real-time transcript updates that include both the caller's speech and the AI Assistant's responses. This allows you to display a live conversation transcript in your application.

Transcript Properties

The SDK provides two main ways to access transcript data:

SharedFlow for Real-time Updates

val transcriptUpdateFlow: SharedFlow<List<TranscriptItem>>

Current Transcript Access

val transcript: List<TranscriptItem>

TranscriptItem Structure

data class TranscriptItem(
val id: String, // Unique identifier
val role: String, // "user" or "assistant"
val content: String, // The transcribed text
val timestamp: Date, // When the item was created
val isPartial: Boolean = false // Whether this is a partial response
) {
companion object {
const val ROLE_USER = "user"
const val ROLE_ASSISTANT = "assistant"
}
}

Setting Up Transcript Updates

class AIConversationActivity : AppCompatActivity() {

private val conversationTranscript = mutableListOf<TranscriptItem>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// Set up transcript listener
setupTranscriptListener()
}

private fun setupTranscriptListener() {
lifecycleScope.launch {
telnyxClient.transcriptUpdateFlow.collect { transcript ->
// Update UI with new transcript
updateConversationUI(transcript)
}
}
}

private fun updateConversationUI(transcript: List<TranscriptItem>) {
runOnUiThread {
conversationTranscript.clear()
conversationTranscript.addAll(transcript)

// Update RecyclerView or other UI components
conversationAdapter.notifyDataSetChanged()

// Auto-scroll to bottom
recyclerView.scrollToPosition(conversationTranscript.size - 1)
}
}
}

Processing Individual Transcript Items

private fun updateConversationUI(transcript: List<TranscriptItem>) {
transcript.forEach { item ->
when (item.role) {
TranscriptItem.ROLE_USER -> {
Log.d("Transcript", "User said: ${item.content}")
// Display user message in UI
addUserMessage(item.content, item.timestamp)
}
TranscriptItem.ROLE_ASSISTANT -> {
Log.d("Transcript", "Assistant said: ${item.content}")
// Display assistant message in UI
addAssistantMessage(item.content, item.timestamp, item.isPartial)
}
}
}
}

Manual Transcript Access

You can also manually retrieve the current transcript at any time:

// Get current transcript
val currentTranscript = telnyxClient.transcript

// Process the transcript
currentTranscript.forEach { item ->
println("${item.role}: ${item.content} (${item.timestamp})")
}

Handling Partial Responses

AI Assistant responses may come in chunks (partial responses). Handle these appropriately:

private fun addAssistantMessage(content: String, timestamp: Date, isPartial: Boolean) {
if (isPartial) {
// Update existing message or show typing indicator
updateLastAssistantMessage(content)
showTypingIndicator(true)
} else {
// Final message - hide typing indicator
showTypingIndicator(false)
finalizeAssistantMessage(content, timestamp)
}
}

Complete Example with RecyclerView

class ConversationAdapter(
private val transcript: List<TranscriptItem>
) : RecyclerView.Adapter<ConversationAdapter.ViewHolder>() {

class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val messageText: TextView = view.findViewById(R.id.messageText)
val timestamp: TextView = view.findViewById(R.id.timestamp)
val roleIndicator: View = view.findViewById(R.id.roleIndicator)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.conversation_item, parent, false)
return ViewHolder(view)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = transcript[position]

holder.messageText.text = item.content
holder.timestamp.text = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
.format(item.timestamp)

// Style based on role
when (item.role) {
TranscriptItem.ROLE_USER -> {
holder.roleIndicator.setBackgroundColor(Color.BLUE)
holder.messageText.gravity = Gravity.END
}
TranscriptItem.ROLE_ASSISTANT -> {
holder.roleIndicator.setBackgroundColor(Color.GREEN)
holder.messageText.gravity = Gravity.START

// Show partial indicator
if (item.isPartial) {
holder.messageText.alpha = 0.7f
} else {
holder.messageText.alpha = 1.0f
}
}
}
}

override fun getItemCount() = transcript.size
}

Widget Settings Access

Access AI conversation widget settings:

// Get current widget settings
val widgetSettings = telnyxClient.currentWidgetSettings

widgetSettings?.let { settings ->
// Use widget settings to configure UI
Log.d("Widget", "Settings: $settings")
}

Important Notes

  • AI Assistant Only: Transcript updates are only available during AI Assistant conversations initiated through anonymousLogin
  • Real-time Updates: Transcripts update in real-time as the conversation progresses
  • Partial Responses: Assistant responses may come in chunks - handle isPartial flag appropriately
  • Memory Management: Transcripts are cleared when calls end or when disconnecting
  • Thread Safety: Always update UI on the main thread when processing transcript updates

Error Handling

lifecycleScope.launch {
try {
telnyxClient.transcriptUpdateFlow.collect { transcript ->
updateConversationUI(transcript)
}
} catch (e: Exception) {
Log.e("Transcript", "Error processing transcript updates: ${e.message}")
}
}

Next Steps

After setting up transcript updates:

  1. Send text messages to interact with the AI Assistant via text