Gcore named a Leader in the GigaOm Radar for AI Infrastructure!Get the report
  1. Home
  2. Blog
  3. How to launch real-time communications for iOS/Android
Network
Developers

How to launch real-time communications for iOS/Android

  • March 13, 2023
  • 9 min read
How to launch real-time communications for iOS/Android

The phrase real-time communications (RTC) refers to any live telecommunications method in which all users can interact in a live capacity, with negligible latency. In other words, a phone or video call. And it can be a valuable feature for an application to provide its users with, even if it’s not the app’s core purpose.

For example, Instagram has interactive broadcasts with guests in Live Rooms, and direct video calling features, despite being a platform for mostly sharing pre-recorded images and video. This way, Instagram keeps users in its app. If interlocutors want to call, they don’t need to navigate to another RTC app—they just need to click a ring button in the Instagram interface.

If you’re considering adding an RTC feature to your application, stick around. We’ll show you step by step how to launch a real-time communication SDK in 15 minutes, for both iOS and Android.

The real-time communication SDK would look like this:

A brief comparison of RTC platforms

Before we begin, let’s do a brief RTC platform comparison. You may already be aware of some of the biggest providers, like Agora, Twilio, and Gcore, but let’s take a closer look at what each of them offer to help narrow which is the best option for RTC.

 GcoreAgoraTwilioZoomJitsi
Ease of integrationPrebuilt SDK with low coding effortCustom SDK requires high coding effortSDK requires manual integration and configuration with high coding effortSDK has two predefined roles; customization is not possibleDevs must manually configure permissions for peers in a call
ScalabilityMax of 100 speakers and 2,000 attendeesMax of 128 hosts and 1,000,000 participants, including hostsMax of 50 hosts and 50 participants, including hostsMax of 1,000 participants including the hostsMax of 100 hosts and 100 participants, including hosts.
PricingFree up to 50K minutesBase price $3.99; complicated pricing plans and policiesHas a free tier and paid tier charged per participant minute starting at $0.0015Free up to 10,000 minutesFree, open-source

Our platform works well for the purposes of this tutorial as we’re focusing on video calls with a simple implementation. Let’s launch the Gcore’s real-time communication SDK in 15 minutes.

Implementing Real-time Video Call for iOS

This article covers implementation for GCoreVideoCallsSDK version 2.5.1.

Before we begin with the iOS part of this tutorial, there are a few requirements you’ll need to make sure you’re up to date on:

You can check out the final iOS demo project on GitHub to further your understanding of this tutorial.

The demo features a production-ready GCore videocall SDK implementation, written in a way that’s easy to read and understand. This demo project should help you gain a deeper understanding of all features of the SDK.

Installing the Gcore SDK

First, you need to install dependencies. Create a podfile and add the following:

Plaintext
pod "mediasoup_ios_client", '1.5.3'

This allows you to use mediasoup which is a framework that will allow you to make video calls on iOS.

Next, launch your terminal and change the directory to your project folder. Enter:

Plaintext
pod install

This installs the library media_ios_client into your project.

Open Xcode and drag the GCoreVideoCallsSDK.xcframework to the root of the project folder.

Make sure Copy items if needed is checked, and then click Finish.

Now, in the project target, navigate to General > Framework, Libraries, and Embedded Content. There, set the Embed value to Embed & Sign for GCoreVideoCallsSDK.xcframework.

In the Build Settings of the target, set ENABLE_BIT CODE = No and Validate Workspace = Yes.

In Info.plist, add a description for the parameters NSCameraUsageDescription and NSMicrophoneUsageDescription.

Create and join a room

Before you can create or join a room, there are a few steps you have to complete.

First, import dependencies:

Plaintext
import GCoreVideoCallsSDK import WebRTC

Activate logger; this code block facilitates communication between the client and the server:

Plaintext
GCoreRoomLogger.activateLogger()

Set the parameters for connecting to the server. The first code block here sets the front camera as the default camera to be used in the video call:

Plaintext
let options = RoomOptions(cameraPosition: .front)
Plaintext
let parameters = MeetRoomParametrs ( roomId: "SampleVideoCall0123", displayName: "John Smith", peerId: "", clientHostName: "meet.gcore.com" )
ParameterTypeDescription
roomIdStringRoom ID to connect to; clients with matching IDs are grouped together. Example: roomId: "SampleVideoCall0123".
displayNameStringSets the display name of the participant. Example: displayName: "Jane Doe".
peerIdString (optional)ID of a participant from your internal system; please specify userID if you have your own. Can be left blank as value will auto-generate. Example: peerId: "user0000000001".
clientHostNameString (optional)Client passes the domain name that it uses to operate the web version of meet. Value: domain only without specifying the protocol. Example: clientHostName: "meet.gcore.com".

Create an instance of the client and connect:

Plaintext
var client: GCoreRoomClient? client = GCoreRoomClient(roomOptions: options, requestParameters: parameters, roomListener: self) try? client?.open()

This creates a room, using the front camera and setting the roomId as SampleVideoCall0123 and the displayName as John Smith, as defined before. John’s device is set as the listener to events happening in the room.

I’ll talk more about events later on.

Now, activate the audio session, which allows the client to listen and speak:

Plaintext
client?.audioSessionActivate()

Listen to room events

Any real-time communication SDK needs to be able to listen to room events to simulate interaction on a live capacity, such as when someone joins a group discussion, raises their hand to ask a question to introduce themselves and more.

Examples of room events:

  • A peer joining or leaving
  • The moderator admitting or expelling peers
  • The moderator muting everyone
  • Peers interacting with their microphones and cameras
  • Changes in user information, like a new moderator has been assigned

Fortunately, the Gcore SDK comes with a RoomListener delegate class, which you’ll use to listen in on events.

For error events:

Plaintext
func roomClientHandle(error: RoomError) ///handles errors in the room

For connection events:

Plaintext
func roomClientStartToConnectWithServices()///Initiates connecting the SDKfunc roomClientSuccessfullyConnectWithServices()///Notify that a successful connection has occurredfunc roomClientDidConnected()///Notify client successfully connects to server/roomfunc roomClientReconnecting()///Notify client is connecting to the room, eg, after network failurefunc roomClientReconnectingFailed()///Notify of a reconnection failurefunc roomClientSocketDidDisconnected(roomClient: GCoreRoomClient)///Notify that connection to the server has been lost

