I am attempting to create a transcriber utilizing this api https://docs.rev.ai/api/streaming/requests/#rtmp-streams , for audio streaming I take advantage of Haishinkit. While you join for the primary time, the stream works appropriately and the API returns textual content. I’ve a button the place the consumer can choose a language; when deciding on a language, the websocket is disconnected and the stream ends, then I attempt to reconnect: ship a request to the api to get hyperlinks for the stream and the identify of the stream, however once I restart the stream I get these messages within the console:
2024-16-01 13:36:32.951 [Info] [com.haishinkit.HaishinKit] [RTMPNWSocket.swift:168] stateDidChange(to:) > Connection is prepared.
2024-16-01 13:36:32.953 [Info] [com.haishinkit.HaishinKit] [RTMPNWSocket.swift:159] viabilityDidChange(to:) > Connection viability modified to true
NetConnection.Join.Success
2024-16-01 13:36:34.158 [Info] [com.haishinkit.HaishinKit] [IOAudioResampler.swift:227] setUp(_:) > inputFormat:<AVAudioFormat 0x2804f00a0: 1 ch, 48000 Hz, Int16>,outputFormat:<AVAudioFormat 0x2804f25d0: 1 ch, 48000 Hz, Int16>
2024-16-01 13:36:34.158 [Info] [com.haishinkit.HaishinKit] [AudioCodec.swift:149] makeAudioConverter() > inputFormat:<AVAudioFormat 0x2804f25d0: 1 ch, 48000 Hz, Int16>,outputFormat:<AVAudioFormat 0x2804f06e0: 1 ch, 48000 Hz, aac (0x00000002) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/body>
2024-16-01 13:36:34.440 [Error] [com.haishinkit.HaishinKit] [RTMPMessage.swift:309] payload > AMF0Serializer{knowledge: 14 bytes,place: 14,reference: HaishinKit.AMFReference}
NetStream.Publish.Begin
NetConnection.Name.Failed
2024-01-16 13:36:37.219701+0300 AmazingTranscriber[1972:138995] [tcp] tcp_input [C5.1.1:2] flags=[R] seq=2497584374, ack=4294967196, win=0 state=CLOSE_WAIT rcv_nxt=2497584375, snd_una=1639471199
2024-01-16 13:36:37.251997+0300 AmazingTranscriber[1972:138995] [] nw_flow_prepare_output_frames Failing the write requests [57: Socket is not connected]
2024-01-16 13:36:37.252031+0300 AmazingTranscriber[1972:138995] [connection] nw_write_request_report [C5] Ship failed with error “Socket just isn’t related”
2024-16-01 13:36:37.252 [Warn] [com.haishinkit.HaishinKit] [RTMPConnection.swift:403] on(standing:) >
2024-01-16 13:36:37.252199+0300 AmazingTranscriber[1972:138995] [tcp] tcp_output [C5.1.1:2] flags=[R.] seq=1639475405, ack=2497584375, win=2048 state=CLOSED rcv_nxt=2497584375, snd_una=1639471199
NetConnection.Join.Closed
2024-16-01 13:36:39.151 [Info] [com.haishinkit.HaishinKit] [RTMPNWSocket.swift:168] stateDidChange(to:) > Connection is prepared.
2024-16-01 13:36:39.152 [Info] [com.haishinkit.HaishinKit] [RTMPNWSocket.swift:159] viabilityDidChange(to:) > Connection viability modified to true
NetConnection.Join.Success
2024-16-01 13:36:40.891 [Error] [com.haishinkit.HaishinKit] [RTMPMessage.swift:309] payload > AMF0Serializer{knowledge: 14 bytes,place: 14,reference: HaishinKit.AMFReference}
NetStream.Publish.Begin
NetConnection.Name.Failed
2024-01-16 13:36:43.799807+0300 AmazingTranscriber[1972:138993] [tcp] tcp_input [C6.1.1:2] flags=[R] seq=3439027247, ack=4294967196, win=0 state=CLOSE_WAIT rcv_nxt=3439027248, snd_una=3732763433
2024-01-16 13:36:43.864706+0300 AmazingTranscriber[1972:138993] [] nw_flow_prepare_output_frames Failing the write requests [57: Socket is not connected]
2024-01-16 13:36:43.864738+0300 AmazingTranscriber[1972:138993] [connection] nw_write_request_report [C6] Ship failed with error “Socket just isn’t related”
2024-16-01 13:36:43.865 [Warn] [com.haishinkit.HaishinKit] [RTMPConnection.swift:403] on(standing:) >
2024-01-16 13:36:43.864895+0300 AmazingTranscriber[1972:138993] [tcp] tcp_output [C6.1.1:2] flags=[R.] seq=3732767695, ack=3439027248, win=2048 state=CLOSED rcv_nxt=3439027248, snd_una=3732763433
NetConnection.Join.Closed
Please inform me the place I am unsuitable, what I am doing unsuitable. Or may this be a server facet error?
Code for rtmp class:
import AVFoundation
import HaishinKit
class RTMP: ObservableObject {
non-public let audioSession: AVAudioSession
non-public var connection: RTMPConnection?
non-public var rtmpStream: RTMPStream!
non-public var streamName = ""
non-public var connectTo = ""
non-public var retryCount: Int = 0
let maxRetryCount: Int = 5
init() {
self.audioSession = AVAudioSession.sharedInstance()
if audioSession.recordPermission != .granted {
audioSession.requestRecordPermission { (isGranted) in
if !isGranted {
fatalError("Entry denied")
}
}
}
do {
strive audioSession.setCategory(.playAndRecord, mode: .default, choices: [])
strive audioSession.setActive(true)
} catch {
fatalError(error.localizedDescription)
}
}
func startStream(streamName: String?, connectTo: String?) {
guard let stream = streamName,
let join = connectTo else {
print("Invalid streamName, invalid connection")
return
}
self.streamName = stream
self.connectTo = join
connection = RTMPConnection()
rtmpStream = RTMPStream(connection: connection!)
connection?.addEventListener(.rtmpStatus, selector: #selector(rtmpStatusHandler), observer: self)
connection?.addEventListener(.ioError, selector: #selector(rtmpErrorHandler), observer: self)
rtmpStream.attachAudio(AVCaptureDevice.default(for: .audio)) { error in
print("attachAudio (error)")
}
// connection?.requireNetworkFramework = true
connection?.join(join)
}
func stopPublish(completion: @escaping () -> ()) {
rtmpStream.shut()
connection?.shut()
connection?.removeEventListener(.rtmpStatus, selector: #selector(rtmpStatusHandler), observer: self)
connection?.removeEventListener(.ioError, selector: #selector(rtmpErrorHandler), observer: self)
connection = nil
completion()
}
func pausePublish() {
rtmpStream.paused.toggle()
}
@objc
non-public func rtmpStatusHandler(_ notification: Notification) {
let e = Occasion.from(notification)
guard let knowledge: ASObject = e.knowledge as? ASObject, let code: String = knowledge["code"] as? String else {
return
}
print(code)
change code {
case RTMPConnection.Code.connectSuccess.rawValue:
retryCount = 0
rtmpStream.publish(streamName)
case RTMPConnection.Code.connectFailed.rawValue, RTMPConnection.Code.connectClosed.rawValue:
guard retryCount <= maxRetryCount else {
return
}
Thread.sleep(forTimeInterval: pow(2.0, Double(retryCount)))
connection?.join(connectTo)
retryCount += 1
default:
break
}
}
@objc
non-public func rtmpErrorHandler(_ notification: Notification) {
let e = Occasion.from(notification)
guard let knowledge: ASObject = e.knowledge as? ASObject, let code: String = knowledge["level"] as? String, let description: String = knowledge["description"] as? String else {
return
}
print("rtmpErrorHandler: (code)")
print("rtmpErrorHandler description: (description)")
connection?.join(connectTo)
}
}
code for reconnection:
struct TestView: View {
@EnvironmentObject non-public var configLanguage: LanguageConfig
@EnvironmentObject var rtmp: RTMP
@EnvironmentObject var websocket: Websocket
@EnvironmentObject var community: Community
@State non-public var switchLanguage: Bool = false
var physique: some View {
ZStack {
Button(motion: {
print("change language")
switchLanguage.toggle()
}, label: {
Textual content(configLanguage.language.rawValue)
})
}
.sheet(isPresented: $switchLanguage) {
if configLanguage.isChanged {
websocket.disconnect()
rtmp.stopPublish(completion: {
community.postRequest(language: configLanguage.language, completion: { mannequin in
websocket.join(with: mannequin.read_url, completion: {
rtmp.startStream(streamName: mannequin.stream_name, connectTo: mannequin.ingestion_url)
})
})
})
}
} content material: {
SwitchLanguageView()
.presentationDetents([.large])
.presentationDragIndicator(.seen)
}
}
}
code for websocket connection:
func join(with: String?, completion: @escaping () -> ()) {
guard let string = with else {
print("Invalid string to attach websocket")
return
}
guard let url = URL(string: string) else { return }
let request = URLRequest(url: url)
webSocketTask = URLSession.shared.webSocketTask(with: request)
webSocketTask?.resume()
receiveMessage()
completion()
}