Empower your mobile applications with seamless real-time communication and media functionalities using the powerful Sariska Media Swift APIs. Integrate features like audio/video calling, live streaming, cloud recording, transcriptions, and language translation effortlessly into your iOS, macOS, watchOS, and tvOS apps.
Installation
Step 1 : Install Sariska Media Transport Client
With CocoaPods
pod 'sariska-media-transport', :git => 'https://github.com/SariskaIO/sariska-ios-sdk-releases.git', tag:'1.1.5', :branch => 'master'
Step 2 : Initialize SDK
// Import the Sariska framework to access its classesimportsariska// Perform initial setup tasksSariskaMediaTransport.initializeSdk();
Step 3 : Establish a WebSocket Connection
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.
let token = {your-token} // Replace with your actual tokenself.connection = SariskaMediaTransport.jitsiConnection(tokens, roomName:"roomname", isNightly:false)// Add event listeners for connection eventsself.connection?.addEventListener("CONNECTION_ESTABLISHED", callback: { self.createConference()// Create conference when connection is established})// Add event listeners for connection eventsself.connection?.addEventListener("CONNECTION_FAILED", callback: {})// Add event listeners for connection eventsself.connection?.addEventListener("CONNECTION_DISCONNECTED", callback: {})// Add event listeners for connection eventsself.connection.addEventListener(event:"PASSWORD_REQUIRED", () {})// Establish the connectionself.connection?.connect(){}
Step 4 : Initiate a Conference
Create a Jitsi-powered conference for real-time audio and video.
conference = connection.initJitsiConference(options)// Add event listeners for conference eventsconference?.addEventListener("CONFERENCE_JOINED") {// Add local tracks to the conference when joinedfor track in self.localTracks { self.conference?.addTrack(track: track) }}// Add event listeners for conference eventsconference?.addEventListener("TRACK_ADDED") { track inlet track = track as! JitsiRemoteTrack DispatchQueue.main.async {if(track.getType()=="video") {let videoView = track.render() self.attachVideo(videoView: videoView, trackId: track.getId()) } }}// Add event listeners for conference eventsconference?.addEventListener("TRACK_REMOVED") { track inlet track = track as! JitsiRemoteTrack DispatchQueue.main.async { self.removeVideo(trackId: track.getId()) }}// Add event listeners for conference events conference?.addEventListener("CONFERENCE_LEFT") {print("CONFERENCE_LEFT")}// Join the conferenceconference.join();
Customize conference
To join with audio muted
startAudioMuted: true
To join with video muted
startVideoMuted: true
To join with startSilent no audio receive/send
startSilent: true
To enable rtcstats tracking analytics
rtcstatsServer: ""
CallStats ID
callStatsID: ""
CallStats Secret
callStatsSecret: ""
Last n speakers
channelLastN: 10
Step 5 : Capture Local Stream
Media Stream
A MediaStream is a collection of audio or video tracks, represented by MediaStreamTrack objects.
Each MediaStreamTrack can have multiple channels (e.g., left and right channels in a stereo audio track).
Capture Local Tracks
Define options:
Specify desired devices ("audio", "video", or "desktop").
Set preferred video resolution.
Optionally configure specific devices, frame rates, screen sharing options, and facing mode.
// Define options for capturing local audio and video tracksvar options:[String:Any] = [:]options["audio"]=trueoptions["video"]=trueoptions["resolution"]=true// Specify desired resolution// ... (additional options for desktop sharing, facing mode, devices, etc.)// Create local tracks with the specified optionsSariskaMediaTransport.createLocalTracks(options){// Handle local tracks once created}
Customize tracks
devices:
Type: Array of strings
Values: "desktop", "video", "audio"
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.
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).
Step 6 : Play Local Stream
DispatchQueue.main.async {// Iterate through local tracksfor track in localTracks {// If the track is a video trackif(track.getType()=="video") {// Render the track into a video viewlet videoView = track.render()// Configure view properties// Set object fit to "cover" (fill the view, potentially cropping) videoView.setObjectFit("cover")// Set height and width constraints videoView.heightAnchor.constraint(equalToConstant:240).isActive =true videoView.widthAnchor.constraint(equalToConstant:360).isActive =true// Add the video view as a subview self.view.addSubview(videoView) } }}
Additional view properties
videoView.setMirror(true or false): Toggles video mirroring (default is false).
videoView.setObjectFit("contain" or "cover"): Sets how the video fills the view (default is "cover").
Audio playback is handled automatically with the video stream.
Step 7 : Handle User Joined Event
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.
Moderator permissions
Password Protection:
Ability to add a password to the meeting room, restricting access.
Role Assignment:
Ability to grant moderator privileges to other participants.
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.
Purpose: Used to display their profile picture in the UI.
email:
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.
Step 8 : Publish Streams
Make audio and video streams visible to others in the conference by publishing them using the following code:
for track in localTracks { conference?.addTrack(track: track)}
Step 9 : Play Remote Peers Streams
conference?.addEventListener(event:"TRACK_ADDED") { track inlet track = track as! JitsiRemoteTrack DispatchQueue.main.async {// If the track is a video trackif(track.getType()=="video") {// Render and display the remote video tracklet videoView = track.render()// Configure view properties// Set object fit to "cover" (fill the view, potentially cropping) videoView.setObjectFit("cover")// Set height and width constraints videoView.heightAnchor.constraint(equalToConstant:240).isActive =true videoView.widthAnchor.constraint(equalToConstant:360).isActive =true// Add the video view as a subview self.view.addSubView(videoView) } }}
Analytics
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.
action: The action associated with the event (string)
actionSubject: The subject of the action (string)
source: The source of the event (string)
attributes: Additional attributes of the event (JSON)
Features
Sariska offers powerful features to enhance your application's capabilities. Find your desired feature using the search bar or explore below!
Active/Dominant Speaker
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.
conference?.addEventListener(event:"DOMINANT_SPEAKER_CHANGED") { id in// id is a string representing the ID of the dominant speaker}
Last N Speakers
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.
// Listen for last N speakers changed eventconference?.addEventListener(event:"LAST_N_ENDPOINTS_CHANGED"){ leavingEndpointIds, enteringEndpointIds in// leavingEndpointIds: Array of IDs of users leaving lastN// enteringEndpointIds: Array of IDs of users entering lastN};// Set the number of last speakers to showconference?.setLastN(10)
Participant Information
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.
// Set a local participant property conference?.setLocalParticipantProperty(key, value);// Remove a local participant property conference?.removeLocalParticipantProperty(key)// Get the value of a local participant property conference?.getLocalParticipantProperty(key)// Listen for changes in participant propertiesconference?.addEventListener(event:"PARTICIPANT_PROPERTY_CHANGED"){ participant, key, oldValue, newValue in}
Participant Count
Get the total number of participants: Retrieve the complete participant count, including both visible and hidden members.
conference?.getParticipantCount(); // Pass true to include hidden participants
Some conferences may include hidden participants besides attendees, such as bots assisting with recording, transcription, or pricing.
Participant Lists
Access all participants: Obtain a list of all participants, including their IDs and detailed information.
// Get all participantsconference?.getParticipants(); // List of all participants// Get participants excluding hidden usersconference?.getParticipantsWithoutHidden(); // List of all participants
Pinning Participants
Pin a single participant: Give a participant higher video quality (if simulcast is enabled).
conference?.selectParticipant(participantId)// Select participant with ID
Pin multiple participants: Give multiple participants higher video quality.
conference?.selectParticipants(participantIds)// Select participants with IDs
Access Local User Details
Retrieve information about the local user directly from the conference object.
// Check if the local user is hiddenconference?.isHidden()// Get local user detailsconfernece?.getUserId()conference?.getUserRole()conference?.getUserEmail()conference?.getUserAvatar()conference?.getUserName()
Set Meeting Subject
Set the subject of the meeting.
conference?.setSubject(subject)
Manage Tracks
Get all remote tracks: Retrieve a list of all remote tracks (audio and video) in the conference.
conference?.getRemoteTracks();
Get all local tracks: Retrieve a list of all local tracks (audio and video)
conference?.getLocalTracks()
Kick Participants
Listen for participant kick events
conference?.addEventListener(event:"KICKED"){ id in// Handle participant kicked};conference?.addEventListener(event:"PARTICIPANT_KICKED"){ actorParticipant, kickedParticipant, reason in}
Kick a participant
conference?.kickParticipant(id)
Kick a moderator
conference?.kickParticipant(id, reason)// Kick a moderator, providing a reason for the kick
Manage Owner Roles
The room creator has a moderator role, while other users have a participatory role.
Grant owner rights
conference?.grantOwner(id)// Grant owner rights to a participant
Listen for role changes
conference?.addEventListener(event:"USER_ROLE_CHANGED"){ id, role inif(conference.getUserId()=== id ) {// My role changed, new role: role; } else {// Participant role changed: role; }};
Revoke owner rights
conference?.revokeOwner(id)// Revoke owner rights from a participant
Change Display Names
Setting a new display name
conference?.setDisplayName(name); // Change the local user's display name
Listen for display name changes
conference?.addEventListener(event:"DISPLAY_NAME_CHANGED") { id, displayName in// Access the participant ID};
Lock/Unlock Room
Lock room: Moderators can restrict access to the room with a password.
conference?.lock(password); // Lock the room with the specified password
Unlock room: Removes any existing password restriction.
conference?.unlock();
Subtitles
Request subtitles: Enable subtitles for spoken content.
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.
var options:[String:Any] = [:]options["desktop"]=truelet videoTrack = localTracks[1]SariskaMediaTransport.createLocalTracks(options: options) { tracks in conference.replaceTrack(videoTrack, tracks[0])}
Messages
Sariska offers robust messaging capabilities for both private and group communication scenarios.
Send a group message to all participants
conference.sendMessage("message");
Send a private message to a specific participant
conference.sendMessage("message", participantId);
Listen for incoming messages
// Add an event listener to handle incoming messagesconference.addEventListener("MESSAGE_RECEIVED")){ message, senderId in// Process the received message});
Transcription
Start Transcription: Initiate transcription for the ongoing conference.
conference.startTranscriber();
Stop Transcription: Stop transcription and get a download link for the transcript.
conference.stopTranscriber();
Mute/Unmute Participants
Mute Remote Participant
track.muteParticipant(participantId, mediaType);// participantId: ID of the participant to be muted// mediaType: Type of media to mute ('audio' or 'video')
The moderator has the ability to temporarily silence the microphone of any participant who is not physically present in the meeting room.
Mute/Unmute Local Participant
// Mute a local track (audio or video)track.mute()// Unmute a previously muted local tracktrack.unmute()
Connection Quality
Local Connection Statistics Received
conference.addEventListener(event:"LOCAL_STATS_UPDATED"){ stats in// Handle local connection statistics}
The SDK features intelligent auto-join/leave functionality based on internet connectivity status. This helps optimize network resources and improve user experience.
Peer-to-Peer Mode
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.
conference.startP2PSession();
Starting Peer-to-Peer mode eliminates server charges as long as the central turn server remains unused.
Stop Peer-to-Peer Mode
If you need to revert to server-mediated communication, you can easily stop Peer-to-Peer mode.
conference.stopP2PSession();
CallStats Integration
Monitor your WebRTC application performance using CallStats (or build your own). See the "RTC Stats" section for details.
var options:[String:Any] = [:]options["callStatsID"]= 'callstats-id';options["callStatsSecret"]= 'callstats-secret';let conference = connection.initJitsiConference(options);
Join Muted/Silent
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
var options:[String:Any] = [:]options["startAudioMuted"]=true;options["startVideoMuted"]=true;const conference = connection.initJitsiConference(options);
Join in Silent Mode
var options:[String: Any] = [:]
options["startSilent"] = true;
let conference = connection.initJitsiConference(options);
Live Stream
Broadcast your conference to multiple platforms simultaneously. Embed live streams directly into your app or website using various formats.
Stream to YouTube
var options:[String: Any] = [:]
options["broadcastId"] = "youtubeBroadcastID"; ; // Put any string this will become part of your publish URL
options["mode"] = "stream";
options["streamId"] = "youtubeStreamKey";
// Start live stream
conference.startRecording(options);
Stream to Facebook
var options:[String: Any] = [:]
options["mode"] = "stream";
options["streamId"] = "rtmps://live-api-s.facebook.com:443/rtmp/FB-4742724459088842-0-AbwKHwKiTd9lFMPy";
// Start live stream
conference.startRecording(options);
Stream to Twitch
var options:[String: Any] = [:]
options["mode"] = "stream";
options["streamId"] = "rtmp://live.twitch.tv/app/STREAM_KEY";
// Start live stream
conference.startRecording(options);
Stream to any RTMP Server
var options:[String: Any] = [:]
options["mode"] = "stream";
options["streamId"] = "rtmps://rtmp-server/rtmp"; // RTMP server URL
// Start live stream
conference.startRecording(options);
Listen for RECORDER_STATE_CHANGED event to track streaming status
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
};
Stop Live Stream
conference.stopRecording(sessionId);
Cloud Recording
Store your recordings and transcriptions in various cloud storage services.
Supported storage providers
Object-based storage: Amazon S3, Google Cloud Storage, Azure Blob Storage, other S3-compatible cloud providers.
Dropbox
Set credentials
Object-based storage
Access your Sariska dashboard
Locate the storage credentials section
Enter the required credentials for your chosen provider
Dropbox
Obtain a Dropbox OAuth token
// Configure for Object-based storage
var options:[String: Any] = [:]
options["mode"] = "file";
options["serviceName"] = "s3";
// Configure for Dropbox
var options:[String: Any] = [:]
options["token"] = "dropbox_oauth_token";
options["mode"] = "file";
options["serviceName"] = "dropbox";
// Start recording
conference.startRecording(options);
// Monitor recording state
conference.addEventListener(event: "RECORDER_STATE_CHANGED") { sessionId, mode, status in
let sessionId = sessionId as! String; // Unique identifier for the cloud recording session
let mode = mode as! String; // Recording mode (e.g., "file")
let 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)
PSTN
Dial-in(PSTN)
// Retrieve the phone pin and number for users to join via PSTN:
let phonePin = conference.getPhonePin() // Get the phone pin for PSTN access
let phoneNumber = conference.getPhoneNumber() // Get the phone number for PSTN access
Share this phone number and pin with users to enable PSTN conference call participation.
Dial-out(PSTN)
// Dial a phone number to invite a participant to the conference
conference.dial(phoneNumber)
This initiates a call to the provided phone number, inviting them to join the conference.
Lobby/Waiting Room
// Join the lobby
conference.joinLobby(displayName, email); // Request to join the conference lobby
// Event listeners for lobby-related actions:
conference.addEventListener(event: "LOBBY_USER_JOINED") { id, name in
// Handle events when a user joins the lobby
}
conference.addEventListener(event: "LOBBY_USER_UPDATED"), { id, participant in
// Handle events when a user's information in the lobby is updated
}
// Additional event listeners for lobby actions:
conference.addEventListener(event: "LOBBY_USER_LEFT") { id in
}
conference.addEventListener(event: "MEMBERS_ONLY_CHANGED"){ enabled in
}
// 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)
SIP Video Gateway
// Initiate a SIP video call
conference.startSIPVideoCall("address@sip.domain.com", "display name"); // Start a SIP video call with the specified address and display name
// Terminate a SIP video call
conference.stopSIPVideoCall('address@sip.domain.com');
// Event listeners for SIP gateway state changes
conference.addEventListener(event: "VIDEO_SIP_GW_SESSION_STATE_CHANGED") { state in
// Handle events when the SIP gateway session state changes (on, off, pending, retrying, failed)
}
// Event listener for SIP gateway availability changes
conference.addEventListener(event: "VIDEO_SIP_GW_AVAILABILITY_CHANGED"){ status in
// Handle events when the SIP gateway availability changes (busy or available)
}
One-to-One Calling
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
conference.addEventListener(event: "USER_STATUS_CHANGED"){ id, status in
let id = id as! String;
let status = status as!
// - id: receiver's user id
// - status: "ringing", "busy", "rejected", "connected", "expired"
};