For guests joining or leaving:

Plaintext
func roomClient(roomClient: GCoreRoomClient, handlePeer: PeerObject)///Notify room members that peer joined the roomfunc roomClient(roomClient: GCoreRoomClient, peerClosed: String)//Notify room members that peer left the room

Note that the peerClosed parameter contains the ID of the peer who left the room.

For audio and video events:

Plaintext
func roomClient(roomClient: GCoreRoomClient, produceLocalVideoTrack videoTrack: RTCVideoTrack)///Local client notifies peers that their video is onfunc roomClient(roomClient: GCoreRoomClient, produceLocalAudioTrack audioTrack: RTCAudioTrack)///Local client notifies peers that their audio is onfunc roomClient(roomClient: GCoreRoomClient, didCloseLocalVideoTrack videoTrack: RTCVideoTrack?)//Local client notifies peers that their video is offfunc roomClient(roomClient: GCoreRoomClient, didCloseLocalAudioTrack audioTrack: RTCAudioTrack?)///Local client notifies peers that their audio is offfunc roomClient(roomClient: GCoreRoomClient, handledRemoteVideo videoObject: VideoObject)///Peers notify local clients about the state of their video stream(on/off).func roomClient(roomClient: GCoreRoomClient, produceRemoteAudio audioObject: AudioObject)

Let me break some of that down:

  • roomClient is an instance of the GCoreRoomClient class, which contains information about the room and its participants.
  • videoTrack contains information about the video stream.
  • audioObject contains information about the audio stream.

For changes in user info:

Plaintext
func roomClient( roomClient: GCoreRoomClient, updateMeInfo: UpdateMeInfoObject)

This function is called when the user’s information changes. It takes in a parameter of type UpdateMeInfoObject, which contains all of the new information about the user. That includes:

  • peerId: The id of the peer who’s info has changed.
  • displayName: The display name for this peer.
  • isModerator: Whether or not this peer is a moderator.
  • isAudioOnly: Whether or not this peer has audio only enabled.
  • isVideoOnly: Whether or not this peer has video only enabled.
  • isScreenShareOnly: Whether or not this peer has screen share only enabled.

For session info events:

Plaintext
func roomClient( roomClient: GCoreRoomClient, captureSession: AVCaptureSession, captureDevice: AVCaptureDevice)

This is a function that allows you to set the camera and microphone settings. It takes three parameters:

  • roomClient: A reference to an object that implements the GCoreRoomClient protocol. This parameter is required and cannot be nil.
  • captureSession: A reference to an object of type AVCaptureSession, which allows you to configure the camera settings. This parameter is required and cannot be nil.
  • captureDevice: A reference to an object of type AVCaptureDevice, which allows you to configure the microphone settings. Again, this parameter is required and cannot be nil.

Listen to moderator events

Moderator events are actions triggered by the admin of the room, such as:

  • Creating and closing the room
  • Muting and unmuting participants
  • Admitting or expelling participants

For a moderator closing someone else’s video or audio:

Plaintext
func roomClient(roomClient: GCoreRoomClient, didCloseRemoteVideoByModerator byModerator: Bool, videoObject: VideoObject)///Moderator closed peer videofunc roomClient(roomClient: GCoreRoomClient, didCloseRemoteAudioByModerator byModerator: Bool, audioObject: AudioObject)///Moderator closed peer audio

This function takes three parameters:

  • roomClient: The room client contains all the information about the current room.
  • byModerator: A Boolean value that indicates whether it was closed by a moderator or not.
  • videoObject: An object containing all the information about the video stream.
  • audioObject: An object containing all the information about the audio track.

The following function notifies a waiting peer that the moderator has not yet accepted the user’s request to join the room. The peer receives a message that says You are waiting for permission from the moderator.

Plaintext
func roomClientWaitingForModeratorJoinAccept()

This function notifies a waiting peer that the moderator has rejected their request to enter the room. The peer receives a message that says You have been rejected by the moderator.

Plaintext
func roomClientModeratorRejectedJoinRequest()

This function notifies a moderator of a request to join a room:

Plaintext
func roomClient( roomClient: GCoreRoomClient, moderatorIsAskedToJoin: ModeratorIsAskedToJoin)

This function notifies a peer that a moderator has removed them. The function itself doesn’t do anything, but you can use it to add custom functionality, like displaying an alert message to the user that they’ve been removed from the room.

Plaintext
func roomClientRemovedByModerator()

Toggle a user’s mic and cam

Use the following code to set the user video:

Plaintext
func roomClientDidConnected() { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.client?.toggleVideo(isOn: true) self.client?.toggleAudio(isOn: true) } }

This is called when the client connects to a room. After one second, the video and audio turn on. Set the Boolean value in (isOn: true) to false to turn off the corresponding feature.

Display remote user video

If the connection is successful, a method is called that returns all the participants in the room, saves them, and draws elements to display the participants:

Plaintext
func joinWithPeersInRoom(_ peers: [PeerObject]) { peers.forEach { peer in let remoteItem = GCLRemoteItem(peerObject: peer) remoteItems.insert(remoteItem) mainScrollView.addSubview(remoteItem.view) }}

When a new participant enters a room, this adds them to the array of connected participants and to the ScrollView, respectively:

Plaintext
func handledPeer(_ peer: PeerObject) { let remoteItem = GCLRemoteItem(peerObject: peer) remoteItems.insert(remoteItem) mainScrollView.addSubview(remoteItem.view)}

When a participant disconnects, this removes them from the array:

Plaintext
func peerClosed(_ peer: String) { if let remoteItem = remoteItems.first(where: { $0.peerId == peer }) { remoteItem.view.removeFromSuperview() remoteItems.remove(remoteItem) }}

Implementing real-time video call for Android

Before we begin with the Android part of this tutorial, there are a few requirements you’ll need to make sure you’re up to date on:

You can check out the Android demo project on GitHub if you want to follow along with it for this tutorial.

As with the iOS version of the tutorial, this demo features a production-ready GCore videocall SDK implementation, written in a way that’s easy to read and understand. Through this demo project, you’ll get a better understanding of the features of the SDK. The SDK’s simplicity makes it perfect for rapid prototyping and experimentation.

Installing the Gcore SDK

