Specter.PeerConnection (specter v0.5.0)
View SourceRepresents an RTCPeerConnection managed in the NIF. A running Specter instance may have 0 or more peer connections at any time.
Users of Specter might choose between different topologies based on their use cases: a Specter might be initialized per connection, and signaling messages passed between different instances of the NIF; a Specter may be initialized per "room," and all peer connections for that room created within the single NIF instance; a "room" may be split across Erlang nodes, with tracks forwarded between the nodes.
Summary
Types
Options for creating a webrtc answer. Values default to false.
Message sent as a result of a call to connection_state/2
.
Possible states of peer connection.
An ICE candidate as JSON.
Message sent as a result of a call to ice_connection_state/2
.
Possible states of ICE connection.
Message sent as a result of a call to ice_gathering_state/2
.
Possible states of ICE gathering process.
Options for creating a webrtc offer. Values default to false.
Message sent as a result of a call to add_track/3
.
A UTF-8 encoded string encapsulating either an offer or an answer.
The type of an SDP message, either an :offer
or an :answer
.
A UTF-8 encoded string encapsulating an Offer or an Answer in JSON. The keys are as follows
Message sent as a result of a call to signaling_state/2
.
Possible states of session parameters negotiation.
Specter.PeerConnection.t/0
represents an instantiated RTCPeerConnection managed in the NIF.
Functions
Given an ICE candidate, add it to the given peer connection. Assumes trickle ICE.
Candidates must be JSON, with the keys candidate
, sdp_mid
, sdp_mline_index
, and
username_fragment
.
Adds track to peer connection.
Closes an open instance of an RTCPeerConnection.
Sends back state of peer connection.
This will send message connection_state_msg_t/0
.
Given an RTCPeerConnection where the remote description has been assigned via
set_remote_description/4
, create an answer that can be passed to another connection.
Creates a data channel on an RTCPeerConnection.
Given an RTCPeerConnection, create an offer that can be passed to another connection.
Sends back the value of the current session description on a peer connection. This will
send back JSON representing an offer or an answer when the peer connection has had
set_local_description/3
called and has successfully negotiated ICE. In all other cases,
nil
will be sent.
Sends back the value of the current remote session description on a peer connection. This will
send back JSON representing an offer or an answer when the peer connection has had
set_remote_description/3
called and has successfully negotiated ICE. In all other cases,
nil
will be sent.
Returns true or false, depending on whether the RTCPeerConnection is initialized.
Sends back a JSON encoded string representing the current stats of a peer connection.
Sends back state of ICE connection for given peer connection.
This will send message ice_connection_state_msg_t/0
Sends back state of ICE gathering process.
This will send message ice_gathering_state_t/0
.
Sends back the value of the local session description on a peer connection. This will
send back JSON representing an offer or an answer when the peer connection has had
set_local_description/3
called. If ICE has been successfully negotated, the current
local description will be sent back, otherwise the caller will receive the pending
local description.
Creates a new RTCPeerConnection, using an API reference created with new_api/3
. The
functionality wrapped by this function is async, so :ok
is returned immediately.
Callers should listen for the {:peer_connection_ready, peer_connection_t()}
message
to receive the results of this function.
Sends back the value of the session description on a peer connection that is pending connection, or nil.
Sends back the value of the remote session description on a peer connection on a peer that is pending connection, or nil.
Sends back the value of the remote session description on a peer connection. This will
send back JSON representing an offer or an answer when the peer connection has had
set_remote_description/3
called. If ICE has been successfully negotated, the current
remote description will be sent back, otherwise the caller will receive the pending
remote description.
Given an offer or an answer session description, sets the local description on
a peer connection. The description should be in the form of JSON with the keys
type
and sdp
.
Given an offer or an answer in the form of SDP generated by a remote party, sets
the remote description on a peer connection. Expects a session description in the
form of JSON with the keys type
and sdp
.
Sends back state of session parameters negotiation.
This will send message signaling_state_msg_t/0
.
Types
@type answer_options_t() :: [] | [{:voice_activity_detection, bool()}]
Options for creating a webrtc answer. Values default to false.
@type connection_state_msg_t() :: {:connection_state, t(), connection_state_t()}
Message sent as a result of a call to connection_state/2
.
@type connection_state_t() ::
:closed
| :connected
| :connecting
| :disconnected
| :failed
| :new
| :unspecified
Possible states of peer connection.
@type ice_candidate_t() :: String.t()
An ICE candidate as JSON.
@type ice_connection_state_msg_t() :: {:ice_connection_state, t(), ice_connection_state_t()}
Message sent as a result of a call to ice_connection_state/2
.
@type ice_connection_state_t() ::
:unspecified
| :new
| :checking
| :connected
| :completed
| :disconnected
| :failed
| :closed
Possible states of ICE connection.
@type ice_gathering_state_msg_t() :: {:ice_gathering_state, t(), ice_connection_state_t()}
Message sent as a result of a call to ice_gathering_state/2
.
@type ice_gathering_state_t() :: :complete | :gathering | :new | :unspecified
Possible states of ICE gathering process.
@type offer_options_t() ::
[] | [voice_activity_detection: bool(), ice_restart: bool()]
Options for creating a webrtc offer. Values default to false.
@type rtp_sender_t() :: {:rtp_sender, t(), Specter.TrackLocalStaticSample.t(), String.t()}
Message sent as a result of a call to add_track/3
.
@type sdp_t() :: String.t()
A UTF-8 encoded string encapsulating either an offer or an answer.
@type sdp_type_t() :: :offer | :answer
The type of an SDP message, either an :offer
or an :answer
.
@type session_description_t() :: String.t()
A UTF-8 encoded string encapsulating an Offer or an Answer in JSON. The keys are as follows:
key | type |
---|---|
type | offer , answer |
sdp | `sdp_t() |
@type signaling_state_msg_t() :: {:signaling_state, t(), signaling_state_t()}
Message sent as a result of a call to signaling_state/2
.
@type signaling_state_t() ::
:closed
| :have_local_offer
| :have_local_pranswer
| :have_remote_offer
| :have_remote_pranswer
| :stable
| :unspecified
Possible states of session parameters negotiation.
@opaque t()
Specter.PeerConnection.t/0
represents an instantiated RTCPeerConnection managed in the NIF.
Functions
@spec add_ice_candidate(Specter.t(), t(), ice_candidate_t()) :: :ok | {:error, term()}
Given an ICE candidate, add it to the given peer connection. Assumes trickle ICE.
Candidates must be JSON, with the keys candidate
, sdp_mid
, sdp_mline_index
, and
username_fragment
.
@spec add_track(Specter.t(), t(), Specter.TrackLocalStaticSample.t()) :: :ok | {:error | term()}
Adds track to peer connection.
Sends back uuid of newly created rtp sender.
This will send message t:rtp_sender_msg_t/0
.
Usage
iex> {:ok, specter} = Specter.init()
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc}
iex> codec = %Specter.RtpCodecCapability{mime_type: "audio"}
iex> {:ok, track} = Specter.TrackLocalStaticSample.new(specter, codec, "audio", "specter")
iex> :ok = Specter.PeerConnection.add_track(specter, pc, track)
iex> assert_receive {:rtp_sender, ^pc, ^track, _rtp_sender}
...>
iex> {:error, :invalid_track} = Specter.PeerConnection.add_track(specter, pc, "invalid_track")
Closes an open instance of an RTCPeerConnection.
Usage
iex> {:ok, specter} = Specter.init(ice_servers: ["stun:stun.l.google.com:19302"])
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc}
...>
iex> Specter.PeerConnection.close(specter, pc)
:ok
iex> {:ok, _pc} =
...> receive do
...> {:peer_connection_closed, ^pc} -> {:ok, pc}
...> after
...> 500 -> {:error, :timeout}
...> end
...>
iex> Specter.PeerConnection.exists?(specter, pc)
false
Sends back state of peer connection.
This will send message connection_state_msg_t/0
.
@spec create_answer(Specter.t(), t(), answer_options_t()) :: :ok | {:error, term()}
Given an RTCPeerConnection where the remote description has been assigned via
set_remote_description/4
, create an answer that can be passed to another connection.
param | type | default |
---|---|---|
specter | t() | |
peer_connection | opaque | |
options | answer_options_t() | voice_activity_detection: false |
Creates a data channel on an RTCPeerConnection.
Note: this can be useful when attempting to generate a valid offer, but where no media tracks are expected to be sent or received. Callbacks from data channels have not yet been implemented.
@spec create_offer(Specter.t(), t(), offer_options_t()) :: :ok | {:error, term()}
Given an RTCPeerConnection, create an offer that can be passed to another connection.
param | type | default |
---|---|---|
specter | t() | |
peer_connection | opaque | |
options | offer_options_t() | voice_activity_detection: false |
ice_restart: false |
Sends back the value of the current session description on a peer connection. This will
send back JSON representing an offer or an answer when the peer connection has had
set_local_description/3
called and has successfully negotiated ICE. In all other cases,
nil
will be sent.
See pending_local_description/2
and local_description/2
.
Usage
iex> {:ok, specter} = Specter.init()
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc}
iex> Specter.PeerConnection.current_local_description(specter, pc)
:ok
iex> assert_receive {:current_local_description, ^pc, nil}
Sends back the value of the current remote session description on a peer connection. This will
send back JSON representing an offer or an answer when the peer connection has had
set_remote_description/3
called and has successfully negotiated ICE. In all other cases,
nil
will be sent.
See current_remote_description/2
and remote_description/2
.
Usage
iex> {:ok, specter} = Specter.init()
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc}
iex> Specter.PeerConnection.current_remote_description(specter, pc)
:ok
iex> assert_receive {:current_remote_description, ^pc, nil}
Returns true or false, depending on whether the RTCPeerConnection is initialized.
Usage
iex> {:ok, specter} = Specter.init(ice_servers: ["stun:stun.l.google.com:19302"])
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc}
iex> Specter.PeerConnection.exists?(specter, pc)
true
iex> {:ok, specter} = Specter.init(ice_servers: ["stun:stun.l.google.com:19302"])
iex> Specter.PeerConnection.exists?(specter, UUID.uuid4())
false
Sends back a JSON encoded string representing the current stats of a peer connection.
Usage
iex> {:ok, specter} = Specter.init()
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc}
...>
iex> Specter.PeerConnection.get_stats(specter, pc)
:ok
iex> assert_receive {:stats, ^pc, json}
iex> {:ok, _stats} = Jason.decode(json)
Sends back state of ICE connection for given peer connection.
This will send message ice_connection_state_msg_t/0
Sends back state of ICE gathering process.
This will send message ice_gathering_state_t/0
.
Sends back the value of the local session description on a peer connection. This will
send back JSON representing an offer or an answer when the peer connection has had
set_local_description/3
called. If ICE has been successfully negotated, the current
local description will be sent back, otherwise the caller will receive the pending
local description.
See current_local_description/2
and pending_local_description/2
.
Usage
iex> {:ok, specter} = Specter.init()
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc}
...>
iex> Specter.PeerConnection.local_description(specter, pc)
:ok
iex> assert_receive {:local_description, ^pc, nil}
...>
iex> :ok = Specter.PeerConnection.create_offer(specter, pc)
iex> assert_receive {:offer, ^pc, offer}
iex> :ok = Specter.PeerConnection.set_local_description(specter, pc, offer)
iex> assert_receive {:ok, ^pc, :set_local_description}
...>
iex> Specter.PeerConnection.local_description(specter, pc)
:ok
iex> assert_receive {:local_description, ^pc, ^offer}
@spec new(Specter.t(), Specter.api_t()) :: {:ok, t()} | {:error, term()}
Creates a new RTCPeerConnection, using an API reference created with new_api/3
. The
functionality wrapped by this function is async, so :ok
is returned immediately.
Callers should listen for the {:peer_connection_ready, peer_connection_t()}
message
to receive the results of this function.
param | type | default |
---|---|---|
specter | t() | |
api | opaque |
Usage
iex> {:ok, specter} = Specter.init(ice_servers: ["stun:stun.l.google.com:19302"])
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
...>
iex> {:ok, _pc} =
...> receive do
...> {:peer_connection_ready, ^pc} -> {:ok, pc}
...> after
...> 500 -> {:error, :timeout}
...> end
Sends back the value of the session description on a peer connection that is pending connection, or nil.
Usage
iex> {:ok, specter} = Specter.init()
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc}
...>
iex> Specter.PeerConnection.pending_local_description(specter, pc)
:ok
iex> assert_receive {:pending_local_description, ^pc, nil}
...>
iex> :ok = Specter.PeerConnection.create_offer(specter, pc)
iex> assert_receive {:offer, ^pc, offer}
iex> :ok = Specter.PeerConnection.set_local_description(specter, pc, offer)
iex> assert_receive {:ok, ^pc, :set_local_description}
...>
iex> Specter.PeerConnection.pending_local_description(specter, pc)
:ok
iex> assert_receive {:pending_local_description, ^pc, ^offer}
Sends back the value of the remote session description on a peer connection on a peer that is pending connection, or nil.
See current_remote_description/2
and pending_remote_description/2
.
Usage
iex> {:ok, specter} = Specter.init()
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc_offer} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc_offer}
iex> :ok = Specter.PeerConnection.create_data_channel(specter, pc_offer, "foo")
iex> assert_receive {:data_channel_created, ^pc_offer}
iex> :ok = Specter.PeerConnection.create_offer(specter, pc_offer)
iex> assert_receive {:offer, ^pc_offer, offer}
...>
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc_answer} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc_answer}
...>
iex> Specter.PeerConnection.pending_remote_description(specter, pc_answer)
:ok
iex> assert_receive {:pending_remote_description, ^pc_answer, nil}
...>
iex> :ok = Specter.PeerConnection.set_remote_description(specter, pc_answer, offer)
iex> assert_receive {:ok, ^pc_answer, :set_remote_description}
...>
iex> Specter.PeerConnection.pending_remote_description(specter, pc_answer)
:ok
iex> assert_receive {:pending_remote_description, ^pc_answer, ^offer}
Sends back the value of the remote session description on a peer connection. This will
send back JSON representing an offer or an answer when the peer connection has had
set_remote_description/3
called. If ICE has been successfully negotated, the current
remote description will be sent back, otherwise the caller will receive the pending
remote description.
See current_remote_description/2
and remote_description/2
.
Usage
iex> {:ok, specter} = Specter.init()
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc_offer} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc_offer}
iex> :ok = Specter.PeerConnection.create_data_channel(specter, pc_offer, "foo")
iex> assert_receive {:data_channel_created, ^pc_offer}
iex> :ok = Specter.PeerConnection.create_offer(specter, pc_offer)
iex> assert_receive {:offer, ^pc_offer, offer}
...>
iex> {:ok, media_engine} = Specter.new_media_engine(specter)
iex> {:ok, registry} = Specter.new_registry(specter, media_engine)
iex> {:ok, api} = Specter.new_api(specter, media_engine, registry)
iex> {:ok, pc_answer} = Specter.PeerConnection.new(specter, api)
iex> assert_receive {:peer_connection_ready, ^pc_answer}
...>
iex> Specter.PeerConnection.remote_description(specter, pc_answer)
:ok
iex> assert_receive {:remote_description, ^pc_answer, nil}
...>
iex> :ok = Specter.PeerConnection.set_remote_description(specter, pc_answer, offer)
iex> assert_receive {:ok, ^pc_answer, :set_remote_description}
...>
iex> Specter.PeerConnection.remote_description(specter, pc_answer)
:ok
iex> assert_receive {:remote_description, ^pc_answer, ^offer}
@spec set_local_description(Specter.t(), t(), session_description_t()) :: :ok | {:error, term()}
Given an offer or an answer session description, sets the local description on
a peer connection. The description should be in the form of JSON with the keys
type
and sdp
.
param | type | default |
---|---|---|
specter | t/0 | |
peer_connection | opaque | |
description | t:session_description_t() |
@spec set_remote_description(Specter.t(), t(), session_description_t()) :: :ok | {:error, term()}
Given an offer or an answer in the form of SDP generated by a remote party, sets
the remote description on a peer connection. Expects a session description in the
form of JSON with the keys type
and sdp
.
param | type | default |
---|---|---|
specter | t/0 | |
peer_connection | opaque | |
description | session_description_t/0 |
Sends back state of session parameters negotiation.
This will send message signaling_state_msg_t/0
.