#c# #unity3d #webrtc
#c# #unity3d #webrtc
Вопрос:
Извините, что я был новичком, и у меня может возникнуть простая проблема для вас. Я надеюсь использовать официальный пакет Unity WebRTC (введите описание ссылки здесь), чтобы сделать общий доступ к просмотру камеры, что означает, что разные устройства, принадлежащие к одной сети WLAN, могут видеть один и тот же общий вид с камеры программы Unity (также принадлежащей к той же сети WLAN). Моя проблема в том, что я не знаю, как разрешить запуск кода примера на разных устройствах и использовать один и тот же вид.
Вот пример сцены: запустите Scence
После того, как я нажму кнопку «Пуск»: после нажатия «Пуск»
После того, как я нажму кнопку «Позвонить»: после нажатия кнопки «Позвонить»
Этот пример сцены (название сцены в этом примере проекта — «MultiplePeerConnections») означает, что вы можете поделиться видом камеры с двумя другими устройствами. И вот пример кода:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
namespace Unity.WebRTC.Samples
{
class MultiplePeerConnectionsSample : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField] private Button startButton;
[SerializeField] private Button callButton;
[SerializeField] private Button hangUpButton;
[SerializeField] private Vector2Int streamingSize;
[SerializeField] private Camera cam;
[SerializeField] private RawImage sourceImage;
[SerializeField] private RawImage receiveImage1;
[SerializeField] private RawImage receiveImage2;
[SerializeField] private AudioSource sourceAudio;
[SerializeField] private AudioSource receiveAudio1;
[SerializeField] private AudioSource receiveAudio2;
[SerializeField] private Transform rotateObject;
[SerializeField] private AudioClip audioclipStereoSample;
#pragma warning restore 0649
private static RTCConfiguration configuration = new RTCConfiguration
{
iceServers = new[] {new RTCIceServer {urls = new[] {"stun:stun.l.google.com:19302"}}}
};
private RTCPeerConnection pc1Local, pc1Remote, pc2Local, pc2Remote;
private MediaStream sourceStream;
private void Awake()
{
WebRTC.Initialize(WebRTCSettings.EncoderType, WebRTCSettings.LimitTextureSize);
}
private void OnDestroy()
{
WebRTC.Dispose();
}
private void Start()
{
StartCoroutine(WebRTC.Update());
startButton.onClick.AddListener(Setup);
callButton.onClick.AddListener(Call);
hangUpButton.onClick.AddListener(HangUp);
startButton.interactable = true;
callButton.interactable = false;
hangUpButton.interactable = false;
}
private void Update()
{
if (rotateObject != null)
{
rotateObject.Rotate(1, 2, 3);
}
}
private void Setup()
{
Debug.Log("Set up source/receive streams");
sourceStream = new MediaStream();
var videoTrack = cam.CaptureStreamTrack(streamingSize.x, streamingSize.y, 0);
sourceStream.AddTrack(videoTrack);
sourceImage.texture = cam.targetTexture;
sourceAudio.clip = audioclipStereoSample;
sourceAudio.loop = true;
sourceAudio.Play();
var audioTrack = new AudioStreamTrack(sourceAudio);
sourceStream.AddTrack(audioTrack);
startButton.interactable = false;
callButton.interactable = true;
}
private void Call()
{
Debug.Log("Starting calls");
pc1Local = new RTCPeerConnection(ref configuration);
pc1Remote = new RTCPeerConnection(ref configuration);
pc1Remote.OnTrack = e =>
{
if (e.Track is VideoStreamTrack videoTrack amp;amp; !videoTrack.IsDecoderInitialized)
{
receiveImage1.texture = videoTrack.InitializeReceiver(streamingSize.x, streamingSize.y);
}
if (e.Track is AudioStreamTrack audioTrack)
{
audioTrack.OnAudioReceived = clip =>
{
receiveAudio1.clip = clip;
receiveAudio1.loop = true;
receiveAudio1.Play();
};
}
};
pc1Local.OnIceCandidate = candidate => pc1Remote.AddIceCandidate(candidate);
pc1Remote.OnIceCandidate = candidate => pc1Local.AddIceCandidate(candidate);
Debug.Log("pc1: created local and remote peer connection object");
pc2Local = new RTCPeerConnection(ref configuration);
pc2Remote = new RTCPeerConnection(ref configuration);
pc2Remote.OnTrack = e =>
{
if (e.Track is VideoStreamTrack videoTrack amp;amp; !videoTrack.IsDecoderInitialized)
{
receiveImage2.texture = videoTrack.InitializeReceiver(streamingSize.x, streamingSize.y);
}
if (e.Track is AudioStreamTrack audioTrack)
{
audioTrack.OnAudioReceived = clip =>
{
receiveAudio2.clip = clip;
receiveAudio2.loop = true;
receiveAudio2.Play();
};
}
};
pc2Local.OnIceCandidate = candidate => pc2Remote.AddIceCandidate(candidate);
pc2Remote.OnIceCandidate = candidate => pc2Local.AddIceCandidate(candidate);
Debug.Log("pc2: created local and remote peer connection object");
foreach (var track in sourceStream.GetTracks())
{
pc1Local.AddTrack(track, sourceStream);
pc2Local.AddTrack(track, sourceStream);
}
Debug.Log("Adding local stream to pc1Local/pc2Local");
StartCoroutine(NegotiationPeer(pc1Local, pc1Remote));
StartCoroutine(NegotiationPeer(pc2Local, pc2Remote));
callButton.interactable = false;
hangUpButton.interactable = true;
}
private void HangUp()
{
foreach (var track in sourceStream.GetTracks())
{
track.Dispose();
}
sourceStream.Dispose();
sourceStream = null;
pc1Local.Close();
pc1Remote.Close();
pc2Local.Close();
pc2Remote.Close();
pc1Local.Dispose();
pc1Remote.Dispose();
pc2Local.Dispose();
pc2Remote.Dispose();
pc1Local = null;
pc1Remote = null;
pc2Local = null;
pc2Remote = null;
sourceImage.texture = null;
sourceAudio.Stop();
sourceAudio.clip = null;
receiveImage1.texture = null;
receiveAudio1.Stop();
receiveAudio1.clip = null;
receiveImage2.texture = null;
receiveAudio2.Stop();
receiveAudio2.clip = null;
startButton.interactable = true;
callButton.interactable = false;
hangUpButton.interactable = false;
}
private static void OnCreateSessionDescriptionError(RTCError error)
{
Debug.LogError($"Failed to create session description: {error.message}");
}
private static IEnumerator NegotiationPeer(RTCPeerConnection localPeer, RTCPeerConnection remotePeer)
{
var opCreateOffer = localPeer.CreateOffer();
yield return opCreateOffer;
if (opCreateOffer.IsError)
{
OnCreateSessionDescriptionError(opCreateOffer.Error);
yield break;
}
var offerDesc = opCreateOffer.Desc;
yield return localPeer.SetLocalDescription(ref offerDesc);
Debug.Log($"Offer from LocalPeer n {offerDesc.sdp}");
yield return remotePeer.SetRemoteDescription(ref offerDesc);
var opCreateAnswer = remotePeer.CreateAnswer();
yield return opCreateAnswer;
if (opCreateAnswer.IsError)
{
OnCreateSessionDescriptionError(opCreateAnswer.Error);
yield break;
}
var answerDesc = opCreateAnswer.Desc;
yield return remotePeer.SetLocalDescription(ref answerDesc);
Debug.Log($"Answer from RemotePeer n {answerDesc.sdp}");
yield return localPeer.SetRemoteDescription(ref answerDesc);
}
}
}
Когда я распаковываю этот проект на две сцены и вывожу два EXE-файла с одинаковым именем, один для показа и один для вызова, он не может работать, даже не может соединиться друг с другом.
Я думаю, проблема в том, что, возможно, я не подписал строку идентификатора или что-то в этом роде при использовании RTCIceServer, который показан ниже.
private static RTCConfiguration configuration = new RTCConfiguration
{
iceServers = new[] {new RTCIceServer {urls = new[] {"stun:stun.l.google.com:19302"}}}
};
Но я не знаю, как с этим справиться. Действительно спасибо за любую помощь.