Copy GCoreVideoCallsSDK and mediasoup-android-client to the root of your project folder.

Add them both to your app/build.gradle file in the dependencies section:

Plaintext
implementation project(':GCoreVideoCallsSDK')implementation project(':mediasoup-android-client')

Include them in settings.gradle as follows:

Plaintext
include ':mediasoup-android-client'include ':GCoreVideoCallsSDK'

Import the dependencies from the SDK archive, but go ahead and add the following in the dependencies section of app/build.gradle as well:

Plaintext
implementation 'androidx.core:core-ktx:1.7.0'implementation 'androidx.appcompat:appcompat:1.4.1'implementation 'com.google.android.material:material:1.5.0'implementation 'androidx.constraintlayout:constraintlayout:2.1.3'testImplementation 'junit:junit:4.13.2'androidTestImplementation 'androidx.test.ext:junit:1.1.3'androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'implementation("androidx.fragment:fragment-ktx:1.4.1")implementation("androidx.navigation:navigation-fragment-ktx:2.4.2")implementation("androidx.navigation:navigation-ui-ktx:2.4.2")implementation "androidx.lifecycle:lifecycle-extensions:$LIFECYCLE_VERSION"implementation "com.google.dagger:dagger:$DAGGER_VERSION"kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"implementation "com.jakewharton.timber:timber:$TIMBER_VERSION"implementation("io.reactivex.rxjava2:rxjava:$RX_JAVA_VERSION")implementation("io.reactivex.rxjava2:rxandroid:$RX_VERSION")implementation "org.protoojs.droid:protoo-client:$PROTO_VERSION"implementation("com.squareup.okhttp3:okhttp:$OKHTTP_VERSION")implementation("com.squareup.okhttp3:logging-interceptor:$OKHTTP_VERSION")def camerax_version = "1.1.0-rc01"implementation("androidx.camera:camera-core:${camerax_version}")implementation("androidx.camera:camera-camera2:${camerax_version}")implementation("androidx.camera:camera-lifecycle:${camerax_version}")implementation("androidx.camera:camera-view:${camerax_version}")

In the plugins section in app/build.gradle, include:

Plaintext
id 'kotlin-kapt'

Create a new file in the root directory of the project and name it versions.gradle. Go ahead and add the following:

Plaintext
ext { KOTLIN_VERSION = "1.5.30" CORE_KTX_VERSION = "1.6.0" ANDROID_GRADLE_PLUGIN_VERSION = '4.0.0' PROTO_VERSION = "4.0.3" DRIOD_VERSION = "3.0.8-beta-3" LIFECYCLE_VERSION = "2.2.0" COROUTINE_VERSION = "1.5.0" DAGGER_VERSION = '2.37' RX_JAVA_VERSION = "2.2.17" RX_VERSION = "2.1.1" TIMBER_VERSION = "4.7.1" LOGGING_INTERCEPTOR_VERSION = '4.9.0' OKHTTP_VERSION = '4.9.0'}

In the build.gradle file, add:

Plaintext
buildscript { apply from: 'versions.gradle'}

In the settings.gradle file, add the following pluginManagement{} and dependencyResolutionManagement{}:

Plaintext
maven {url ' https://jitpack.io '}jcenter()

It should look something like this:

Now, resync the project!

Set user permissions

The Gcore SDK requires internet connection and access to microphone and camera. Requesting those permissions takes just a couple steps.

First, to declare the permissions, navigate to AndroidManifest.xml in app/src/main and add the following:

Plaintext
<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.CALL_PHONE"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

And finally, request the permissions:

Plaintext
if (!allPermissionGranted()) { requestPermissions.launch(REQUIRED_PERMISSIONS) }companion object { private val REQUIRED_PERMISSIONS = arrayOF( Manifest.permission.CAMERA, Manifest.permision.RECORD_AUDIO)}

Create and join a room

Creating or joining a room requires a few steps. First, initialize the Gcore SDK:

Plaintext
GCoreMeet.instance.init( applicationContext: Application, logger: null, enableLogs: false)

Then define the parameters for connecting to the server:

Plaintext
GCoreMeet.instance.clientHostName = "meet.gcore.com"GCoreMeet.instance.roomManager.displayName = "Jane Doe"GCoreMeet.instance.setRoomId("SampleVideoCall1234")GCoreMeet.instance.roomManager.peerId = ""GCoreMeet.instance.roomManager.isModer = true
MethodTypeDescription
setRoomIdStringRoom ID to connect to. Example: roomId: "SampleVideoCall1234".
ParameterTypeDescription
displayNameStringSet display name of participant. Example: displayName: "Jane Doe".
peerIdString (optional)ID of a participant from your internal system. Please specify userID, if you have your own or leave it blank to autogenerate. Example: peerId:"user0000000001".
clientHostNameString (optional)Client passes the domain name used to operate the web version of the meet. Value: domain only, no protocol specified. Example: clientHostName: "meet.gcore.com".
isModerBooleanIf true, then the user will be a moderator, with access to additional functionality.

Next, set audio and video:

Plaintext
GCoreMeet.instance.roomManager.options.startWithCam = trueGCoreMeet.instance.roomManager.options.startWithMic = true

And establish a connection to the server:

Plaintext
GCoreMeet.instance.startConnection(getApplication())

Finally, join the room:

Plaintext
if GCoreMeet.instance.roomManager.isClosed()) { GCoreMeet.instance.roomManager.join()}

At the end of a session, go ahead and close the room for all participants:

Plaintext
GCoreMeet.instance.roomManager.destroyRoom()

Display room members

To properly display the members of a room, this function observes the number of peers present in a room and changes the layout manager span count accordingly.

Plaintext
private val _layoutManagerSpanCount = MutableLiveData<Int>()val layoutManagerSpanCount: LiveData<Int> = _layoutManagerSpanCountprivate fun connect() { GCoreMeet.instance.getPeers().observeForever { peers: Peers? -> val peersCount = peers?.allPeers?.size ?: 0 if (peersCount > 1) { _layoutManagerSpanCount.value = 2 } else { _layoutManagerSpanCount.value = 1 } } }

Enable and disable user mic and cam

To enable and disable a microphone, respectively:

Plaintext
GCoreMeet.instance.roomManager.enableMic()GCoreMeet.instance.roomManager.disableMic()

To enable and disable a camera, respectively:

