Skip to main content
Version: iOS SDK v1.0.11

Host Low Latency Stream

This guide shows you how to use our low latency live streaming framework to broadcast (1:n) a camera stream to multiple devices.

Setup

Make sure you followed the guide to use our live framework in your project.

Import our Live Framework in your ViewController.

import VideoKitLive

Now, in our viewDidLoad

  • We setup the live preview view, which will give us a preview of what we are going to stream
  • Prepare the stream,
  • Set our desired parameters,
  • And start hosting the broadcast

Stream Using Back Camera

override func viewDidLoad() {
let streamView = UIView(frame: .zero)
view.addSubview(streamView)
streamView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
streamView.topAnchor.constraint(equalTo: view.topAnchor),
streamView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
streamView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
streamView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])

let vkLive = VKLiveStream()

// Set camera to back camera (default is back)
vkLive.streamer.cameraPosition = .front

// We want to stream video and audio (other options for instance are cameraVideoOnly or audioOnly)
vkLive.streamer.streamingMode = .cameraVideoAndAudio

// Start hosting inside your view streamView
// This will initialize the stream on our backend, prepare your camera and preview view
// and give you a VKStreamerProtocol instance (streamer) to start broadcasting
vkLive.host(type: .lowLatency, inView: streamView) { (streamer, stream, error) in
guard let stream = stream else {
print("There was an error starting your stream.")
return
}

// Start broadcasting your stream
streamer.start()

print("Stream started: \(stream.id)")
print("Playback url: " + stream.getPlaybackUrl()?.absoluteString ?? "Error retrieving stream URL")
}
}

Stop Streaming

vkLive.stopHosting(stream: stream) { (success) in
print("Stream ended.")
}

Stream a Capture of Your App

This example creates a webview and broadcasts your apps screen.

Please note that streaming is paused if you move your app into background. To enable streaming from background, you will have to implement a broadcast extension.

override func viewDidLoad() {

// Prepare webview that we are going to broadcast
view.addSubview(webView)
webView.anchor(top: view.topAnchor, leading: view.leadingAnchor, bottom: view.bottomAnchor, trailing: view.trailingAnchor)
webView.navigationDelegate = self

let url = URL(string: "https://www.video.io")!
webView.load(URLRequest(url: url))
webView.allowsBackForwardNavigationGestures = true

let vkLive = VKLiveStream()

// Set streaming mode to screen and audio capture
vkLive.streamingMode = .appScreenCaptureAndAudio

// Start Broadcasting
vkLive.host(type: .lowLatency) { (stream, error) in
guard let stream = stream else {
print("There was an error starting your stream.")
return
}

print("Stream started: \(stream.id)")
print("Playback url: " + stream.getPlaybackUrl()?.absoluteString ?? "Error retrieving stream URL")
}
}

Full Code Example

Here is an implemtation example for a view controller to host a camera stream.

LiveHostViewController.swift
//
// LiveHostViewController.swift
// TestApp
//
// Created by Dennis Stücken on 11/25/20.
// Copyright © 2020 V. All rights reserved.
//
import Foundation
import UIKit
import VideoKitLive
import VideoKitCore
import ReplayKit

class LiveHostViewController: UIViewController {
public var vkLive: VKLiveStream = VKLiveStream()
public var stream: VKStream?

internal var streamType: VKStreamProfile
internal var stopStreamingOnDisappear = true

private let streamView: UIView = {
UIView(frame: .zero)
}()

private let closeButton: UIButton = {
let button = UIButton(frame: .zero)
button.backgroundColor = UIColor(red: 0.96, green: 0.24, blue: 0.48, alpha: 1)
button.setTitleColor(.white, for: .normal)
button.setTitle(" Close Stream ", for: .normal)
button.titleLabel?.font = UIFont(name: "Avenir-Medium", size: 12)
button.layer.cornerRadius = 4
button.layer.borderColor = UIColor.white.cgColor
button.layer.borderWidth = 1.0
return button
}()

init(streamType: VKStreamProfile) {
self.streamType = streamType
super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
self.streamType = .lowLatency
super.init(coder: coder)
}

override func viewDidLoad() {
super.viewDidLoad()

// Preparing live stream
view.addSubview(streamView)
streamView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
streamView.topAnchor.constraint(equalTo: view.topAnchor),
streamView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
streamView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
streamView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])

view.addSubview(closeButton)
closeButton.sizeToFit()
closeButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
closeButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
closeButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20),
])
closeButton.addTarget(self, action: #selector(closeTapped), for: .touchUpInside)
view.bringSubview(toFront: closeButton)
}

func startHosting(completion: @escaping () -> Void) {
// Host your stream
vkLive.host(type: self.streamType, inView: streamView) { (stream, error) in
guard let stream = stream else {
print("There was an error starting your stream.")
return
}

print("Stream started: \(stream.id)")
self.stream = stream
completion()
}
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)

guard let stream = stream else { return }

if stopStreamingOnDisappear {
vkLive.stopHosting(stream: stream) { (success) in
print("Stream ended.")
}
}
}

@objc func closeTapped() {
self.dismiss(animated: true, completion: nil)

guard let stream = stream else {
print("There is no stream to close.")
return
}

vkLive.stopHosting(stream: stream) { (success) in
if success {
print("Stream Ended")
} else {
print("Error Ending Stream")
}

DispatchQueue.main.async {
self.navigationController?.popViewController(animated: true)
}
}
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
}
LiveCameraHostViewController.swift
//
// LiveCameraHostViewController.swift
// TestApp
//
// Created by Dennis Stücken on 12/10/20.
// Copyright © 2020 V. All rights reserved.
//
import Foundation
import VideoKitLive
import UIKit

class LiveCameraHostViewController: LiveHostViewController {
override func viewDidLoad() {
super.viewDidLoad()

vkLive.streamer.cameraPosition = .back
vkLive.streamer.streamingMode = .cameraVideoAndAudio
vkLive.streamer.orientation = .portrait

startHosting() {
// The stream id for your viewers. Populate this to the devices that want to join.
if let stream = self.stream {
print(stream.id)
print(stream.getPlaybackUrl()?.absoluteString ?? "Error retrieving stream URL")
}
}
}
}

Use the Example

Just instantiate the LiveCameraHostViewController with the corresponding streaming type and it will start a full screen camera broadcast.

let streamVC = LiveCameraHostViewController(streamType: .lowLatency)
self.navigationController?.pushViewController(streamVC, animated: true)