Skip to end of metadata
Go to start of metadata

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

  • a stream with video of the participant, named <participantName> + "#" + <roomName>, is published
  • the participant's stream is added to mixer named <roomName> (in case such mixer did not exist, it is auto created)
  • a new mixer named <roomName> + "-" + <participantName> + <roomName> and containing video from all the participants (including this one) and audio only from the other participants is created and played for the participant

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:

  • WCS server URL
  • server application name defaultApp
    @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:

  • stream name to publish
  • local view to display
  • WebRTC transport type
  • audio and video publishing constraints
    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:

  • stream name to play
  • remote view to display
  • WebRTC transport type
    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;
    }
  • No labels