gpt4 book ai didi

swift - 一对多 webrtc

转载 作者:搜寻专家 更新时间:2023-10-31 19:28:49 31 4
gpt4 key购买 nike

我想创建一个“一对多”(最多 3 个设备)webrtc 设置。我有一台设备是我的主要设备。其他设备正在连接到该设备。您可以考虑使用对讲机。使用他们正在连接的一台设备。

我有这段代码适用于一对一连接。

import AVFoundation
import UIKit
import WebRTC
import SocketIO
import CoreTelephony
import ReachabilitySwift

let TAG = "ViewController"
let AUDIO_TRACK_ID = TAG + "AUDIO"
let LOCAL_MEDIA_STREAM_ID = TAG + "STREAM"

class ViewController: UIViewController, RTCPeerConnectionDelegate, RTCDataChannelDelegate {

var mediaStream: RTCMediaStream!
var localAudioTrack: RTCAudioTrack!
var remoteAudioTrack: RTCAudioTrack!
var dataChannel: RTCDataChannel!
var dataChannelRemote: RTCDataChannel!

var roomName: String!


override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

initWebRTC();
sigConnect(wsUrl: "http://192.168.1.69:3000");

localAudioTrack = peerConnectionFactory.audioTrack(withTrackId: AUDIO_TRACK_ID)
mediaStream = peerConnectionFactory.mediaStream(withStreamId: LOCAL_MEDIA_STREAM_ID)
mediaStream.addAudioTrack(localAudioTrack)
}

func getRoomName() -> String {
return (roomName == nil || roomName.isEmpty) ? "_defaultroom": roomName;
}

// webrtc
var peerConnectionFactory: RTCPeerConnectionFactory! = nil
var peerConnection: RTCPeerConnection! = nil
var mediaConstraints: RTCMediaConstraints! = nil

var socket: SocketIOClient! = nil
var wsServerUrl: String! = nil
var peerStarted: Bool = false

func initWebRTC() {
RTCInitializeSSL()
peerConnectionFactory = RTCPeerConnectionFactory()

let mandatoryConstraints = ["OfferToReceiveAudio": "true", "OfferToReceiveVideo": "false"]
let optionalConstraints = [ "DtlsSrtpKeyAgreement": "true", "RtpDataChannels" : "true", "internalSctpDataChannels" : "true"]


mediaConstraints = RTCMediaConstraints.init(mandatoryConstraints: mandatoryConstraints, optionalConstraints: optionalConstraints)

}

func connect() {
if (!peerStarted) {
sendOffer()
peerStarted = true
}
}

func hangUp() {
sendDisconnect()
stop()
}

func stop() {
if (peerConnection != nil) {
peerConnection.close()
peerConnection = nil
peerStarted = false
}
}

func prepareNewConnection() -> RTCPeerConnection {
var icsServers: [RTCIceServer] = []

icsServers.append(RTCIceServer(urlStrings: ["stun:stun.l.google.com:19302"], username:"",credential: ""))

let rtcConfig: RTCConfiguration = RTCConfiguration()
rtcConfig.tcpCandidatePolicy = RTCTcpCandidatePolicy.disabled
rtcConfig.bundlePolicy = RTCBundlePolicy.maxBundle
rtcConfig.rtcpMuxPolicy = RTCRtcpMuxPolicy.require
rtcConfig.iceServers = icsServers;

peerConnection = peerConnectionFactory.peerConnection(with: rtcConfig, constraints: mediaConstraints, delegate: self)
peerConnection.add(mediaStream);

let tt = RTCDataChannelConfiguration();
tt.isOrdered = false;


self.dataChannel = peerConnection.dataChannel(forLabel: "testt", configuration: tt)

self.dataChannel.delegate = self
print("Make datachannel")

return peerConnection;
}

// RTCPeerConnectionDelegate - begin [ ///////////////////////////////////////////////////////////////////////////////


/** Called when the SignalingState changed. */
public func peerConnection(_ peerConnection: RTCPeerConnection, didChange stateChanged: RTCSignalingState){
print("signal state: \(stateChanged.rawValue)")
}


