Skip to main content
Version: 0.x.x

Relay Media(PK Host) - Android

Overview​

The Relay Media feature enables hosts to relay their media (audio, video, screen share) to one or multiple other live streams. This creates cross-stream interactions similar to "PK battles" or collaborative broadcasts.

This feature allows audiences in one live stream to view and hear hosts from another live stream without changing rooms, creating powerful interactive experiences.

Key Concepts​

  • Media Relay: The process of transmitting a host's audio/video from one live stream to another
  • Source Meeting: The original live stream where the host is broadcasting
  • Destination Meeting: The target live stream(s) where the host's media will be relayed
  • Relay Kinds: The types of media that can be relayed (video, audio, screen share, etc.)

Sequence Diagram​

sequenceDiagram participant HostA as Host A participant HostB as Host B participant AudienceB as Audience B HostA->>HostB: requestMediaRelay(meetingB_Id, token, kinds) HostB-->>HostB: mediaRelayRequestReceived event alt Accept HostB->>HostA: accept() HostA-->>HostA: mediaRelayRequestResponse("accepted") HostA-->>HostA: mediaRelayStarted(meetingB_Id) HostA->>AudienceB: Media streaming else Reject HostB->>HostA: reject() HostA-->>HostA: mediaRelayRequestResponse("rejected") end HostA->>HostB: stopMediaRelay(meetingB_Id) HostA-->>HostA: mediaRelayStopped(meetingB_Id, reason);

Implementation Guide​

1. Requesting Media Relay​

requestMediaRelay()​

Parameters:

  • destinationMeetingId (String, required) – ID of the target meeting
  • token (String) – Authentication token for the destination meeting.
    If you pass null, the SDK will use the existing authentication token.
  • kinds (Array<String>) – Media types to relay. If null, all media types will be relayed. Options:
    • "video" – Camera video
    • "audio" – Microphone audio
    • "share" – Screen share video
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import live.videosdk.rtc.android.Meeting

class LiveStreamActivity : AppCompatActivity() {
//Initialize meeting
liveStream = VideoSDK.initMeeting(... )
//...
val switchButton: Button = findViewById(R.id.switchLiveStreamButton)
switchButton.setOnClickListener {
requestMediaRelayToAnotherMeeting()
}

fun requestMediaRelayToAnotherMeeting() {
val liveStreamId = "liveStream-B"
// Secure token to authenticate the relay meeting
val relayToken = "secureToken123"
// Specify the media types to relay
val mediaTypes = listOf("video", "audio")
// Request media relay
liveStream.requestMediaRelay(liveStreamId, relayToken, mediaTypes)
}
}

2. Handling Relay Requests (Destination Meeting)​

In the destination liveStream, hosts (participants with SEND_AND_RECV mode) will receive relay requests:

import com.google.android.material.dialog.MaterialAlertDialogBuilder
import live.videosdk.rtc.android.Meeting
import live.videosdk.rtc.android.listeners.MeetingEventListener

class LiveStreamView() {
init {
// initialize initialize
liveStream = VideoSDK.initMeeting(... )
// ...
// Set up media relay request listener
liveStream.addEventListener(object : MeetingEventListener() {
override fun onMediaRelayRequestReceived(participantId: String, liveStreamId: String, listener:RelayRequestListener) {
showRelayRequest(participantId, liveStreamId, listener)
}
})
}

private fun showRelayRequest(participantId: String,liveStreamId: String,listener: RelayRequestListener) {
MaterialAlertDialogBuilder(this@MainActivity)
.setTitle("Entry Request : $participantId")
.setMessage("$liveStreamId is requesting to join")
.setPositiveButton("Approve") { dialog, _ -> listener.accept() }
.setNegativeButton("Deny") { dialog, _ -> listener.reject() }
.setCancelable(false)
.show()
}

}

3. Handling Request Responses (Source Meeting)​

In the source liveStream, track the response to your relay requests:

import android.content.Context
import android.widget.Toast
import live.videosdk.rtc.android.Meeting
import live.videosdk.rtc.android.listeners.MeetingEventListener

class LiveStreamView() {
//initialize initialize
liveStream = VideoSDK.initMeeting(... )

init {
// Set up media relay request response listener
liveStream.addEventListener(object : MeetingEventListener() {
override fun onMediaRelayRequestResponse(participantId: String, decision: String) {
handleMediaRelayResponse(participantId, decision)
}
})
}

// Handling the media relay request response
private fun handleMediaRelayResponse(participantId: String, decision: String) {
if (decision == "accepted") {
// Relay request accepted by participant
println("Relay request accepted by $participantId")
} else {
// Relay request rejected by participant
println("Relay request rejected by $participantId")
}
}
}

