shogo4405 / HaishinKit.swift

Camera and Microphone streaming library via RTMP and SRT for iOS, macOS, tvOS and visionOS.
BSD 3-Clause "New" or "Revised" License
2.78k stars 617 forks source link

Rtmp client on simulator doesn't send data to rtmp server(audio only) #521

Closed AugustAtSeattle closed 5 years ago

AugustAtSeattle commented 5 years ago

Describe the bug use ios simulator run the rtmp client Received connection event Received publish event but can't send data to rtmp server (It works on devices properly) Expected behavior ios simulator sent audio data to rtmp server

Screenshots log on rtmp server when simulator client connect and publish image network traffic on simulator image

log on rtmp server when device client and publish image network traffic on device image

Desktop (please complete the following information):

Smartphone (please complete the following information):

Additional context

@IBAction func onStart(_ sender: Any) {
    let rtmpConnection = RTMPConnection()
    let rtmpStream = RTMPStream(connection: rtmpConnection)
    rtmpStream.audioSettings = [
        "muted": false, // mute audio
        "bitrate": 32 * 1024,
        "sampleRate": sampleRate,
    ]
    rtmpStream.attachAudio(AVCaptureDevice.default(for: AVMediaType.audio) , automaticallyConfiguresApplicationAudioSession: true) { error in
        print(error)
    }
    rtmpConnection.connect("rtmp://192.168.1.109:1935/app")
    rtmpConnection.addEventListener(Event.RTMP_STATUS, selector: #selector(rtmpStatusEvent), observer: self)
    rtmpConnection.addEventListener(Event.EVENT, selector: #selector(rtmpStatusEvent), observer: self)
    rtmpConnection.addEventListener(Event.SYNC, selector: #selector(rtmpStatusEvent), observer: self)
    rtmpConnection.addEventListener(Event.IO_ERROR, selector: #selector(rtmpStatusEvent), observer: self)
    rtmpStream.delegate = self
    self.rtmpStream = rtmpStream;
}

//event handler
@objc func rtmpStatusEvent(_ notification: Notification) {
    let e: Event = Event.from(notification)
    if let data: ASObject = e.data as? ASObject, let code: String = data["code"] as? String{
        // you can handle errors.
        switch code {
        case RTMPConnection.Code.connectSuccess.rawValue:
            self.rtmpStream!.publish("test");
            break
        case RTMPConnection.Code.connectRejected.rawValue:
            break
        case RTMPConnection.Code.connectClosed.rawValue:
            break
        case RTMPConnection.Code.connectFailed.rawValue:
            break
        case RTMPConnection.Code.connectIdleTimeOut.rawValue:
            break
        case RTMPStream.Code.unpublishSuccess.rawValue:
            break;
        case RTMPStream.Code.publishStart.rawValue:
            break
        case RTMPStream.Code.unpublishSuccess.rawValue:
            break
        default:
            break
        }
    }
}
AugustAtSeattle commented 5 years ago

info: 2019-03-04 11:37:32.155 [Info] [com.haishinkit.HaishinKit] [AudioConverter.swift:86] inSourceFormat > nil clear 2019-03-04 11:38:02.238 [Warn] [com.haishinkit.HaishinKit] [RTMPConnection.swift:357] on(status:) > 2019-03-04 11:38:02.238 [Info] [com.haishinkit.HaishinKit] [AudioConverter.swift:86] inSourceFormat > nil clear

AugustAtSeattle commented 5 years ago

trace:

2019-04-04 10:57:19.800 [Info] [com.haishinkit.HaishinKit] [AudioConverter.swift:86] inSourceFormat > nil 2019-04-04 10:57:19.875 [Trace] [com.haishinkit.HaishinKit] [RTMPSocket.swift:84] doOutput(chunk:locked:) > RTMPChunk{size: 0,type: zero,streamId: 3,message: Optional(RTMPCommandMessage{type: amf0Command,length: 386,streamId: 0,timestamp: 0,payload: 374 bytes,objectEncoding: 0,commandName: connect,transactionId: 1,commandObject: Optional(["videoFunction": Optional(1), "app": Optional("live?publishertoken=gle-41894e63-6d4a-4890-955b-f68cbf0c69c8"), "swfUrl": nil, "objectEncoding": Optional(0), "tcUrl": Optional("rtmp://192.168.1.109:1935/live?publishertoken=gle-41894e63-6d4a-4890-955b-f68cbf0c69c8"), "flashVer": Optional("FMLE/3.0 (compatible; FMSc/1.0)"), "fpad": Optional(false), "pageUrl": nil, "capabilities": Optional(239), "audioCodecs": Optional(1024), "videoCodecs": Optional(128)]),arguments: [],serializer: AMF0Serializer{data: 0 bytes,position: 0,reference: HaishinKit.AMFReference}}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.877 [Trace] [com.haishinkit.HaishinKit] [RTMPConnection.swift:488] listen > RTMPChunk{size: 128,type: zero,streamId: 2,message: Optional(RTMPWindowAcknowledgementSizeMessage{type: windowAck,length: 4,streamId: 0,timestamp: 0,payload: 4 bytes,size: 5000000}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.878 [Trace] [com.haishinkit.HaishinKit] [RTMPSocket.swift:84] doOutput(chunk:locked:) > RTMPChunk{size: 0,type: zero,streamId: 2,message: Optional(RTMPWindowAcknowledgementSizeMessage{type: windowAck,length: 16,streamId: 0,timestamp: 0,payload: 4 bytes,size: 5000000}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.879 [Trace] [com.haishinkit.HaishinKit] [RTMPConnection.swift:488] listen > RTMPChunk{size: 128,type: zero,streamId: 2,message: Optional(RTMPSetPeerBandwidthMessage{type: bandwidth,length: 5,streamId: 0,timestamp: 0,payload: 5 bytes,size: 5000000,limit: dynamic}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.880 [Trace] [com.haishinkit.HaishinKit] [RTMPConnection.swift:488] listen > RTMPChunk{size: 128,type: zero,streamId: 2,message: Optional(RTMPSetChunkSizeMessage{type: chunkSize,length: 4,streamId: 0,timestamp: 0,payload: 4 bytes,size: 3000}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.881 [Trace] [com.haishinkit.HaishinKit] [RTMPConnection.swift:488] listen > RTMPChunk{size: 3000,type: zero,streamId: 3,message: Optional(RTMPCommandMessage{type: amf0Command,length: 190,streamId: 0,timestamp: 0,payload: 190 bytes,objectEncoding: 0,commandName: _result,transactionId: 1,commandObject: Optional(["fmsVer": Optional("FMS/3,0,1,123"), "capabilities": Optional(31.0)]),arguments: [Optional(["code": Optional("NetConnection.Connect.Success"), "description": Optional("Connection succeeded."), "level": Optional("status"), "objectEncoding": Optional(0.0)])],serializer: AMF0Serializer{data: 0 bytes,position: 0,reference: HaishinKit.AMFReference}}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.883 [Trace] [com.haishinkit.HaishinKit] [RTMPSocket.swift:84] doOutput(chunk:locked:) > RTMPChunk{size: 0,type: zero,streamId: 2,message: Optional(RTMPSetChunkSizeMessage{type: chunkSize,length: 16,streamId: 0,timestamp: 0,payload: 4 bytes,size: 8192}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.884 [Trace] [com.haishinkit.HaishinKit] [RTMPSocket.swift:84] doOutput(chunk:locked:) > RTMPChunk{size: 0,type: zero,streamId: 3,message: Optional(RTMPCommandMessage{type: amf0Command,length: 37,streamId: 0,timestamp: 0,payload: 25 bytes,objectEncoding: 0,commandName: createStream,transactionId: 2,commandObject: nil,arguments: [],serializer: AMF0Serializer{data: 0 bytes,position: 0,reference: HaishinKit.AMFReference}}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.886 [Trace] [com.haishinkit.HaishinKit] [RTMPConnection.swift:488] listen > RTMPChunk{size: 3000,type: zero,streamId: 3,message: Optional(RTMPCommandMessage{type: amf0Command,length: 29,streamId: 0,timestamp: 0,payload: 29 bytes,objectEncoding: 0,commandName: _result,transactionId: 2,commandObject: Optional([:]),arguments: [Optional(1.0)],serializer: AMF0Serializer{data: 0 bytes,position: 0,reference: HaishinKit.AMFReference}}),fragmented: false,_data: 12 bytes} clear 2019-04-04 10:57:19.888 [Trace] [com.haishinkit.HaishinKit] [RTMPSocket.swift:84] doOutput(chunk:locked:) > RTMPChunk{size: 0,type: zero,streamId: 3,message: Optional(RTMPCommandMessage{type: amf0Command,length: 47,streamId: 0,timestamp: 0,payload: 35 bytes,objectEncoding: 0,commandName: FCPublish,transactionId: 3,commandObject: nil,arguments: [Optional("8fdcda563b")],serializer: AMF0Serializer{data: 0 bytes,position: 0,reference: HaishinKit.AMFReference}}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.889 [Trace] [com.haishinkit.HaishinKit] [RTMPSocket.swift:84] doOutput(chunk:locked:) > RTMPChunk{size: 0,type: zero,streamId: 4,message: Optional(RTMPCommandMessage{type: amf0Command,length: 52,streamId: 1,timestamp: 0,payload: 40 bytes,objectEncoding: 0,commandName: publish,transactionId: 0,commandObject: nil,arguments: [Optional("8fdcda563b"), Optional("live")],serializer: AMF0Serializer{data: 0 bytes,position: 0,reference: HaishinKit.AMFReference}}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.891 [Trace] [com.haishinkit.HaishinKit] [RTMPConnection.swift:488] listen > RTMPChunk{size: 3000,type: zero,streamId: 3,message: Optional(RTMPCommandMessage{type: amf0Command,length: 179,streamId: 1,timestamp: 0,payload: 179 bytes,objectEncoding: 0,commandName: onStatus,transactionId: 0,commandObject: Optional([:]),arguments: [Optional(["code": Optional("NetStream.Publish.Start"), "description": Optional("/live?publishertoken=gle-41894e63-6d4a-4890-955b-f68cbf0c69c8/8fdcda563b is now published."), "level": Optional("status")])],serializer: AMF0Serializer{data: 0 bytes,position: 0,reference: HaishinKit.AMFReference}}),fragmented: false,_data: 12 bytes} 2019-04-04 10:57:19.893 [Trace] [com.haishinkit.HaishinKit] [RTMPSocket.swift:84] doOutput(chunk:locked:) > RTMPChunk{size: 0,type: zero,streamId: 3,message: Optional(RTMPDataMessage{type: amf0Data,length: 45,streamId: 1,timestamp: 0,payload: 33 bytes,objectEncoding: 0,handlerName: @setDataFrame,arguments: [Optional("onMetaData"), Optional([:])],serializer: AMF0Serializer{data: 0 bytes,position: 0,reference: HaishinKit.AMFReference}}),fragmented: false,_data: 12 bytes}

AugustAtSeattle commented 5 years ago
    let audios: [Any]! =  AVCaptureDevice.devices(for: AVMediaType.audio)
    print(AVCaptureDevice.authorizationStatus(for: AVMediaType.audio).rawValue) // output 3 means authorized 
    for audio in audios {
        if let audio: AVCaptureDevice = audio as? AVCaptureDevice { // output empty no input audio recognized
            print(audio.localizedName) 
        }
    }
stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.