Transmisión de video en iOS a través de RTMP

Intro

Recientemente tuve una tarea interesante para trabajar, hacer una aplicación para video streaming, esto es para una startup ShopStory (ecomm live streaming). La primera versión de la aplicación se implementó utilizando la biblioteca de código abierto para la transmisión de RTMP HaishinKit . Y la segunda versión está en Larix SDK . En este artículo analizaré qué problemas surgieron en el proceso.





Requisitos

 ShopStory.live - B2B live e-commerce, , . , , , , . ShopStory.live  , , beauty- live commerce .





ShopStory, LarixBroadcaster , Android iOS. :





  1. , , , LarixBroadcaster



    , . , , , .





  2. , , .





  3. .





  4. , (, , ).





:









  • ( , )





  • ABR - Adaptive BitRate ( )





  • , fps, ..





  • .





– . Larix SDK



– , .

, :





  • LFLiveKit – 4.2k , 2016. 115 issue, .





  • HaishinKit – 2.1k , 7 . 11 issues.





  • VideoCore – 1.5k , 2015. .





  • KSY Live iOS SDK – 0.8k , 22 2020. README .





HaishinKit. , , .





HaishinKit

, . . /, . AVCaptureSession, AVCaptureDevice, AVCaptureDeviceInput



. View



, attach



RTMPStream







:





protocol BroadcastService: AnyObject {
    func connect()
    func publish()
    func stop()
}
      
      



.





class HaishinBroadcastService: BroadcastService {}
      
      



ABR - Adaptive BitRate

, , ().





ABR, issue. RTMPStreamDelegate



.





extension HaishinBroadcastService: RTMPStreamDelegate {
    func rtmpStream(_ stream: RTMPStream, didPublishInsufficientBW connection: RTMPConnection) {
        guard self.config.adaptiveBitrate else { return }
        guard let bitrate = self.currentBitrate else {
            assertionFailure()
            return
        }
        let newBitrate = max(UInt32(Double(bitrate) * Constants.bitrateDown), Constants.minBitrate)
        self.rtmpStream.videoSettings[.bitrate] = newBitrate
    }

    func rtmpStream(_ stream: RTMPStream, didPublishSufficientBW connection: RTMPConnection) {
        guard self.config.adaptiveBitrate else { return }
        guard let currentBitrate = self.currentBitrate,
              currentBitrate < Constants.maxBitrate else {
            return
        }
        guard self.bitrateRetryCounter >= Constants.retrySecBeforeUpBitrate else {
            self.bitrateRetryCounter += 1
            return
        }

        self.bitrateRetryCounter = 0
        let newBitrate = min(Constants.maxBitrate, UInt32(Double(currentBitrate) * Constants.bitrateUp))
        if newBitrate == currentBitrate { return }

        self.rtmpStream.videoSettings[.bitrate] = newBitrate
    }
}

private struct Constants {
    static let bitrateDown: Double = 0.75
    static let bitrateUp: Double = 1.15
    static let retrySecBeforeUpBitrate = 20
}
      
      



issue – ( 2 ), . didPublishInsufficientBW



, .





:





  • , 0.75





  • , 20 ( ), 1.15





Live update resolution

, , . RTMP . VK Live . Instagram , rtmp , , , ( , ). ShopStory .





. Wi-Fi, LTE. Larix SDK



. LarixBroadcaster – .





Larix SDK

LarixBroadcaster



+ LarixDemo ( ), , StepByStepGuide.





:





  • ,





  • .





:









  • , - LarixBroadcaster



    ( , : over 2000 )









  • connect



    publish







-

… , LarixBroadcaster



ViewController



2100 , Streamer



1100 . SDK. … , . @Aquary ( ):





« " ". — - . , . — . , , .. , .»





, SDK . , . c HaishinKit



, .. ( HaishinKit



).





ABR, ( ), , . . LarixBroadcaster



3 StreamConditionerMode1, 2, 3,



. ABR? ABR ( ).





, . , status = disconnected



. , .





func connectionStateDidChangeId(_ connectionID: Int32, state: ConnectionState, status: ConnectionStatus, info: [AnyHashable: Any]) {}
      
      



Larix



.

: SDK StreamerEngineProxy



bytesSent



bytesDelivered



, , . , , .





Connect Publish

RTMP, publish



connect



, Larix



( ), . - BroadcastService



.





?





  • , , , , , .





  • . , publish



    , , , , ( ). publish



    ( ). .





. , .





La elección de una biblioteca libre para streaming en iOS no es muy grande y, de hecho, todo se reduce a una opción - HaishinKit



. Tiene una ventaja indudable: el código abierto, y si Larix



no logramos alinear los gráficos y aumentar la estabilidad, nos sumergiremos en el código abierto y buscaremos lugares que se puedan mejorar.





Comprar un SDK de pago: no espere que resuelva todos sus problemas, tal vez tenga más de ellos (aprenda vc en 2000 líneas).





Y se pueden sacar algunas conclusiones más globales solo después de ejecutar el ensamblaje en un mayor número de flujos.








All Articles