Example of client for MCU conference participant

This example can be used to organize an MCU video conference on Web Call Server. Each participant of such conference can publish a WebRTC stream and play a mixer stream with audio and video from the other participants and own video (without own audio).

The following settings are required in WCS flashphoner.properties

mixer_auto_start=true
mixer_mcu_audio=true
mixer_mcu_video=true

When a participant joins a conference using the client

On the screenshot below the participant is publishing a stream and playing his conference mixer stream:

Analyzing example code

To analyze the code take MCUClientSwift class which is available on GitHub.

Man application view class: MCUViewController (implementation file MCUViewController.swift).

1. API import code

import FPWCSApi2Swift

2. Session creation and connecting to the server

WCSSession, WCSSession.connect code

The following session parameters are set:

    @IBAction func joinPressed(_ sender: Any) {
        self.changeViewState(joinButton, false)
        if (joinButton.title(for: .normal) == "JOIN") {
            if (session == nil) {
                let options = FPWCSApi2SessionOptions()
                options.urlServer = serverField.text
                options.appKey = "defaultApp"
                do {
                    try session = WCSSession(options)
                } catch {
                    print(error)
                }
            }
            ...
            self.changeViewState(serverField, false)
            session?.connect()
        } else {
            leave()
        }
        
    }

3. Participant stream publishing

WCSSession.createStream, WCSStream.publish code

The following parameters are passed to createStream method:

    func publish() {
        ...
        let constraints = FPWCSApi2MediaConstraints()
        if (audioSwitch.isOn) {
            constraints.audio = FPWCSApi2AudioConstraints()
        }
        if (videoSwitch.isOn) {
            constraints.video = FPWCSApi2VideoConstraints()
        }
        let options = FPWCSApi2StreamOptions()
        options.name = loginField.text! + "#" + roomField.text!
        options.transport = transportSwitch.isOn ? kFPWCSTransport.fpwcsTransportTCP : kFPWCSTransport.fpwcsTransportUDP
        options.constraints = constraints
        options.display = localDisplay.videoView
        do {
            publishStream = try session!.createStream(options)
        } catch {
            print(error);
        }
        ...        
        do {
            try publishStream?.publish()
        } catch {
            print(error);
        }
    }

4. MCU mixer stream playback

WCSSession.createStream, WCSStream.play code

The following parameters are passed to createStream method:

    func play() {
        ...
        let options = FPWCSApi2StreamOptions()
        options.name = roomField.text! + "-" + loginField.text! + roomField.text!
        options.transport = transportSwitch.isOn ? kFPWCSTransport.fpwcsTransportTCP : kFPWCSTransport.fpwcsTransportUDP
        options.display = remoteDisplay.videoView;
        do {
            playStream = try session!.createStream(options)
        } catch {
            print(error)
        }
        ...
        do {
            try playStream?.play()
        } catch {
            print(error);
        }
    }

5. Stream playback stopping

WCSStream.stop code

    func stopPlay() {
        do {
            try playStream?.stop();
        } catch {
            print(error);
        }
        playStream = nil;
    }

6. Stream publishing stopping

WCSStream.stop code

    func stopPublish() {
        do {
            try publishStream?.stop()
        } catch {
            print(error);
        }
        publishStream = nil;
    }

7. Connection closing

WCSSession.disconnect code

    func leave() {
        session?.disconnect()
        session = nil;
    }