Overview

Introduction

The StreamVideo SDK provides UI components to facilitate the integration of video capabilities into your apps.

The UI components are provided in SwiftUI. If you use UIKit, we also provide UIKit wrappers, that can make it easier for you to integrate video in UIKit-based apps.

UI components vs Custom

StreamVideo provides both ready made components to use directly in your app, as well as extension points that you can use to inject your own custom UI. If you only need the calling functionality to support your (custom built) UI, you can simply rely on our low-level client.

Let’s explore the different possibilities and how they would impact your app and the integration efforts.

Using only the low-level client

If your app needs a completely custom UI and calling flow, you can use only our low-level client that implements the WebRTC protocol and communicates with our backend services. If you go with this approach, you can either use our stateful CallViewModel that allows you to observe the call state (list of participants, camera & microphone state, etc), or use our lower level Call object and implement your own presentation objects.

Additionally, if you go with this approach, you can still use some components from our UI SDKs (if they fit your use-case), to facilitate your development. We have several examples for this in our cookbook.

This approach would require some familiarity with our low-level client, and the highest development efforts compared to the other two options. On the other hand, it gives you maximum flexibility to customize the calling flow according to your needs.

In any case, our view components are highly customizable and flexible for many video/audio calling cases, and they can save big development efforts. Therefore, we recommend that you consider the other two options below, before deciding on starting from scratch.

Mix & match

The mix & match approach is ideal if you need one of the standard calling flows, but with a possibility to replace parts of the UI with your own implementation. Our UI SDK allows you to completely swap views with your own interface elements.

For example, if you are building an app with incoming / outgoing calling screens, you can easily swap only those screens. For building your custom screens, you can still reuse our lower level components.

This approach provides a nice balance between levels of customization and development efforts. Find examples and extension slots to get started in our docs here.

Simple theming

If you need a standard video calling experience that needs to match the rest of your app’s look and feel, you can use our theming customizations.

This is the fastest way to add calling support to your app, just setup our video client and attach our CallModifier to your hosting view. You can change the fonts, colors, icons, texts and sounds used in the SDK, by interacting with our Appearance class.

StreamVideoUI object

The UI SDK provides a context provider object that allows simple access to functionalities exposed by the SDK, such as branding, presentation logic, icons, and the low-level video client.

The StreamVideoUI object can be initialized in two ways. The first way is to implicitly create the low-level client StreamVideo, by only creating the StreamVideoUI object.

let streamVideoUI = StreamVideoUI(
	apiKey: "your_api_key",
	user: user.userInfo,
	token: user.token,
	tokenProvider: { result in
		result(.success(user.token))
	}
)

The other option is to first create the StreamVideo client (in case you want to keep an instance of it), and use that one to create the StreamVideoUI object.

let streamVideo = StreamVideo(
    apiKey: "your_api_key",
    user: user.userInfo,
    token: user.token,
    tokenProvider: { result in
        result(.success(user.token))
    }
)
let streamVideoUI = StreamVideoUI(streamVideo: streamVideo)

It’s important to initialize the client early in your app’s lifecycle, and as soon as your user is logged in. If you try to display a view without the StreamVideoUI object being created, you will receive a crash.

Customization options

Appearance

When you create the StreamVideoUI object, you can optionally provide your custom version of the Appearance class, which will allow you to customize things like fonts, colors, icons, and sounds used in the SDK.

Find more details on how to do this on this page.

Changing Views

Apart from the basic theming customizations, you can also swap certain views, with your implementation. You can find more details on how to do that on this page.

Dependency Injection

For injecting dependencies in the SwiftUI SDK, we are using an approach based on this article. It works similarly to the @Environment in SwiftUI, but it also allows access to the dependencies in non-view related code.

When you initialize the SDK (by creating the StreamVideoUI object), all the dependencies are created too, and you can use them anywhere in your code. In order to access a particular type, you need to use the @Injected(\.keyPath) property wrapper:

@Injected(\.streamVideo) var streamVideo
@Injected(\.fonts) var fonts
@Injected(\.colors) var colors
@Injected(\.images) var images
@Injected(\.sounds) var sounds
@Injected(\.utils) var utils

Extending the DI with Custom Types

In some cases, you might also need to extend our DI mechanism with your own types. For example, you may want to be able to access your custom types like this:

@Injected(\.customType) var customType

In order to achieve this, you first need to define your own InjectionKey, and define it’s currentValue, which basically creates the new instance of your type.

class CustomType {
	// your custom logic here
}

struct CustomInjectionKey: InjectionKey {
    static var currentValue: CustomType = CustomType()
}

Next, you need to extend our InjectedValues with your own custom type, by defining its getter and setter.

extension InjectedValues {
    /// Provides access to the `CustomType` instance in the views and view models.
    var customType: CustomType {
        get {
            Self[CustomInjectionKey.self]
        }
        set {
            Self[CustomInjectionKey.self] = newValue
        }
    }
}

With these few simple steps, you can now access your custom functionality in both your app code and in your custom implementations of the views used throughout the SDK.

Additionally, DI entries can be accessed by using the InjectedValues[\.<keypath>] syntax (for example InjectedValues[\.customType]). This approach can be useful in case you want to override our default injected values.

© Getstream.io, Inc. All Rights Reserved.