Skip to content

Moving from 1.9.x APIs to 2.0.0

shogo4405 edited this page Aug 27, 2024 · 26 revisions
  • I will update the documentation based on the finalized sections. I aim to complete it before the 2.0.0 release.
  • The update to Swift 6.0 will be done in version 2.1.0 + Xcode 16.0. Version 2.0.0 targets Swift 5.10 + Xcode 15.4, which is compatible with Swift 6.0.

IOStream

I redesigned the system to address the demand for streaming to multiple services. The responsibilities are split into MediaMixer, which handles capture from the device, and HKStream, which focuses on live streaming video and audio.

Attaching the view

1.9.x

stream: IOStream
view: MTHKView

view.attachStream(stream)

2.0.0

mixer: MediaMixer
stream: HKStream
view: MTHKView
// view2: MTHKView

mixer.addOutput(stream)
stream.addOutput(view)
// stream.addOutput(view2)

It is possible to set multiple views on the mixer. This allows you to directly monitor the video CMSampleBuffer during capture. You can switch between views by changing the track. Setting track = UInt8.max makes it equivalent to the value being output to HKStream.

mixer: MediaMixer
view0: MTHKView
view1: MTHKView

view0.track = 0
view1.track = UInt8.max

mixer.addOutput(view0)
mixer.addOutput(view1)

attachCamera, attachAudio

1.9.x

stream: IOStream

stream.attachCamera(AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back), track: 0) { _, error in
  if let error {
    logger.warn(error)
  }
}

stream.attachAudio(AVCaptureDevice.default(for: .audio)) { _, error in
  if let error {
    logger.warn(error)
  }
}

2.0.x

mixer: MediaMixer
stream: RTMPStream or SRTStream

do {
  try await mixer.attachVideo(AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back))
} catch {
  logger.warn(error)
}

do {
  try await mixer.attachAudio(AVCaptureDevice.default(for: .audio))
} catch {
  logger.warn(error)
}

mixer.addOutput(stream)

RTMP

Discontinued

  • RTMPT, RTMPTS protocols.
    • I decided this because I judged the usage frequency to be low.

Signature

Inheritance is no longer possible due to the transition to actors. If you were using inheritance and are now facing issues, please let us know how you were using it, and I can discuss possible solutions.

1.9.x 2.0.0
public class RTMPConnection actor RTMPConnection
open class RTMPStream actor RTMPStream

RTMPConnection

Regarding the specification of detailed properties.

1.9.x

public actor RTMPConnection {
  /// Specifies the URL of .swf.
  public var swfUrl: String?
  /// Specifies the URL of an HTTP referer.
  public var pageUrl: String?
  /// Specifies the time to wait for TCP/IP Handshake done.
  ...
}

2.0.x

The constructor now accepts it as an argument.

public actor RTMPConnection {
  /// The URL of .swf.
  public let swfUrl: String?
  /// The URL of an HTTP referer.
  public let pageUrl: String?
  /// The name of application.
  public let flashVer: String
  /// The time to wait for TCP/IP Handshake done.
  public let timeout: Int
  /// The RTMP request timeout value. Defaul value is 500 msec.
  public let requestTimeout: UInt64
  /// The outgoing RTMPChunkSize.
  public let chunkSize: Int
  /// The dispatchQos for socket.
  public let qualityOfService: DispatchQoS

  /// Creates a new connection.
  public init(
    swfUrl: String? = nil,
    pageUrl: String? = nil,
    flashVer: String = RTMPConnection.defaultFlashVer,
    timeout: Int = RTMPConnection.defaultTimeout,
    requestTimeout: UInt64 = RTMPConnection.defaultRequestTimeout,
    chunkSize: Int = RTMPConnection.defaultChunkSizeS,
    qualityOfService: DispatchQoS = .userInitiated) {
    self.swfUrl = swfUrl
    self.pageUrl = pageUrl
    self.flashVer = flashVer
    self.timeout = timeout
    self.requestTimeout = requestTimeout
    self.chunkSize = chunkSize
    self.qualityOfService = qualityOfService
  }
}

EventHandle

1.9.x

Discontinued event handling related to addEventHandler.

connection.addEventListener(.rtmpStatus, selector: #selector(rtmpStatusHandler), observer: self)
connection.addEventListener(.ioError, selector: #selector(rtmpErrorHandler), observer: self)

@objc
private func rtmpStatusHandler(_ notification: Notification) {
  let e = Event.from(notification)
  guard let data: ASObject = e.data as? ASObject, let code: String = data["code"] as? String else {
    return
  }
  logger.info(code)
  switch code {
  case RTMPConnection.Code.connectSuccess.rawValue:
    stream?.play(Preference.default.streamName!)
  case RTMPConnection.Code.connectFailed.rawValue, RTMPConnection.Code.connectClosed.rawValue:
    connection?.connect(uri)
  default:
    break
  }
}

2.0.0

connection: RTMPConnection
stream: RTMPStream

do {
  let response = try await connection.connect(preference.uri ?? "")
  logger.info(response)
  let response = try await stream.publish(Preference.default.streamName)
} catch RTMPConnection.Error.requestFailed(let response) {
  logger.warn(response)
} catch RTMPStream.Error.requestFailed(let response) {
  logger.warn(response)
} catch {
  logger.warn(error)
}

RTMPConnectionDelegate

1.9.x

/// The interface a RTMPConnectionDelegate uses to inform its delegate.
public protocol RTMPConnectionDelegate: AnyObject {
  /// Tells the receiver to publish insufficient bandwidth occured.
  func connection(_ connection: RTMPConnection, publishInsufficientBWOccured stream: RTMPStream)
  /// Tells the receiver to publish sufficient bandwidth occured.
  func connection(_ connection: RTMPConnection, publishSufficientBWOccured stream: RTMPStream)
  /// Tells the receiver to update statistics.
  func connection(_ connection: RTMPConnection, updateStats stream: RTMPStream)
}

var connection: RTMPConnect
connection.delegate = self

2.0.0

/// A type with a network bitrate strategy representation.
public protocol HKStreamBitRateStrategy: Sendable {
  /// The mamimum video bitRate.
  var mamimumVideoBitRate: Int { get }
  /// The mamimum audio bitRate.
  var mamimumAudioBitRate: Int { get }

  /// Adjust a bitRate.
  func adjustBitrate(_ event: NetworkMonitorEvent, stream: some HKStream) async
}

/// An enumeration that indicate the network monitor event.
public enum NetworkMonitorEvent: Sendable {
  /// To update statistics.
  case status(report: NetworkMonitorReport)
  /// To publish sufficient bandwidth occured.
  case publishInsufficientBWOccured(report: NetworkMonitorReport)
  /// To reset statistics.
  case reset
}

final final actor MyStreamBitRateStrategy: HKStreamBitRateStrategy {
  func adjustBitrate(_ event: NetworkMonitorEvent, stream: some HKStream) async {
  }
}

var stream: (any HKStream)
var strategy = MyStreamBitRateStrategy()
async stream.setBitrateStrategy(strategy)

SRT

Signature

1.9.x 2.0.0
public class SRTConnection actor SRTConnection
final class SRTStream actor SRTStream

Others

Discontinued

ASClass

1.9.x 2.0.0
ASObject AMFObject
ASUndefined AMFUndefined
ASTypedObject AMFTypedObject
ASArray AMFArray
ASXMLDocument AMFXMLDocument
ASXMLDocument AMFXMLDocument
ASXML AMFXML
Clone this wiki locally