using System;
using System.Collections.Generic;
using System.Linq;
using Unity.WebRTC;
using UnityEngine;
namespace Unity.RenderStreaming
{
///
/// AudioStreamReceiver is a component that receives audio streams and plays them through a specified AudioSource.
///
///
[AddComponentMenu("Render Streaming/Audio Stream Receiver")]
public class AudioStreamReceiver : StreamReceiverBase
{
internal const string CodecPropertyName = nameof(m_Codec);
internal const string TargetAudioSourcePropertyName = nameof(m_TargetAudioSource);
///
/// Delegate for handling updates to the received audio source.
///
/// The updated AudioSource.
public delegate void OnUpdateReceiveAudioSourceHandler(AudioSource source);
///
/// Event triggered when the received audio source is updated.
///
public OnUpdateReceiveAudioSourceHandler OnUpdateReceiveAudioSource;
[SerializeField]
private AudioSource m_TargetAudioSource;
[SerializeField, Codec]
private AudioCodecInfo m_Codec;
///
/// Gets the codec information for the audio stream.
///
public AudioCodecInfo codec
{
get { return m_Codec; }
}
///
/// Gets or sets the target AudioSource where the received audio will be played.
///
public AudioSource targetAudioSource
{
get { return m_TargetAudioSource; }
set { m_TargetAudioSource = value; }
}
///
/// Gets the available audio codecs.
///
///
/// var codecs = AudioStreamReceiver.GetAvailableCodecs();
/// foreach (var codec in codecs)
/// Debug.Log(codec.name);
///
///
/// A list of available codecs.
static public IEnumerable GetAvailableCodecs()
{
var excludeCodecMimeType = new[] { "audio/CN", "audio/telephone-event" };
var capabilities = RTCRtpReceiver.GetCapabilities(TrackKind.Audio);
return capabilities.codecs.Where(codec => !excludeCodecMimeType.Contains(codec.mimeType)).Select(codec => AudioCodecInfo.Create(codec));
}
///
/// Sets the codec for the audio stream.
///
///
///
/// x.mimeType.Contains("opus"));
/// audioStreamReceiver.SetCodec(codec);
/// ]]>
///
///
/// The codec information to set.
/// Thrown if the transceiver is streaming or the track has ended.
public void SetCodec(AudioCodecInfo codec)
{
m_Codec = codec;
if (Transceiver == null)
return;
if (!string.IsNullOrEmpty(Transceiver.Mid))
throw new InvalidOperationException("Transceiver is streaming. This operation is invalid during the track is in use.");
if (Transceiver.Sender.Track.ReadyState == TrackState.Ended)
throw new InvalidOperationException("Track has already been ended.");
var codecs = new AudioCodecInfo[] { m_Codec };
RTCErrorType error = Transceiver.SetCodecPreferences(SelectCodecCapabilities(codecs).ToArray());
if (error != RTCErrorType.None)
throw new InvalidOperationException($"Set codec is failed. errorCode={error}");
}
internal IEnumerable SelectCodecCapabilities(IEnumerable codecs)
{
return RTCRtpReceiver.GetCapabilities(TrackKind.Audio).SelectCodecCapabilities(codecs);
}
private protected virtual void Start()
{
OnStartedStream += StartedStream;
OnStoppedStream += StoppedStream;
}
private void StartedStream(string connectionId)
{
if (Track is AudioStreamTrack audioTrack)
{
m_TargetAudioSource?.SetTrack(audioTrack);
OnUpdateReceiveAudioSource?.Invoke(m_TargetAudioSource);
}
}
private void StoppedStream(string connectionId)
{
}
}
}