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)