Plaintext
GCoreMeet.instance.roomManager.enableCam() GCoreMeet.instance.roomManager.disableCam()

Subscribe to room changes

The following functions provide notifications regarding changes to the room.

The state of the connection:

Plaintext
GCoreMeet.instance.roomManager.roomProvider.connected

What peers or members are in the room:

Plaintext
GCoreMeet.instance.roomManager.roomProvider.peers GCoreMeet.instance.getPeers()

What speakers are active:

Plaintext
GCoreMeet.instance.roomManager.roomProvider.roomInfo.observeForever{ roomInfo-> roomInfo.activeSpeakerIds roomInfo.connectionState}

In the previous function, room.ConnectionState can have the following states:

  • DISCONNECTED: No data is received from the server and no requests are sent to it.
  • CONNECTING: The connection with the server is established, but there is no information about other participants in the room yet.
  • CONNECTED: Connected to a room and receiving data from other participants in it.
  • RECONNECTING: The connection with the server was interrupted for some reason (for example, due to a network failure).

To be informed of changes in local user state:

Plaintext
roomManager.roomProvider.me.observeForever { localState: LocalState ->}

The following are possible returns for user state:

  • localState.isAudioMuted: Checks whether a user’s microphone is muted or not.
  • localState.isVideoMuted: Checks whether a user’s camera is on or not.
  • localState.isScreenSharingEnabled: Checks whether demonstration is enabled or not.

For changes in entry request state:

Plaintext
roomManager.roomProvider.waitingState.observeForever{state: WaitingState -> }

This function checks for changes to a join request with the following possible states:

  • NOTHING
  • IN_WAITING: Waiting for moderator response.
  • ACCEPTED: A moderator allowed a user entry.
  • REJECTED: A moderator denied a user entry.

For when a moderator kicks out a peer:

Plaintext
roomManager.roomProvider.closedByModerator.observeForever{}

For changes in a room’s permissions:

Plaintext
roomManager.roomProvider.micAllowed.observeForever{allowet: Boolean -> } roomManager.roomProvider.camAllowed.observeForever{allowet: Boolean -> } roomManager.roomProvider.acceptedAudioPermission.observeForever{}///Audio use is permitted in the room roomManager.roomProvider.acceptedVideoPermission.observeForever{}///Video use is permitted in the room

For a moderator’s response to peer:

Plaintext
roomManager.roomProvider.acceptedAudioPermissionFromModerator.observeForever{}///Mod allows use of audio in the roomroomManager.roomProvider.acceptedVideoPermissionFromModerator.observeForever{}///Mod allows use of video in the room

For changes in blocked user states, for example, if a user has a microphone or camera blocked, but wants to turn them on:

Plaintext
roomManager.askUserConfirmMic.observeForever{}roomManager.askUserConfirmCam.observeForever{}

For peer requests to moderator:

Plaintext
roomManager.roomProvider.requestToModerator.observeForever { data: RequestPeerData ->}

In the previous function, RequestPeerData contains userName, peerId, requestType. requestType can be AUDIO, VIDEO, and SHARE requests for microphone, camera, and demonstration, respectively.

Conclusion

With Gcore’s SDK, you’ve created and joined RTC rooms for both iOS and Android platforms. You’ve walked through enabling and disabling the microphone and camera, setting the client as moderator, and listening to changes in a meeting. You’re now equipped to implement video call features in your application, with an SDK that’s easy to integrate, easy to scale with, and affordable.

If you want to experiment further with Gcore’s SDK, remember that you can check out the iOS demo project and the Android demo project on Gcore’s GitHub.

Written by Michael Simiyu

Try Gcore Network

Gcore all-in-one platform: cloud, AI, CDN, security, and other infrastructure services.

Related articles

Gcore partners with AVEQ to elevate streaming performance monitoring

At Gcore, delivering exceptional streaming experiences to users across our global network is at the heart of what we do. We're excited to share how we're taking our CDN performance monitoring to new heights through our partnership with AVEQ and their innovative Surfmeter solution.Operating a massive global network spanning 210 points of presence across six continents comes with unique challenges. While our globally distributed caching infrastructure already ensures optimal performance for end-users, we recognized the need for deeper insights into the complex interactions between applications and our underlying network. We needed to move beyond traditional server-side monitoring to truly understand what our customers' users experience in the real world.Real-world performance visibilityThat's where AVEQ's Surfmeter comes in. We're now using Surfmeter to gain unprecedented visibility into our network performance through automated, active measurements that simulate actual streaming video quality, exactly as end-users experience it.This isn't about checking boxes or reviewing server logs. It's about measuring what users see on their screens at home. With Surfmeter, our engineering teams can identify and resolve potential bottlenecks or suboptimal configurations, and collaborate more effectively with our customers to continuously improve Quality of Experience (QoE).How we use SurfmeterAVEQ helps us simulate and analyze real-world scenarios where users access different video streams. Their software runs both on network nodes close to our data center CDN caches and at selected end-user locations with genuine ISP connections.What sets Surfmeter apart is its authentic approach: it opens video streams from the same platforms and players that end-users rely on, ensuring measurements truly represent real-world conditions. Unlike monitoring solutions that simply check stream availability, Surfmeter doesn't make assumptions or use third-party playback engines. Instead, it precisely replicates how video players request and decode data served from our CDN.Rapid issue resolutionWhen performance issues arise, Surfmeter provides our engineers with the deep insights needed to quickly identify root causes. Whether the problem lies within our CDN, with peering partners, or on the server side, we can pinpoint it with precision.By monitoring individual video requests, including headers and timings, and combining this data with our internal logging, we gain complete visibility and observability into our entire streaming pipeline. Surfmeter can also perform ping and traceroute tests from the same device, measuring video QoE, allowing our engineers to access all collected data through one API rather than manually connecting to devices for troubleshooting.Competitive benchmarking and future capabilitiesSurfmeter also enables us to benchmark our performance against other services and network providers. By deploying Surfmeter probes at customer-like locations, we can measure streaming from any source via different ISPs.This partnership reflects our commitment to transparency and data-driven service excellence. By leveraging AVEQ's Surfmeter solution, we ensure that our customers receive the best possible streaming performance, backed by objective, end-user-centric insights.Learn more about Gcore CDN

How we engineered a single pipeline for LL-HLS and LL-DASH

