Sariska Media provides a robust suite of Kotlin APIs designed to streamline the development of real-time android applications. With Sariska, you can seamlessly integrate a variety of features.
With Pre-built Artifacts
For older Android Studio versions:
In your project's root directory, locate the build.gradle file.
Add the following code block within the repositories section:
For newer Android Studio versions:
In your project's root directory, locate the settings.gradle file.
Add the following code block within the repositories section:
With Maven
Add the dependency:
After installing the Sariska Media Transport SDK, begin by initializing it.
Media Services utilizes WebSockets to establish a continuous, two-way communication channel between your application and the server. This persistent connection offers significant advantages over traditional HTTP requests, particularly in terms of responsiveness.
Create a Jitsi-powered conference for real-time audio and video.
A MediaStream consists of various audio or video tracks represented by MediaStreamTrack objects. Each track can have multiple channels, which are the smallest units of the stream (e.g., left and right audio channels in stereo).
This event is triggered when a new user joins the conference. Moderators have exclusive control over meetings and can manage participants. To assign a moderator, set the moderator value to true when generating the token.
Make audio and video streams visible to others in the conference by publishing them using the following code:
Sariska-media-transport offers pre-configured events to help you track and analyze user interactions, media usage, and overall performance. This data can be used to enhance your product, improve user experience, and make informed decisions.
Available Events
Here are some of the key events you can track:
User Actions:
User joined
User left
Media Usage:
Add Event Listener to Track Events
Sariska offers powerful features to enhance your application's capabilities. Find your desired feature using the search bar or explore below!
Identify the main speaker: Easily detect the active or dominant speaker in a conference. Choose to stream only their video for improved resolution and reduced bandwidth usage. Ideal for one-way streaming scenarios like virtual concerts.
Dynamically showcase recent speakers: Focus on the active conversation by displaying video only for the last N participants who spoke. This automatically adjusts based on speech activity, offering a more efficient and relevant view.
Set local participant properties: Define additional information about participants beyond the default settings. This can include screen-sharing status, custom roles, or any other relevant attributes.
Get the total number of participants: Retrieve the complete participant count, including both visible and hidden members.
Access all participants: Obtain a list of all participants, including their IDs and detailed information.
Pin a single participant: Give a participant higher video quality (if simulcast is enabled).
Pin multiple participants: Give multiple participants higher video quality.
Retrieve information about the local user directly from the conference object.
Set the subject of the meeting.
Get all remote tracks: Retrieve a list of all remote tracks (audio and video) in the conference.
Get all local tracks: Retrieve a list of all local tracks (audio and video)
Listen for participant kick events
Kick a participant
The room creator has a moderator role, while other users have a participatory role.
Grant owner rights
Listen for role changes
Revoke owner rights
Setting a new display name
Listen for display name changes
Lock room: Moderators can restrict access to the room with a password.
Unlock room: Removes any existing password restriction.
Request subtitles: Enable subtitles for spoken content.
Request language translation: Translate subtitles into a specific language.
Receive subtitles: Listen for incoming subtitles.
Stop subtitles: Disable subtitles.
Each participant can contribute two types of data to a meeting: audio and video. Screen sharing counts as a video track. If you want to share your screen while also showing your own video (like when presenting), you need to enable "Presenter mode". This mode hides the gallery of other participants' videos and gives you more control over the meeting layout.
Start screen share: Share your screen with other participants.
Sariska offers robust messaging capabilities for both private and group communication scenarios.
Send a group message to all participants
Send a private message to a specific participant
Listen for incoming messages
Start Transcription: Initiate transcription for the ongoing conference.
Stop Transcription: Stop transcription and get a download link for the transcript.
Mute Remote Participant
Mute/Unmute Local Participant
Local Connection Statistics Received
Remote Connection Statistics Received
The SDK features intelligent auto-join/leave functionality based on internet connectivity status. This helps optimize network resources and improve user experience.
Designed for efficient communication between two participants.
Start Peer-to-Peer Mode
Sariska automatically activates Peer-to-Peer mode when your conference has exactly two participants. This mode bypasses the central server and directly connects participants, maximizing bandwidth efficiency and reducing latency. However, even with more than two participants, you can forcefully start Peer-to-Peer mode.
Stop Peer-to-Peer Mode
If you need to revert to server-mediated communication, you can easily stop Peer-to-Peer mode.
Monitor your WebRTC application performance using CallStats (or build your own). See the "RTC Stats" section for details.
Join conferences with audio and video already muted, or in a silent mode where no audio is transmitted or received. This ensures a seamless experience and respects participant preferences.
Join with Muted Audio and Video
Join in Silent Mode
Broadcast your conference to multiple platforms simultaneously. Embed live streams directly into your app or website using various formats.
Stream to YouTube
Stream to Facebook
Stream to Twitch
Stream to any RTMP Server
Listen for RECORDER_STATE_CHANGED event to track streaming status
Stop Live Stream
Store your recordings and transcriptions in various cloud storage services.
Dial-in(PSTN)
Dial-out(PSTN)
This allows synchronous phone calls, similar to WhatsApp, even if the receiver's app is closed or in the background.
Initiating Calls:
Make a call even if the callee's app is closed or in the background.
Play a busy tone if the callee is on another call or disconnects your call.
Play ringtone/ringback/DTMF tones.
Step 1 : Caller Initiates Call
HTTP Call to Sariska Server
{API Method}
Push Notification to callee using Firebase or APNS
This notifies the receiver even if their app is closed or in the background.
Step 2 : Callee Responds to Call
Reads Push Notification
Processes the notification even if the app is closed or in the background.
HTTP Call to Update Status
{API Method}
No need to join conference via SDK
Status update through the HTTP call suffices.
Step 3 : Caller Receives Response
Listens for USER_STATUS_CHANGED event
Step 4 : After Connection Established
The call proceeds like a normal conference call.
startVideoMuted: true
startSilent: true
rtcstatsServer: ""
callStatsID: ""
callStatsSecret: ""
channelLastN: 10
Purpose: Specifies which devices to request from the browser's GetUserMedia (GUM) API.
Default: If this property is not set, GUM will attempt to access all available devices.
resolution:
Type: String
Values: 180, 240, 360, vga, 480, qhd, 540, hd, 720, fullhd, 1080, 4k, 2160
Purpose: Sets the preferred resolution for the local video stream.
cameraDeviceId
Type: String
Purpose: Specifies the device ID of the camera to use.
micDeviceId
Type: String
Purpose: Specifies the device ID of the microphone to use.
minFps
Type: Integer
Purpose: Sets the minimum frame rate for the video stream.
maxFps
Type: Integer
Purpose: Sets the maximum frame rate for the video stream.
desktopSharingFrameRate
Type: Object
Properties:
min: Minimum frame rate for desktop sharing
max: Maximum frame rate for desktop sharing
desktopSharingSourceDevice
Type: String
Purpose: Specifies the device ID or label of the video input source to use for screen sharing.
facingMode
Type: String
Values: "user", "environment"
Purpose: Sets the camera's facing mode (front-facing or back-facing).
view.setZOrderOnTop(0)Participant Removal:
Ability to kick non-moderators or even other moderators from the meeting.
Audio Control:
Ability to mute individual participants or all participants at once.
Video Focus:
Ability to make everyone's video view follow the moderator's video.
Joining Settings: Ability to:
Set participants to join with audio muted by default.
Set participants to join with video disabled by default.
Lobby Management:
Ability to enable or disable the lobby room, requiring approval for participants to join.
Join Approval:
Ability to approve or deny join requests when the lobby is enabled.
Moderator Transfer:
If the current moderator leaves the meeting, a new moderator is automatically selected.
Type: String
Purpose: May be used for identification or communication purposes.
moderator:
Type: Boolean
Purpose: Used to control moderation-related features in the UI.
audioMuted:
Type: Boolean
Purpose: Used to display the audio muted state in the UI.
videoMuted:
Type: Boolean
Purpose: Used to display the video muted state in the UI.
displayName:
Type: String
Purpose: Used to identify them in the UI.
role:
Type: String
Purpose: Used to determine their permissions and UI features.
status:
Type: String
Purpose: Used to display ("online", "offline", "away") their availability in the UI.
hidden:
Type: Boolean
Purpose: Typically used for bots like transcribers or recorders.
botType:
Type: String
Purpose: Used to identify the bot's purpose and capabilities.
Conference duration
Camera duration
Audio track duration
Video track duration
Recording:
Recording started
Recording stopped
Local recording started
Local recording stopped
Transcription:
Transcription started
Transcription stopped
Performance:
Speaker stats
Connection stats
Performance stats
Danish
de
German
el
Greek
en
English
enGB
English (United Kingdom)
eo
Esperanto
es
Spanish
esUS
Spanish (Latin America)
et
Estonian
eu
Basque
fi
Finnish
fr
French
frCA
French (Canadian)
he
Hebrew
hi
Hindi
hr
Croatian
hu
Hungarian
hy
Armenian
id
Indonesian
it
Italian
ja
Japanese
kab
Kabyle
ko
Korean
lt
Lithuanian
ml
Malayalam
lv
Latvian
nl
Dutch
oc
Occitan
fa
Persian
pl
Polish
pt
Portuguese
ptBR
Portuguese (Brazil)
ru
Russian
ro
Romanian
sc
Sardinian
sk
Slovak
sl
Slovenian
sr
Serbian
sq
Albanian
sv
Swedish
te
Telugu
th
Thai
tr
Turkish
uk
Ukrainian
vi
Vietnamese
zhCN
Chinese (China)
zhTW
Chinese (Taiwan)
mr
Marathi
Enter the required credentials for your chosen provider
Dropbox
Obtain a Dropbox OAuth token
connected: receiver accepted your call
expired: receiver didn't answer within 40 seconds
af
Afrikaans
ar
Arabic
bg
Bulgarian
ca
Catalan
cs
Czech
da
allprojects {
// Add the Sariska repository
repositories {
maven {
url "https://github.com/SariskaIO/sariska-maven-repository/raw/master/releases"
}
// Add other repositories
google()
mavenCentral()
maven { url 'https://www.jitpack.io' }
}
}dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url "https://github.com/SariskaIO/sariska-maven-repository/raw/master/releases"
}
maven {
url "https://maven.google.com"
}
}
}dependencies {
implementation 'io.sariska:sariska-media-transport:5.4.9'
}import io.sariska.sdk.SariskaMediaTransport;
import io.sariska.sdk.Connection;
import io.sariska.sdk.Conference;
import io.sariska.sdk.JitsiRemoteTrack;
import io.sariska.sdk.JitsiLocalTrack;
import io.sariska.sdk.Participant;
SariskaMediaTransport.initializeSdk();// Replace {your-token} with your actual Sariska token
val token = {your-token}
// Create a connection object
val connection = SariskaMediaTransport.JitsiConnection(token, "roomName", isNightly)
// Add event listeners for connection status
connection.addEventListener("CONNECTION_ESTABLISHED"), {
// Handle successful connection establishment
}
connection.addEventListener("CONNECTION_FAILED"), { error->
if (error === PASSWORD_REQUIRED) {
// Token expired, update the connection with a new token
connection.setToken(token)
}
}
connection.addEventListener("CONNECTION_DISCONNECTED"), {
// Handle connection disconnection
}
// Connect to the Sariska server
connection.connect()// Create a conference object using the connection and optional configuration
val conference = connection.initJitsiConference(options);
// Join the conference
conference.join();// Define options for local stream capture
val options = Bundle()
// Enable audio and video tracks in the stream
options.putBoolean("audio", true)
options.putBoolean("video", true)
// Set desired video resolution
options.putInt("resolution", 240) // Specify desired resolution
// ... (additional options for desktop sharing, facing mode, devices, etc.)
// Create local audio and video tracks based on the options
SariskaMediaTransport.createLocalTracks(options) { tracks ->
localTracks = tracks;
}runOnUiThread(() -> {
// Loop through each local track
for (JitsiLocalTrack track : localTracks) {
if (track.getType().equals("video")) {
// Get the view for rendering the video track
val view = track.render();
// Set the view to fill the container
view.setObjectFit("cover");
// Add the video view to the container layout
mLocalContainer.addView(view);
}
}
})conference.addEventListener("USER_JOINED", (id, participant)=>{
});// Loop through all local tracks
for (JitsiLocalTrack track : localTracks) {
// Add the track to the conference, allowing others to see/hear you
conference.addTrack(track);
}// Add an event listener to the conference for "TRACK_ADDED" events
conference.addEventListener("TRACK_ADDED") { p ->
// Cast the event object to a JitsiRemoteTrack instance
val track: JitsiRemoteTrack = p as JitsiRemoteTrack
// Run code on the UI thread
runOnUiThread {
// Check if the track type is video
if (track.getType().equals("video")) {
// Render the video track using Jitsi's WebRTCView component
val view: WebRTCView = track.render()
// Set the view to cover the entire container
view.setObjectFit("cover")
// Store the view for potential later reference
remoteView = view
// Add the view to the container layout, displaying the remote video
mRemoteContainer!!.addView(view)
}
}
}conference.startTracking();conference.addEventListener("DOMINANT_SPEAKER_CHANGED") { p ->
// participantId is a string containing the ID of the dominant speaker
val participantId = p as String
}// Listen for last N speakers changed event
conference.addEventListener("LAST_N_ENDPOINTS_CHANGED") { leavingEndpointIds, enteringEndpointIds ->
// leavingEndpointIds: Array of IDs of users leaving lastN
// enteringEndpointIds: Array of IDs of users entering lastN
};
// Set the number of last speakers to show
conference.setLastN(10)// Set local participant property
conference.setLocalParticipantProperty(key, value);
// Remove a local participant property
conference.rempveLocalParticipantProperty(key)
// Get the value of a local participant property
conference.getLocalParticipantProperty(key)
// Listen for changes in participant properties
conference.addEventListener("PARTICIPANT_PROPERTY_CHANGED"){ participant, key, oldValue, newValue ->
}conference.getParticipantCount();
// Pass true to include hidden participants// Get all participants
conference.getParticipants(); // List of all participants
// Get participants excluding hidden users
conference.getParticipantsWithoutHidden(); // List of all participantsconference.selectParticipant(participantId) // Select participant with IDconference.selectParticipants(participantIds) // Select participant with IDs// Check if the local user is hidden
conference.isHidden()
// Get local user details
confernece.getUserId()
conference.getUserRole()
conference.getUserEmail()
conference.getUserAvatar()
conference.getUserName()conference.setSubject(subject)conference.getRemoteTracks();conference.getLocalTracks()conference.addEventListener("KICKED"){ id ->
// Handle participant kicked
};
conference.addEventListener("PARTICIPANT_KICKED") { actorParticipant, kickedParticipant, reason ->
}confernece.kickParticipant(id)conference.grantOwner(id) // Grant owner rights to a participantconference.addEventListener("USER_ROLE_CHANGED"){ id, role ->
if (confernece.getUserId() === id ) {
// My role changed, new role: role;
} else {
// Participant role changed: role;
}
};conference.revokeOwner(id) // Revoke owner rights from a participantconference.setDisplayName(name); // Change the local user's display nameconference.addEventListener("DISPLAY_NAME_CHANGED"){ id, displayName->
// Access the participant ID
};conference.lock(password); // Lock the room with the specified passwordconference.unlock();conference.setLocalParticipantProperty("requestingTranscription", true);conference.setLocalParticipantProperty("translation_language", 'hi'); // Example for Hindiconference.addEventListener("SUBTITLES_RECEIVED"){ id, name, text->
// Handle received subtitle data (id, speaker name, text)
};conference.setLocalParticipantProperty("requestingTranscription", false);// Create a desktop track
val options = new Bundle();
options.putBoolean("desktop", true);
val videoTrack = localTracks[1]; // Participant's local video track
SariskaMediaTransport.createLocalTracks(options, tracks -> {
conference.replaceTrack(videoTrack, tracks[0]);
});conference.sendMessage("message");conference.sendMessage("message", participantId);// Add an event listener to handle incoming messages
conference.addEventListener("MESSAGE_RECEIVED" ){ message, senderId->
// Process the received message
});conference.startTranscriber();conference.stopTranscriber();conference.muteParticipant(participantId, mediaType)
// participantId: ID of the participant to be muted
// mediaType: Type of media to mute ('audio' or 'video')// Mute a local track (audio or video)
track.mute()
// Unmute a previously muted local track
track.unmute()conference.addEventListener(event: "LOCAL_STATS_UPDATED"){ stats in
// Handle local connection statistics
}conference.addEventListener(event: "REMOTE_STATS_UPDATED") { id, stats->
// Handle remote connection statistics
}conference.startP2PSession();conference.stopP2PSession();val options = new Bundle();
options.putString("callStatsID", 'callstats-id');
options.putString("callStatsSecret", 'callstats-secret');
val conference = connection.initJitsiConference(options);val options = new Bundle();
options.putBoolean("startAudioMuted", true);
options.putBoolean("starVideoMuted", true);
val conference = connection.initJitsiConference(options);val options = new Bundle();
options.putBoolean("startSilent", true);
val confernce = connection.initJitsiConference(options);val options = new Bundle();
options.putString("broadcastId", "youtubeBroadcastID"); // Put any string this will become part of your publish URL
options.putString("mode", "stream");
options.putString("streamId", "youtubeStreamKey");
// Start live stream
conference.startRecording(options);val options = new Bundle();
options.putString("mode", "stream");
options.putString("streamId", "rtmps://live-api-s.facebook.com:443/rtmp/FB-4742724459088842-0-AbwKHwKiTd9lFMPy");
// Start live stream
conference.startRecording(options);val options = new Bundle();
options.putString("mode", "stream");
options.putString("streamId", "rtmp://live.twitch.tv/app/STREAM_KEY");
// Start live stream
conference.startRecording(options); val options = new Bundle();
options.putString("mode", "stream");
options.putString("streamId", "rtmps://rtmp-server/rtmp"); // RTMP server URL
// Start live stream
conference.startRecording(options);conference.addEventListener("RECORDER_STATE_CHANGED"){ sessionId, mode, status in
// Verify mode is "stream"
// Get the live streaming session ID
// Check the streaming status: on, off, or pending
};conference.stopRecording(sessionId);// Configure for Object-based storage
val options = new Bundle();
options.putString("mode", "file");
options.putString("serviceName", "s3");
// Configure for Dropbox
val options = new Bundle();
options.putString("mode", "file");
options.putString("serviceName", "dropbox");
options.putString("token", "dropbox_oauth_token");
// Start recording
conference.startRecording(options);
// Monitor recording state
conference.addEventListener("RECORDER_STATE_CHANGED"){ sessionId, mode, status ->
val sessionId = sessionId as String; // Unique identifier for the cloud recording session
val mode = mode as String; // Recording mode (e.g., "file")
val status = status as String; // Current recording status ("on", "off", or "pending")
// Handle recording state changes based on mode, sessionId, and status
});
// Stop recording
conference.stopRecording(sessionId)// Retrieve the phone pin and number for users to join via PSTN:
val phonePin = conference.getPhonePin() // Get the phone pin for PSTN access
val phoneNumber = conference.getPhoneNumber() // Get the phone number for PSTN access // Dial a phone number to invite a participant to the conference
conference.dial(phoneNumber)// Join the lobby
conference.joinLobby(displayName, email); // Request to join the conference lobby
// Event listeners for lobby-related actions:
conference.addEventListener("LOBBY_USER_JOINED"){ id, name ->
// Handle events when a user joins the lobby
val id = id as String;
val name = name as String
})
conference.addEventListener(event: "LOBBY_USER_UPDATED"), { id, participant ->
// Handle events when a user's information in the lobby is updated
val id = id as String;
val name = participant as Participant
}
// Additional event listeners for lobby actions:
conference.addEventListener(event: "LOBBY_USER_LEFT") { id ->
val id = id as String;
}
conference.addEventListener(event: "MEMBERS_ONLY_CHANGED") { enabled ->
val enabled = enabled as Boolean;
}
// Moderator actions for lobby access:
conference.lobbyDenyAccess(participantId); // Deny access to a participant in the lobby
conference.lobbyApproveAccess(participantId); // Approve access to a participant in the lobby
// Lobby management methods:
conference.enableLobby() // Enable lobby mode for the conference (moderator only)
conference.disableLobby(); // Disable lobby mode for the conference (moderator only)
conference.isMembersOnly(); // Check if the conference is in members-only mode (lobby disabled)// Initiate a SIP video call
conference.startSIPVideoCall("[email protected]", "display name"); // Start a SIP video call with the specified address and display name
// Terminate a SIP video call
conference.stopSIPVideoCall('[email protected]');
// Event listeners for SIP gateway state changes
conference.addEventListener("VIDEO_SIP_GW_SESSION_STATE_CHANGED", (state)=>{
// Handle events when the SIP gateway session state changes (on, off, pending, retrying, failed)
}
// Event listener for SIP gateway availability changes
conference.addEventListener("VIDEO_SIP_GW_AVAILABILITY_CHANGED"){ status ->
// Handle events when the SIP gateway availability changes (busy or available)
}conference.addEventListener(event: "USER_STATUS_CHANGED"){ id, status ->
val id = id as! String;
val status = status as!
// - id: receiver's user id
// - status: "ringing", "busy", "rejected", "connected", "expired"
};