/** Called when media is received on a new stream from remote peer. */
public func peerConnection(_ peerConnection: RTCPeerConnection, didAdd stream: RTCMediaStream){
if (peerConnection == nil) {
return
}

if (stream.audioTracks.count > 1) {
print("Weird-looking stream: " + stream.description)
return
}
}

/** Called when a remote peer closes a stream. */
public func peerConnection(_ peerConnection: RTCPeerConnection, didRemove stream: RTCMediaStream){}


/** Called when negotiation is needed, for example ICE has restarted. */
public func peerConnectionShouldNegotiate(_ peerConnection: RTCPeerConnection){}


/** Called any time the IceConnectionState changes. */
public func peerConnection(_ peerConnection: RTCPeerConnection, didChange newState: RTCIceConnectionState){}


/** Called any time the IceGatheringState changes. */
public func peerConnection(_ peerConnection: RTCPeerConnection, didChange newState: RTCIceGatheringState){}


/** New ice candidate has been found. */
public func peerConnection(_ peerConnection: RTCPeerConnection, didGenerate candidate: RTCIceCandidate){


print("iceCandidate: " + candidate.description)
let json:[String: AnyObject] = [
"type" : "candidate" as AnyObject,
"sdpMLineIndex" : candidate.sdpMLineIndex as AnyObject,
"sdpMid" : candidate.sdpMid as AnyObject,
"candidate" : candidate.sdp as AnyObject
]
sigSendIce(msg: json as NSDictionary)

}


/** Called when a group of local Ice candidates have been removed. */
public func peerConnection(_ peerConnection: RTCPeerConnection, didRemove candidates: [RTCIceCandidate]){}


/** New data channel has been opened. */
public func peerConnection(_ peerConnection: RTCPeerConnection, didOpen dataChannel: RTCDataChannel){
print("Datachannel is open, name: \(dataChannel.label)")
dataChannel.delegate = self
self.dataChannelRemote = dataChannel
}



// RTCPeerConnectionDelegate - end ]/////////////////////////////////////////////////////////////////////////////////

public func dataChannel(_ dataChannel: RTCDataChannel, didReceiveMessageWith buffer: RTCDataBuffer){
print("iets ontvangen");
}

public func dataChannelDidChangeState(_ dataChannel: RTCDataChannel){
print("channel.state \(dataChannel.readyState.rawValue)");
}


func sendData(message: String) {
let newData = message.data(using: String.Encoding.utf8)
let dataBuff = RTCDataBuffer(data: newData!, isBinary: false)
self.dataChannel.sendData(dataBuff)
}

func onOffer(sdp:RTCSessionDescription) {
print("on offer shizzle")

setOffer(sdp: sdp)
sendAnswer()
peerStarted = true;
}

func onAnswer(sdp:RTCSessionDescription) {
setAnswer(sdp: sdp)
}

func onCandidate(candidate:RTCIceCandidate) {
peerConnection.add(candidate)
}

func sendSDP(sdp:RTCSessionDescription) {
print("Converting sdp...")
let json:[String: AnyObject] = [
"type" : sdp.type.rawValue as AnyObject,
"sdp" : sdp.sdp.description as AnyObject
]

sigSend(msg: json as NSDictionary);
}

func sendOffer() {
peerConnection = prepareNewConnection();
peerConnection.offer(for: mediaConstraints) { (RTCSessionDescription, Error) in

if(Error == nil){
print("send offer")

self.peerConnection.setLocalDescription(RTCSessionDescription!, completionHandler: { (Error) in
print("Sending: SDP")
print(RTCSessionDescription as Any)
self.sendSDP(sdp: RTCSessionDescription!)
})
} else {
print("sdp creation error: \(Error)")
}

}
}


func setOffer(sdp:RTCSessionDescription) {
if (peerConnection != nil) {
print("peer connection already exists")
}
peerConnection = prepareNewConnection();
peerConnection.setRemoteDescription(sdp) { (Error) in

}
}