Viewers in sports, gaming, and interactive events expect real-time, low-latency streaming experiences. To deliver this, the industry has rallied around two powerful protocols: Low-Latency HLS (LL-HLS) and Low-Latency DASH (LL-DASH).While they share a goal, their methods are fundamentally different. LL-HLS delivers video in a sequence of tiny, discrete files. LL-DASH delivers it as a continuous, chunked download of a larger file. This isn't just a minor difference in syntax; it implies completely different behaviors for the packager, the CDN, and the player.This duality presents a major architectural challenge: How do you build a single, efficient, and cost-effective pipeline that can serve both protocols simultaneously from one source?At Gcore, we took on this unification problem. The result is a robust, single-source pipeline that delivers streams with a glass-to-glass latency of approximately 2.0 seconds for LL-DASH and 3.0 seconds for LL-HLS. This is the story of how we designed it.Understanding the dualityTo build a unified system, we first had to deeply understand the differences in how each protocol operates at the delivery level.LL-DASH: the continuous feedMPEG-DASH has always been flexible, using a single manifest file to define media segments by their timing. Low-Latency DASH builds on this by using Chunked CMAF segments.Imagine a file that is still being written to on the server. Instead of waiting for the whole file to be finished, the player can request it, and the server can send it piece by piece using Chunked Transfer Encoding. The player receives a continuous stream of bytes and can start playback as soon as it has enough data.Single, long-lived files: A segment might be 2–6 seconds long, but it’s delivered as it’s being generated.Timing-based requests: The player knows when a segment should be available and requests it. The server uses chunked transfer to send what it has so far.Player-driven latency: The manifest contains a targetLatency attribute, giving the player a strong hint about how close to the live edge it should play.LL-HLS: the rapid-fire deliveryLL-HLS takes a different approach. It extends the traditional playlist-based HLS by breaking segments into even smaller chunks called Parts.Think of it like getting breaking news updates. The server pre-announces upcoming Parts in the manifest before they are fully available. The player then requests a Part, but the server holds that request open until the Part is ready to be delivered at full speed. This is called a Blocking Playlist Reload.Many tiny files (Parts): A 2-second segment might be broken into four 0.5-second Parts, each requested individually.Manifest-driven updates: The server constantly updates the manifest with new Parts, and uses special tags like #EXT-X-PART-INF and #EXT-X-SERVER-CONTROL to manage delivery.Server-enforced timing: The server controls when the player receives data by holding onto requests, which helps synchronize all viewers.A simplified diagram visually comparing the LL-HLS delivery of many small parts versus the LL-DASH chunked transfer of a single, larger segment over the same time period.These two philosophies demand different things from a CDN. LL-DASH requires the CDN to intelligently cache and serve partially complete files. LL-HLS requires the CDN to handle a massive volume of short, bursty requests and hold connections open for manifest updates. A traditional CDN is optimized for neither.Forging a unified strategyWith two different delivery models, where do you start? You find the one thing they both depend on: the keyframe.Playback can only start from a keyframe (or I-frame). Therefore, the placement of keyframes, which defines the Group of Pictures (GOP), is the foundational layer that both protocols must respect. By enforcing a consistent keyframe interval on the source stream, we could create a predictable media timeline. This timeline can then be described in two different “languages” in the manifests for LL-HLS and LL-DASH.A single timeline with consistent GOPs being packaged for both protocols.This realization led us to a baseline configuration, but each parameter involved a critical engineering trade-off:GOP: 1 second. We chose a frequent, 1-second GOP. The primary benefit is extremely fast stream acquisition; a player never has to wait more than a second for a keyframe to begin playback. The trade-off is a higher bitrate. A 1-second GOP can increase bitrate by 10–15% compared to a more standard 2-second GOP because you're storing more full-frame data. For real-time, interactive use cases, we prioritized startup speed over bitrate savings.Segment Size: 2 seconds. A 2-second segment duration provides a sweet spot. For LL-DASH and modern HLS players, it's short enough to keep manifest sizes manageable. For older, standard HLS clients, it prevents them from falling too far behind the live edge, keeping latency reduced even on legacy players.Part Size: 0.5 seconds. For LL-HLS, this means we deliver four updates per segment. This frequency is aggressive enough to achieve sub-3-second latency while being coarse enough to avoid overwhelming networks with excessive request overhead, which can happen with part durations in the 100–200ms range.Cascading challenges through the pipeline1. Ingest: predictability is paramountTo produce a clean, synchronized output, you need a clean, predictable input. We found that the encoder settings of the source stream are critical. An unstable source with a variable bitrate or erratic keyframe placement will wreck any attempt at low-latency delivery.For our users, we recommend settings that prioritize speed and predictability over compression efficiency:Rate control: Constant Bitrate (CBR)Keyframe interval: A fixed interval (e.g., every 30 frames for 30 FPS, to match our 1s GOP).Encoder tune: zerolatencyAdvanced options: Disable B-frames (bframes=0) and scene-cut detection (scenecut=0) to ensure keyframes are placed exactly where you command them to be.Here is an example ffmpeg command in Bash that encapsulates these principles:ffmpeg -re -i "source.mp4" -c:a aac -c:v libx264 \ -profile:v baseline -tune zerolatency -preset veryfast \ -x264opts "bframes=0:scenecut=0:keyint=30" \ -f flv "rtmp://your-ingest-url"2. Transcoding and packagingOur transcoding and Just-In-Time Packaging (JITP) layer is where the unification truly happens. This component does more than just convert codecs; it has to operate on a stream that is fundamentally incomplete.The primary challenge is that the packager must generate manifests and parts from media files that are still being written by the transcoder. This requires a tightly-coupled architecture where the packager can safely read from the transcoder's buffer.To handle the unpredictable nature of live sources, especially user-generated content via WebRTC, we use a hybrid workflow:GPU Workers (Nvidia/Intel): These handle the heavy lifting of decoding and encoding. Offloading to GPU hardware is crucial for minimizing processing latency and preserving advanced color formats like HDR+.Software Workers and Filters: These provide flexibility. When a live stream from a mobile device suddenly changes resolution or its framerate drops due to a poor connection, a rigid hardware pipeline would crash. Our software layer can handle these context changes gracefully, for instance, by scaling the erratic source and overlaying it on a stable, black-background canvas, meaning the output stream never stops.This makes our JITP a universal packager, creating three synchronized content types from a single, resilient source:LL-DASH (CMAF)LL-HLS (CMAF)Standard HLS (MPEG-TS) for backward compatibility3. CDN delivery: solving two problems at onceThis was the most intensive part of the engineering effort. Our CDN had to be taught how to excel at two completely different, high-performance tasks simultaneously.For LL-DASH, we developed a custom caching module we call chunked-proxy. When the first request for a new .m4s segment arrives, our edge server requests it from the origin. As bytes flow in from the origin, the chunked-proxy immediately forwards them to the client. When a second client requests the same file, our edge server serves all the bytes it has already cached and then appends the new bytes to both clients' streams simultaneously. It’s a multi-client cache for in-flight data.For LL-HLS, the challenges were different:Handling Blocked Requests: Our edge servers needed to be optimized to hold thousands of manifest requests open for hundreds of milliseconds without consuming excessive resources.Intelligent Caching: We needed to correctly handle cache statuses (MISS, EXPIRED) for manifests to ensure only one request goes to the origin per update, preventing a "thundering herd" problem.High Request Volume: LL-HLS generates a storm of requests for tiny part-files. Our infrastructure was scaled and optimized to serve these small files with minimal overhead.The payoff: ultimate flexibility for developersThis engineering effort wasn't just an academic exercise. It provides tangible benefits to developers building with our platform. The primary benefit is simplicity through unification, but the most powerful benefit is the ability to optimize for every platform.Consider the complex landscape of Apple devices. With our unified pipeline, you can create a player logic that does this:On iOS 17.1+: Use LL-DASH with the new Managed Media Source (MMS) API for ~2.0 second latency.On iOS 14.0 - 17.0: Use native LL-HLS for ~3.0 second latency.On older iOS versions: Automatically fall back to standard HLS with a reduced latency of ~9 seconds.This lets you provide the best possible experience on every device, all from a single backend and a single live source, without any extra configuration.Don't fly blind: observability in a low-latency worldA complex system is useless without visibility, and traditional metrics can be misleading for low-latency streaming. Simply looking at response_time from a CDN log is not enough.We had to rethink what to measure. For example:For an LL-HLS manifest, a high response_time (e.g., 500ms) is expected behavior, as it reflects the server correctly holding the request while waiting for the next part. A low response_time could actually indicate a problem. We monitor “Manifest Hold Time” to ensure this blocking mechanism is working as intended.For LL-DASH, a player requesting a chunk that isn't ready yet might receive a 404 Not Found error. While occasional 404s are normal, a spike can indicate origin-to-edge latency issues. This metric, combined with monitoring player liveCatchup behavior, gives a true picture of stream health.Gcore: one pipeline to serve them allThe paths of LL-HLS and LL-DASH may be different, but their destination is the same: real-time interaction with a global audience. By starting with a common foundation—the keyframe—and custom-engineering every component of our pipeline to handle this duality, we successfully solved the unification problem.The result is a single, robust system that gives developers the power of both protocols without the complexity of running two separate infrastructures. It’s how we deliver ±2.0s latency with LL-DASH and ±3.0s with LL-HLS, and it’s the foundation upon which we’ll build to push the boundaries of real-time streaming even further.