4. Tracking Active Relays​

When a relay successfully starts:

import android.util.Log
import live.videosdk.rtc.android.Meeting
import live.videosdk.rtc.android.listeners.MeetingEventListener

class LiveStreamView() {
// initialize meeting
liveStream = VideoSDK.initMeeting(... )
// ...
companion object {
private const val TAG = "LiveStreamView"
}
init {
// Set up media relay started listener
liveStream.addEventListener(object : MeetingEventListener() {
override fun onMediaRelayStarted(liveStreamId: String) {
handleMediaRelayStarted(liveStreamId)
}
})
}
// Called when media relay starts
private fun handleMediaRelayStarted(liveStreamId: String) {
Log.d(TAG, "Media relay started to $liveStreamId")
// You can update UI or handle logic here
}
}

5. Stopping Media Relay​

To stop an ongoing relay:

stopMediaRelay()​

Parameters:

  • liveStreamId (string): ID of the liveStream where the relay should stop
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import live.videosdk.rtc.android.Meeting

class LiveStreamActivity : AppCompatActivity() {
// Initialize meeting
liveStream = VideoSDK.initMeeting(... )
//..
val stopRelayButton = findViewById<Button>(R.id.btnStopRelay)

stopRelayButton.setOnClickListener {
handleStopMediaRelay()
}

// Called to stop media relay
private fun handleStopMediaRelay() {
val liveStreamId = "liveStream-B"
liveStream.stopMediaRelay(liveStreamId)
}
}

6. Handling Relay Stop Events​

When a relay stops for any reason:

import android.util.Log
import live.videosdk.rtc.android.Meeting
import live.videosdk.rtc.android.listeners.MeetingEventListener

class LiveStreamView() {
// initialize meeting
val liveStream = VideoSDK.initMeeting(... )
// ...
companion object {
private const val TAG = "LiveStreamView"
}

fun setupListeners() {
liveStream.addEventListener(object : MeetingEventListener() {
override fun onMediaRelayStopped(liveStreamId: String, reason: String) {
handleMediaRelayStopped(liveStreamId, reason)
}
})
}

private fun handleMediaRelayStopped(liveStreamId: String, reason: String) {
Log.d(TAG, "Relay to $liveStreamId stopped. Reason: $reason")
// Update UI based on stop reason
when (reason) {
"user_stopped" -> showMessage("You stopped relaying to $liveStreamId")
"connection_lost" -> showMessage("Relay to $liveStreamId ended due to connection issues")
else -> showMessage("Relay to $liveStreamId ended: $reason")
}
}

private fun showMessage(message: String) {
Log.i(TAG, message)
}
}

7. Handling Relay Errors​

To handle errors that may occur during relay:

import android.util.Log
import live.videosdk.rtc.android.Meeting
import live.videosdk.rtc.android.listeners.MeetingEventListener

class LiveStreamView() {
// initialize meeting
val liveStream = VideoSDK.initMeeting(... )
// ...
companion object {
private const val TAG = "LiveStreamView"
}

private fun setupListeners() {
liveStream.addEventListener(object : MeetingEventListener() {
override fun onMediaRelayError(liveStreamId: String, error: String) {
handleMediaRelayError(liveStreamId, error)
}
})
}

private fun handleMediaRelayError(liveStreamId: String, error: String) {
Log.e(TAG, "Relay error to $liveStreamId: $error")
}
}

Use Cases​

  1. Guest Appearances: Allow popular hosts to make guest appearances in other streams without leaving their audience
  2. Cross-Stream Competitions: Create "battles" or competitions between hosts in different streams
  3. Multi-Location Broadcasting: Connect hosts from different physical locations into a shared experience
  4. Expert Commentary: Bring in subject matter experts to comment on events in another stream

Troubleshooting​

Common Issues​

  1. Relay Request Not Received

    • Verify both meetings are active
    • Check that destination liveStream ID is correct
    • Ensure the token has proper permissions
  2. Media Not Visible After Acceptance

    • Verify network connectivity
    • Check that appropriate media kinds were specified
    • Ensure the host has enabled their camera/microphone
  3. Unexpected Relay Termination

    • Check for network connectivity issues
    • Verify that both meetings remain active
    • Look for error events with specific reasons

API Reference​

Got a Question? Ask us on discord