func sendAnswer() {
print("sending Answer. Creating remote session description...")
if (peerConnection == nil) {
print("peerConnection NOT exist!")
return
}

peerConnection.answer(for: mediaConstraints) { (RTCSessionDescription, Error) in
print("ice shizzle")

if(Error == nil){
self.peerConnection.setLocalDescription(RTCSessionDescription!, completionHandler: { (Error) in
print("Sending: SDP")
print(RTCSessionDescription as Any)
self.sendSDP(sdp: RTCSessionDescription!)
})
} else {
print("sdp creation error: \(Error)")
}

}
}

func setAnswer(sdp:RTCSessionDescription) {
if (peerConnection == nil) {
print("peerConnection NOT exist!")
return
}

peerConnection.setRemoteDescription(sdp) { (Error) in
print("remote description")
}
}

func sendDisconnect() {
let json:[String: AnyObject] = [
"type" : "user disconnected" as AnyObject
]
sigSend(msg: json as NSDictionary);
}

// websocket related operations
func sigConnect(wsUrl:String) {
wsServerUrl = wsUrl;

print("connecting to " + wsServerUrl)
socket = SocketIOClient(socketURL: NSURL(string: wsServerUrl)! as URL)

socket.on("connect") { data in
print("WebSocket connection opened to: " + self.wsServerUrl);
self.sigEnter();
}
socket.on("disconnect") { data in
print("WebSocket connection closed.")
}
socket.on("message") { (data, emitter) in
if (data.count == 0) {
return
}

let json = data[0] as! NSDictionary
print("WSS->C: " + json.description);

let type = json["type"] as! Int

if (type == RTCSdpType.offer.rawValue) {
print("Received offer, set offer, sending answer....");
let sdp = RTCSessionDescription(type: RTCSdpType(rawValue: type)!, sdp: json["sdp"] as! String)
self.onOffer(sdp: sdp);
} else if (type == RTCSdpType.answer.rawValue && self.peerStarted) {
print("Received answer, setting answer SDP");
let sdp = RTCSessionDescription(type: RTCSdpType(rawValue: type)!, sdp: json["sdp"] as! String)
self.onAnswer(sdp: sdp);
} else {
print("Unexpected websocket message");
}
}

socket.on("ice") { (data, emitter) in
if (data.count == 0) {
return
}

let json = data[0] as! NSDictionary
print("WSS->C: " + json.description);

let type = json["type"] as! String


if (type == "candidate" && self.peerStarted) {
print("Received ICE candidate...");
let candidate = RTCIceCandidate(
sdp: json["candidate"] as! String,
sdpMLineIndex: Int32(json["sdpMLineIndex"] as! Int),
sdpMid: json["sdpMid"] as? String)
self.onCandidate(candidate: candidate);
} else {
print("Unexpected websocket message");
}
}

socket.connect();
}

func sigRecoonect() {
socket.disconnect();
socket.connect();
}

func sigEnter() {
let roomName = getRoomName();
print("Entering room: " + roomName);
socket.emit("enter", roomName);
}

func sigSend(msg:NSDictionary) {
socket.emit("message", msg)
}

func sigSendIce(msg:NSDictionary) {
socket.emit("ice", msg)
}
}

所以我想我需要一个与同行的数组。而mediaStream、localAudioTrack和dataChannel需要是一个对象,因为本地音频是一样的?有没有好的解决方案?因为我不知道如何正确实现。

我正在研究涉及多调用 webrtc 设置的不同问题和项目。

我在 GitHub 上看到了这个(网站)webrtc 设置: https://github.com/anoek/webrtc-group-chat-example/blob/master/client.html

我将尝试将其逆向工程为 swift:)。非常感谢任何帮助。

最佳答案

我建议不要使用一对多架构,在这种架构中,单个设备需要将其媒体发送给所有其他设备。这中断得非常快(比如在需要连接 2-3 个设备之后)。

原因是上行链路的容量通常有限,即使没有容量限制,设备也不适合将如此多的数据流式传输到许多其他设备。

要“按比例”执行您想要的操作,请使用将媒体路由到其他设备的服务器组件。看https://jitsi.org/http://www.kurento.org/起点。

关于swift - 一对多 webrtc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42725091/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com