Gcore CDN updates: Dedicated IP and BYOIP now available

We’re pleased to announce two new premium features for Gcore CDN: Dedicated IP and Bring Your Own IP (BYOIP). These capabilities give customers more control over their CDN configuration, helping you meet strict security, compliance, and branding requirements.Many organizations, especially in finance and other regulated sectors, require full control over their network identity. With these new features, Gcore enables customers to use unique, dedicated IP addresses to meet compliance or security standards; retain ownership and visibility over IP reputation and routing, and deliver content globally while maintaining trusted, verifiable IP associations.Read on for more information about the benefits of both updates.Dedicated IP: exclusive addresses for your CDN resourcesThe Dedicated IP feature enables customers to assign a private IP address to their CDN configuration, rather than using shared ones. This is ideal for:Businesses that are subject to strict security or legal frameworks.Customers who want isolated IP resources to ensure consistent access and reputation.Teams using WAAP or other advanced security solutions where dedicated IPs simplify policy management.BYOIP: bring your own IP range to Gcore CDNWith Bring Your Own IP (BYOIP), customers can use their own public IP address range while leveraging the performance and global reach of Gcore CDN. This option is especially useful for:Resellers who prefer to keep Gcore infrastructure invisible to end clients.Enterprises maintaining brand consistency and control over IP reputation.How to get startedBoth features are currently available as paid add-ons and are configured manually by the Gcore team. To request activation or learn more, please contact Gcore Support or your account manager.We’re working on making these features easier to manage and automate in future releases. As always, we welcome your feedback on both the feature functionality and the request process—your insights help us improve the Gcore CDN experience for everyone.Get in touch for more information

Smart caching and predictive streaming: the next generation of content delivery

