Intro
Recently I got an interesting task to work, to make an application for video streaming, this is for a startup ShopStory (ecomm live streaming). The first version of the application was implemented using the Open Source library for RTMP streaming HaishinKit . And the second version is on Larix SDK . In this article, I will analyze what problems arose in the process.
Requirements
ShopStory.live - B2B live e-commerce, , . , , , , . ShopStory.live , , beauty- live commerce .
ShopStory, LarixBroadcaster , Android iOS. :
, , ,
LarixBroadcaster
, . , , , .
, , .
.
, (, , ).
:
( , )
ABR - Adaptive BitRate ( )
, fps, ..
.
โ . Larix SDK
โ , .
, :
LFLiveKit โ 4.2k , 2016. 115 issue, .
HaishinKit โ 2.1k , 7 . 11 issues.
-
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
( ). .
. , .
The choice of a free library for streaming on iOS is not very large and in fact it all comes down to one option - HaishinKit
. It has an undoubted advantage - open source, and if Larix
we fail to align graphics and increase stability, we will dive into open source and look for places that can be improved.
Buying a paid SDK - do not expect that it will solve all your problems, perhaps you will have more of them (learn vc over 2000 lines).
And some more global conclusions can be made only after we run the assembly on a larger number of streams.