Live Captioning for Livestreams - Android
Live captioning enhances your livestreams by converting hosts' speech into text in real-time, boosting accessibility and engagement. Using the startTranscription() and stopTranscription() methods, you can enable or disable captions on the fly, and display captions dynamically in your UI for all viewers.
Video SDK offers flexible configuration and event-driven updates to help you integrate captions seamlessly into your broadcast layout.
startTranscription()
The startTranscription() method, accesible from the Meeting class, is used to initiate live captions in a live stream.
stopTranscription()
The stopTranscription() method, accesible from the Meeting class, is used to stop the live captions in a live stream.
Example
- Kotlin
 - Java
 
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import live.videosdk.rtc.android.Meeting
import live.videosdk.rtc.android.VideoSDK
import live.videosdk.rtc.android.meeting.SummaryConfig
import live.videosdk.rtc.android.meeting.TranscriptionConfig
class LiveStreamActivity : AppCompatActivity() {
    private lateinit var liveStream: Meeting
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_stream)
        // Initialize the meeting (replace with actual meeting ID and token)
        liveStream = VideoSDK.initMeeting(... )
        val startCaptionsButton: Button = findViewById(R.id.btn_start_captions)
        val stopCaptionsButton: Button = findViewById(R.id.btn_stop_captions)
        startCaptionsButton.setOnClickListener {
            startRealtimeTranscription()
        }
        stopCaptionsButton.setOnClickListener {
            stopRealtimeTranscription()
        }
    }
    private fun startRealtimeTranscription() {
        val webhookUrl = "https://www.example.com"
        val summaryConfig = SummaryConfig(
            true,
            "Write summary in sections like Title, Agenda, Speakers, Action Items, Outlines, Notes and Summary"
        )
        val transcriptionConfig = TranscriptionConfig(
            webhookUrl,
            summaryConfig
        )
        liveStream.startTranscription(transcriptionConfig)
    }
    private fun stopRealtimeTranscription() {
        liveStream.stopTranscription()
    }
}
public class LiveStreamActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live_stream);
        // Initialize the meeting
        Meeting liveStream = VideoSDK.initMeeting( ...);
        Button startCaptionsButton = findViewById(R.id.btn_start_captions);
        Button stopCaptionsButton = findViewById(R.id.btn_stop_captions);
        startCaptionsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startRealtimeTranscription();
            }
        });
        stopCaptionsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopRealtimeTranscription();
            }
        });
    }
    private void startRealtimeTranscription() {
        String webhookUrl = "https://www.example.com";
        SummaryConfig summaryConfig = new SummaryConfig(
                true,
                "Write summary in sections like Title, Agenda, Speakers, Action Items, Outlines, Notes and Summary"
        );
        TranscriptionConfig transcriptionConfig = new TranscriptionConfig(
                webhookUrl,
                summaryConfig
        );
        liveStream.startTranscription(transcriptionConfig);
    }
    private void stopRealtimeTranscription() {
        liveStream.stopTranscription();
    }
}
Events associated with live captioning
- All participants-including all the hosts and audience members will receive a callback on the 
onTranscriptionStateChangedevent with the current state of the captioning. - All participants-including all the hosts and audience members will receive a callback on the 
onTranscriptionTextevent with the latest captions whenever a host speaks. 
- Kotlin
 - Java
 
private val meetingEventListener: MeetingEventListener = object : MeetingEventListener() {
  override fun onTranscriptionStateChanged(data: JSONObject) {
    try {
        val status = data.getString("status")
        val id = data.getString("id")
        when (status) {
            TranscriptionState.TRANSCRIPTION_STARTING.name -> Log.d("onTranscriptionStateChanged", "Realtime Transcription is starting, ID: $id")
            TranscriptionState.TRANSCRIPTION_STARTED.name -> Log.d("onTranscriptionStateChanged", "Realtime Transcription is started, ID: $id")
            TranscriptionState.TRANSCRIPTION_STOPPING.name -> Log.d("onTranscriptionStateChanged", "Realtime Transcription is stopping, ID: $id")
            TranscriptionState.TRANSCRIPTION_STOPPED.name -> Log.d("onTranscriptionStateChanged", "Realtime Transcription is stopped, ID: $id")
            else -> Log.d("onTranscriptionStateChanged", "Unknown transcription state: $status, ID: $id")
        }
    } catch (e: JSONException) {
        Log.e("onTranscriptionStateChanged", "Error parsing transcription state", e)
    }
  }
  override fun onTranscriptionText(data: TranscriptionText) {
    val participantId: String = data.participantId
    val participantName: String = data.participantName
    val text: String = data.text
    val timestamp: Int = data.timestamp
    val type: String = data.type
    Log.d("onTranscriptionText", "$participantName: $text $timestamp")
  }
}
override fun onCreate(savedInstanceState: Bundle?) {
  //...
  // add listener to meeting
  liveStream!!.addEventListener(meetingEventListener)
}
private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
  @Override
    public void onTranscriptionStateChanged(JSONObject data) {
        try {
            String status = data.getString("status");
            String id = data.getString("id");
            if (TranscriptionState.TRANSCRIPTION_STARTING.name().equals(status)) {
                Log.d("onTranscriptionStateChanged", "Realtime Transcription is starting, ID: " + id);
            }
            else if (TranscriptionState.TRANSCRIPTION_STARTED.name().equals(status)) {
                Log.d("onTranscriptionStateChanged", "Realtime Transcription is started, ID: " + id);
            }
            else if (TranscriptionState.TRANSCRIPTION_STOPPING.name().equals(status)) {
                Log.d("onTranscriptionStateChanged", "Realtime Transcription is stopping, ID: " + id);
            }
            else if (TranscriptionState.TRANSCRIPTION_STOPPED.name().equals(status)) {
                Log.d("onTranscriptionStateChanged", "Realtime Transcription is stopped, ID: " + id);
            }
            else {
                Log.d("onTranscriptionStateChanged", "Unknown transcription state: " + status + ", ID: " + id);
            }
        } catch (JSONException e) {
            Log.e("onTranscriptionStateChanged", "Error parsing transcription state", e.getMessage());
        }
    }
    @Override
    public void onTranscriptionText(TranscriptionText data) {
        String participantId = data.getParticipantId();
        String participantName = data.getParticipantName();
        String text = data.getText();
        int timestamp = data.getTimestamp();
        String type = data.getType();
        Log.d("onTranscriptionText", participantName + ": " + text + " " + timestamp);
    }
}
@Override
protected void onCreate(Bundle savedInstanceState) {
  //...
  // add listener to meeting
  liveStream.addEventListener(meetingEventListener);
}
API Reference
The API references for all the methods utilized in this guide are provided below.
Got a Question? Ask us on discord