As streaming demand surges worldwide, providers face mounting pressure to deliver high-quality video without buffering, lag, or quality dips, no matter where the viewer is or what device they're using. That pressure is only growing as audiences consume content across mobile, desktop, smart TVs, and edge-connected devices.Traditional content delivery networks (CDNs) were built to handle scale, but not prediction. They reacted to demand, but couldn’t anticipate it. That’s changing.Today, predictive streaming and AI-powered smart caching are enabling a proactive, intelligent approach to content delivery. These technologies go beyond delivering content by forecasting what users will need and making sure it's there before it's even requested. For network engineers, platform teams, and content providers, this marks a major evolution in performance, reliability, and cost control.What are predictive streaming and smart caching?Predictive streaming is a technology that uses AI to anticipate what a viewer will watch next, so the content can be ready before it's requested. That might mean preloading the next episode in a series, caching popular highlights from a live event, or delivering region-specific content based on localized viewing trends.Smart caching supports this by storing that predicted content on servers closer to the viewer, reducing delays and buffering. Together, they make streaming faster and smoother by preparing content in advance based on user behavior.Unlike traditional caching, which relies on static popularity metrics or simple geolocation, predictive streaming is dynamic. It adapts in real time to what’s happening on the platform: user actions, traffic spikes, network conditions, and content trends. This results in:Faster playback with minimal bufferingReduced bandwidth and server loadHigher quality of experience (QoE) scores across user segmentsFor example, during the 2024 UEFA European Championship, several broadcasters used predictive caching to preload high-traffic game segments and highlight reels based on past viewer drop-off points. This allowed for instant replay delivery in multiple languages without overloading central servers.Why predictive streaming matters for viewersGlobally, viewers tend to binge-watch new streaming platform releases. For example, sci-fi-action drama Fallout got 25% of its annual US viewing minutes (2.9 billion minutes) in its first few days of release. The South Korean series Queen of Tears became Netflix's most-watched Korean drama of all time in 2024, amassing over 682.6 million hours viewed globally, with more than half of those watch hours occurring during its six-week broadcast run.A predictive caching system can take advantage of this launch-day momentum by pre-positioning likely-to-be-watched episodes, trailers, or bonus content at the edge, customized by region, device, or time of day.The result is a seamless, high-performance experience that anticipates user behavior and scales intelligently to meet it.Benefits for streaming providersTraditional CDNs often waste resources caching content that may never be viewed. Predictive caching focuses only on content that is likely to be accessed, leading to:Lower egress costsReduced server loadMore efficient cache hit ratiosOne of the core benefits of predictive streaming is latency reduction. By caching content at the edge before it’s requested, platforms avoid the delay caused by round-trips to origin servers. This is especially critical for:Live sports and eventsInteractive or real-time formats (e.g., polls, chats, synchronized streams)Edge environments with unreliable last-mile connectivityFor instance, during the 2024 Copa América, mobile viewers in remote areas of Argentina were able to stream matches without delay thanks to proactive edge caching based on geo-temporal viewing predictions.How it worksAt the core of predictive streaming is smart caching: the process of storing data closer to the end user before it’s explicitly requested. Here’s how it works:Data ingestion: The system gathers data on user behavior, device types, content popularity, and location-based trends.Behavior modeling: AI models identify patterns (e.g., binge-watching behaviors, peak-hour traffic, or regional content spikes).Pre-positioning: Based on predictions, the system caches video segments, trailers, or interactive assets to edge servers closest to where demand is expected.Real-time adaptation: As user behavior changes, the system continuously updates its caching strategy.Use cases across streaming ecosystemsSmart caching and predictive delivery benefit nearly every vertical of streaming.Esports and gaming platforms: Live tournaments generate unpredictable traffic surges, especially when underdog teams advance. Predictive caching helps preload high-interest match content, post-game analysis, and multilingual commentary before traffic spikes hit. This helps provide global availability with minimal delay.Corporate webcasts and investor events: Virtual AGMs or earnings calls need to stream seamlessly to thousands of stakeholders, often under compliance pressure. Predictive systems can cache frequently accessed segments, like executive speeches or financial summaries, at regional nodes.Education platforms: In EdTech environments, predictive delivery ensures that recorded lectures, supplemental materials, and quizzes are ready for users based on their course progression. This reduces lag for remote learners on mobile connections.VOD platforms with regional licensing: Content availability differs across geographies. Predictive caching allows platforms to cache licensed material efficiently and avoid serving geo-blocked content by mistake, while also meeting local performance expectations.Government or emergency broadcasts: During public health updates or crisis communications, predictive streaming can support multi-language delivery, instant replay, and mobile-first optimization without overloading networks during peak alerts.Looking forward: Personalization and platform governanceWe predict that the next wave of predictive streaming will likely include innovations that help platforms scale faster while protecting performance and compliance:Viewer-personalized caching, where individual user profiles guide what’s cached locally (e.g., continuing series, genre preferences)Programmatic cache governance, giving DevOps and marketing teams finer control over how and when content is distributedCross-platform intelligence, allowing syndicated content across services to benefit from shared predictions and joint caching strategiesGcore’s role in the predictive futureAt Gcore, we’re building AI-powered delivery infrastructure that makes the future of streaming a practical reality. Our smart caching, real-time analytics, and global edge network work together to help reduce latency and cost, optimize resource usage, and improve user retention and stream stability.If you’re ready to unlock the next level of content delivery, Gcore’s team is here to help you assess your current setup and plan your predictive evolution.Discover how Gcore streaming technologies helped fan.at boost subscription revenue by 133%

Protecting networks at scale with AI security strategies

