private void ProcessMessage(AntMediaSignalingMessage msg)
    {
        switch (msg.command)
        {
        case "start":
            OnStart.Invoke(msg.streamId);
            break;

        case "takeConfiguration":
            if (msg.type == "offer")
            {
                OnOffer.Invoke(msg);
            }
            else if (msg.type == "answer")
            {
                OnAnswer.Invoke(msg);
            }
            break;

        case "takeCandidate":
            OnIceCandidate.Invoke(msg);
            break;

        case "error":
            OnSignalingError.Invoke(msg.definition);
            break;
        }
    }
    private void send(AntMediaSignalingMessage msg)
    {
        var json    = JsonConvert.SerializeObject(msg, Formatting.Indented, jsonSettings);
        var logJson = string.Join("\n", json.Split('\n').Select(x => $"> {x}"));

        ws.Send(json);
    }
    public void Stop(string streamId)
    {
        var msg = new AntMediaSignalingMessage
        {
            command  = "stop",
            streamId = streamId
        };

        send(msg);
    }
    public void Play(string streamId)
    {
        var msg = new AntMediaSignalingMessage
        {
            command  = "play",
            streamId = streamId
        };

        send(msg);
    }
    private void Signaling_OnIceCandidate(AntMediaSignalingMessage msg)
    {
        var candidate = new RTCIceCandidate(new RTCIceCandidateInit
        {
            candidate     = msg.candidate,
            sdpMLineIndex = msg.label,
            sdpMid        = msg.id
        });

        peer.AddIceCandidate(candidate);
    }
    public void SendDesc(string streamId, string type, string sdp)
    {
        var msg = new AntMediaSignalingMessage
        {
            command  = "takeConfiguration",
            streamId = streamId,
            type     = type,
            sdp      = sdp
        };

        send(msg);
    }
    public void Publish(string streamId)
    {
        var msg = new AntMediaSignalingMessage
        {
            command  = "publish",
            streamId = streamId,
            video    = true,
            audio    = false
        };

        send(msg);
    }
    public void SendIceCandidate(string streamId, string candidate, int sdpMLineIndex, string sdpMId)
    {
        var msg = new AntMediaSignalingMessage
        {
            command   = "takeCandidate",
            streamId  = streamId,
            label     = sdpMLineIndex,
            id        = sdpMId,
            candidate = candidate
        };

        send(msg);
    }
 private void Signaling_OnAnswer(AntMediaSignalingMessage msg)
 {
     log(LogLevel.Log, $"[Signaling OnAnswer]");
     StartCoroutine(setRemoteDesc(RTCSdpType.Answer, msg.sdp));
 }