MediaSFU for Swift and Apple platforms
Build a native MediaSFU room for iPhone and iPad (iOS 15 or later) with
MediaSFUAppleSDK 0.1.7. MediaSFUIosHostBridge presents the complete room
from Swift: participants, microphone and camera, remote media, screen sharing,
chat, polls, breakouts, whiteboard, recording controls, and leave.
For an isolated local prototype you can launch with restricted, revocable development credentials; never commit them. For anything you share or release, let your backend create or join the room and pass the app only the room-scoped handoff shown below; see the secure backend guide.
Install
In Xcode, choose File > Add Package Dependencies, enter this URL, and add
the MediaSFUAppleSDK product to your app target:
https://github.com/MediaSFU/mediasfu-apple-sdk.git
Select release 0.1.7. Swift Package Manager also resolves the prebuilt
MediaSFUSDK room framework (1.0.8) and the native media client, so there is
nothing to download by hand.
The starter below creates the native media device (MSCDevice), so your app
target must also link the native media client. Add this package too and select
its MediaSFUMediasoupClient product for the app target:
https://github.com/MediaSFU/mediasfu-mediasoup-client-apple.git
Xcode resolves one version of it for both packages and embeds its framework in the app. One import then gives you the room framework and the media types:
import MediaSFUAppleSDK
Add Apple permissions and settings
Add camera and microphone descriptions to Info.plist, plus the frame-rate
setting the hosted room checks when it first opens:
<key>NSCameraUsageDescription</key>
<string>Use the camera during calls and meetings.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Use the microphone during calls and meetings.</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
If Xcode generates your Info.plist, add a source plist with these keys and
select it with the app target's INFOPLIST_FILE build setting.
Screen sharing on iOS also requires a ReplayKit broadcast upload extension. Add that extension before enabling screen sharing in a shipping app.
Copy/paste starter
Your backend creates or joins the room with MediaSFU and returns the
roomName, secret, and link from that response. The app launches the room
with only those room-scoped values, so no account API key ever reaches the
device:
import SwiftUI
import UIKit
import MediaSFUAppleSDK
/// Room details returned by your backend after it creates or joins the room.
struct RoomHandoff {
let roomName: String
let secret: String
let link: String
}
struct MediaSFURoomView: UIViewControllerRepresentable {
let handoff: RoomHandoff
let displayName: String
final class Coordinator {
// Keep the native media device alive for the whole room session.
let nativeDevice = MSCDevice()
}
func makeCoordinator() -> Coordinator { Coordinator() }
func makeUIViewController(context: Context) -> UIViewController {
let bridge = MediaSFUIosHostBridge()
let config = bridge.makeLaunchConfig()
// Non-secret bootstrap values that pass launch validation. The
// room-scoped handoff below replaces them before the socket connects.
config.apiUserName = "roomUser"
config.apiKey = String(repeating: "0", count: 64)
config.connectMediaSFU = true
config.action = "join"
config.userName = displayName
config.roomName = handoff.roomName
config.roomApiToken = handoff.secret
config.roomLink = handoff.link
config.autoProceed = true
// Connect the native media engine before the room starts.
MediaSFUKmpBridgeInstaller.installMediaSFUMediasoupClientBridgeIfSupported(
device: context.coordinator.nativeDevice
)
return bridge.makeHostViewController(config: config)
}
func updateUIViewController(
_ uiViewController: UIViewController,
context: Context
) {}
}
Show MediaSFURoomView full screen (for example with .ignoresSafeArea())
once your backend call succeeds. The SDK makes no further account-authenticated
request: roomName and secret authenticate the socket, and link selects the
media node.
For a self-hosted MediaSFU Open server, set config.localLink to the server's
HTTPS address instead of the handoff fields, and set config.eventType to
conference, webinar, broadcast, or chat when the app creates the room.
Leave localLink empty for MediaSFU Cloud.
Control the hosted room from Swift
Keep the MediaSFUIosHostBridge instance when your own Swift controls need to
open a MediaSFU panel or toggle local media:
final class RoomControls {
let bridge = MediaSFUIosHostBridge()
func toggleMicrophone() {
bridge.triggerToggleAudio()
}
func toggleCamera() {
bridge.triggerToggleVideo()
}
func toggleScreenShare() {
bridge.triggerToggleScreenShare()
}
func showParticipants() {
bridge.triggerShowModal(name: "participants")
}
}
Keep the controller returned by makeHostViewController(config:) mounted for
the whole session, and embed that same controller wherever the room should
appear. For a fully custom interface, keep it mounted as the room runtime and
render the tracks from latestLocalVideoTrack() and latestRemoteVideoTracks().
Before release
- Confirm that the app target resolves
MediaSFUAppleSDK0.1.7and linksMediaSFUMediasoupClient. - Confirm that the app contains no MediaSFU account API key; Cloud rooms launch from your backend's handoff.
- Test microphone, camera, remote audio/video, rotation, background/foreground transitions, screen sharing, leave, and cleanup on the oldest and newest iPhones and iPads you support.
- Check that denied permissions and an interrupted network lead to a useful recovery path.
Build in Xcode on macOS and run these checks on real devices.
Features your Apple app owns
The hosted Apple room includes participant, chat, poll, waiting-room, breakout, whiteboard, recording-control, device, and media-control panels. Use those hosted controls first. Your application and backend provide:
- room creation and joining on your server, invite redemption, durable bans, role policy, and a product-specific host-end rule;
- host end or host leave-without-ending as a separate Swift action; dismissing the hosted view does neither;
- reconnect and cleanup policy, device-selection UI, and the recovery messages your users see after a denied permission or interrupted connection;
- file sharing, recording storage or exports, SIP/PSTN, HLS/WHEP/WHIP, and AI-agent handoff;
- a fully headless operator console or custom media renderer. Use the hosted room first; replacing it means your app owns the missing UI and lifecycle.
MediaSFU can be part of each of those experiences, while your product retains responsibility for authorization, consent, retention, business rules, and the customer-facing experience.