Network cyberattacks are no longer isolated incidents. They are a constant, relentless assault on network infrastructure, probing for vulnerabilities in routing, session handling, and authentication flows. With AI at their disposal, threat actors can move faster than ever, shifting tactics mid-attack to bypass static defenses.Legacy systems, designed for simpler threats, cannot keep pace. Modern network security demands a new approach, combining real-time visibility, automated response, AI-driven adaptation, and decentralized protection to secure critical infrastructure without sacrificing speed or availability.At Gcore, we believe security must move as fast as your network does. So, in this article, we explore how L3/L4 network security is evolving to meet new network security challenges and how AI strengthens defenses against today’s most advanced threats.Smarter threat detection across complex network layersModern threats blend into legitimate traffic, using encrypted command-and-control, slow drip API abuse, and DNS tunneling to evade detection. Attackers increasingly embed credential stuffing into regular login activity. Without deep flow analysis, these attempts bypass simple rate limits and avoid triggering alerts until major breaches occur.Effective network defense today means inspection at Layer 3 and Layer 4, looking at:Traffic flow metadata (NetFlow, sFlow)SSL/TLS handshake anomaliesDNS request irregularitiesUnexpected session persistence behaviorsGcore Edge Security applies real-time traffic inspection across multiple layers, correlating flows and behaviors across routers, load balancers, proxies, and cloud edges. Even slight anomalies in NetFlow exports or unexpected east-west traffic inside a VPC can trigger early threat alerts.By combining packet metadata analysis, flow telemetry, and historical modeling, Gcore helps organizations detect stealth attacks long before traditional security controls react.Automated response to contain threats at network speedDetection is only half the battle. Once an anomaly is identified, defenders must act within seconds to prevent damage.Real-world example: DNS amplification attackIf a volumetric DNS amplification attack begins saturating a branch office's upstream link, automated systems can:Apply ACL-based rate limits at the nearest edge routerFilter malicious traffic upstream before WAN degradationAlert teams for manual inspection if thresholds escalateSimilarly, if lateral movement is detected inside a cloud deployment, dynamic firewall policies can isolate affected subnets before attackers pivot deeper.Gcore’s network automation frameworks integrate real-time AI decision-making with response workflows, enabling selective throttling, forced reauthentication, or local isolation—without disrupting legitimate users. Automation means threats are contained quickly, minimizing impact without crippling operations.Hardening DDoS mitigation against evolving attack patternsDDoS attacks have moved beyond basic volumetric floods. Today, attackers combine multiple tactics in coordinated strikes. Common attack vectors in modern DDoS include the following:UDP floods targeting bandwidth exhaustionSSL handshake floods overwhelming load balancersHTTP floods simulating legitimate browser sessionsAdaptive multi-vector shifts changing methods mid-attackReal-world case study: ISP under hybrid DDoS attackIn recent years, ISPs and large enterprises have faced hybrid DDoS attacks blending hundreds of gigabits per second of L3/4 UDP flood traffic with targeted SSL handshake floods. Attackers shift vectors dynamically to bypass static defenses and overwhelm infrastructure at multiple layers simultaneously. Static defenses fail in such cases because attackers change vectors every few minutes.Building resilient networks through self-healing capabilitiesEven the best defenses can be breached. When that happens, resilient networks must recover automatically to maintain uptime.If BGP route flapping is detected on a peering session, self-healing networks can:Suppress unstable prefixesReroute traffic through backup transit providersPrevent packet loss and service degradation without manual interventionSimilarly, if a VPN concentrator faces resource exhaustion from targeted attack traffic, automated scaling can:Spin up additional concentratorsRedistribute tunnel sessions dynamicallyMaintain stable access for remote usersGcore’s infrastructure supports self-healing capabilities by combining telemetry analysis, automated failover, and rapid resource scaling across core and edge networks. This resilience prevents localized incidents from escalating into major outages.Securing the edge against decentralized threatsThe network perimeter is now everywhere. Branches, mobile endpoints, IoT devices, and multi-cloud services all represent potential entry points for attackers.Real-world example: IoT malware infection at the branchMalware-infected IoT devices at a branch office can initiate outbound C2 traffic during low-traffic periods. Without local inspection, this activity can go undetected until aggregated telemetry reaches the central SOC, often too late.Modern edge security platforms deploy the following:Real-time traffic inspection at branch and edge routersBehavioral anomaly detection at local points of presenceAutomated enforcement policies blocking malicious flows immediatelyGcore’s edge nodes analyze flows and detect anomalies in near real time, enabling local containment before threats can propagate deeper into cloud or core systems. Decentralized defense shortens attacker dwell time, minimizes potential damage, and offloads pressure from centralized systems.How Gcore is preparing networks for the next generation of threatsThe threat landscape will only grow more complex. Attackers are investing in automation, AI, and adaptive tactics to stay one step ahead. Defending modern networks demands:Full-stack visibility from core to edgeAdaptive defense that adjusts faster than attackersAutomated recovery from disruption or compromiseDecentralized detection and containment at every entry pointGcore Edge Security delivers these capabilities, combining AI-enhanced traffic analysis, real-time mitigation, resilient failover systems, and edge-to-core defense. In a world where minutes of network downtime can cost millions, you can’t afford static defenses. We enable networks to protect critical infrastructure without sacrificing performance, agility, or resilience.Move faster than attackers. Build AI-powered resilience into your network with Gcore.Check out our docs to see how DDoS Protection protects your network

Introducing Gcore for Startups: created for builders, by builders

Building a startup is tough. Every decision about your infrastructure can make or break your speed to market and burn rate. Your time, team, and budget are stretched thin. That’s why you need a partner that helps you scale without compromise.At Gcore, we get it. We’ve been there ourselves, and we’ve helped thousands of engineering teams scale global applications under pressure.That’s why we created the Gcore Startups Program: to give early-stage founders the infrastructure, support, and pricing they actually need to launch and grow.At Gcore, we launched the Startups Program because we’ve been in their shoes. We know what it means to build under pressure, with limited resources, and big ambitions. We wanted to offer early-stage founders more than just short-term credits and fine print; our goal is to give them robust, long-term infrastructure they can rely on.Dmitry Maslennikov, Head of Gcore for StartupsWhat you get when you joinThe program is open to startups across industries, whether you’re building in fintech, AI, gaming, media, or something entirely new.Here’s what founders receive:Startup-friendly pricing on Gcore’s cloud and edge servicesCloud credits to help you get started without riskWhite-labeled dashboards to track usage across your team or customersPersonalized onboarding and migration supportGo-to-market resources to accelerate your launchYou also get direct access to all Gcore products, including Everywhere Inference, GPU Cloud, Managed Kubernetes, Object Storage, CDN, and security services. They’re available globally via our single, intuitive Gcore Customer Portal, and ready for your production workloads.When startups join the program, they get access to powerful cloud and edge infrastructure at startup-friendly pricing, personal migration support, white-labeled dashboards for tracking usage, and go-to-market resources. Everything we provide is tailored to the specific startup’s unique needs and designed to help them scale faster and smarter.Dmitry MaslennikovWhy startups are choosing GcoreWe understand that performance and flexibility are key for startups. From high-throughput AI inference to real-time media delivery, our infrastructure was designed to support demanding, distributed applications at scale.But what sets us apart is how we work with founders. We don’t force startups into rigid plans or abstract SLAs. We build with you 24/7, because we know your hustle isn’t a 9–5.One recent success story: an AI startup that migrated from a major hyperscaler told us they cut their inference costs by over 40%…and got actual human support for the first time. What truly sets us apart is our flexibility: we’re not a faceless hyperscaler. We tailor offers, support, and infrastructure to each startup’s stage and needs.Dmitry MaslennikovWe’re excited to support startups working on AI, machine learning, video, gaming, and real-time apps. Gcore for Startups is delivering serious value to founders in industries where performance, cost efficiency, and responsiveness make or break product experience.Ready to scale smarter?Apply today and get hands-on support from engineers who’ve been in your shoes. If you’re an early-stage startup with a working product and funding (pre-seed to Series A), we’ll review your application quickly and tailor infrastructure that matches your stage, stack, and goals.To get started, head on over to our Gcore for Startups page and book a demo.Discover Gcore for Startups

Subscribe to our newsletter

Get the latest industry trends, exclusive insights, and Gcore updates delivered straight to your inbox.