RTCPeerConnection
方法
addTrack()
adds a new media track to the set of tracks which will be transmitted to the other peer.
注意:
Adding a track to a connection triggers renegotiation by firing a
negotiationneeded
event. See
Starting negotiation
in
Signaling and video calling
了解细节。
rtpSender = rtcPeerConnection.addTrack(track, stream...);
track
MediaStreamTrack
object representing the media track to add to the peer connection.
stream...
可选
MediaStream
objects to which the track should be added.
指定
track
doesn't necessarily have to already be part of any of the specified
stream
s. Instead, the
stream
s are simply a way to group tracks together on the receiving end of the connection, making sure they are synchronized. Any tracks that are added to the same stream on the local end of the connection will be on the same stream on the remote end.
RTCRtpSender
object which will be used to transmit the media data.
注意:
每个
RTCRtpSender
is paired with an
RTCRtpReceiver
to make up an
RTCRtpTransceiver
. The associated receiver is muted (indicating that it is not able to deliver packets) until and unless one or more streams are added to the receiver by the remote peer.
InvalidAccessError
RTCPeerConnection
.
InvalidStateError
RTCPeerConnection
is closed.
之后
track
parameter, you can optionally specify one or more
MediaStream
objects to add the track to. Only tracks are sent from one peer to another, not streams. Since streams are specific to each peer, specifying one or more streams means the other peer will create a corresponding stream (or streams) automatically on the other end of the connection, and will then automatically add the received track to those streams.
If no streams are specified, then the track is
streamless
. This is perfectly acceptable, although it will be up to the remote peer to decide what stream to insert the track into, if any. This is a very common way to use
addTrack()
when building many types of simple applications, where only one stream is needed. For example, if all you're sharing with the remote peer is a single stream with an audio track and a video track, you don't need to deal with managing what track is in what stream, so you might as well just let the transceiver handle it for you.
Here's an example showing a function that uses
getUserMedia()
to obtain a stream from a user's camera and microphone, then adds each track from the stream to the peer connection, without specifying a stream for each track:
async openCall(pc) {
const gumStream = await navigator.mediaDevices.getUserMedia(
{video: true, audio: true});
for (const track of gumStream.getTracks()) {
pc.addTrack(track);
}
}
The result is a set of tracks being sent to the remote peer, with no stream associations. The handler for the
track
event on the remote peer will be responsible for determining what stream to add each track to, even if that means simply adding them all to the same stream. The
ontrack
handler might look like this:
let inboundStream = null;
pc.ontrack = ev => {
if (ev.streams && ev.streams[0]) {
videoElem.srcObject = ev.streams[0];
} else {
if (!inboundStream) {
inboundStream = new MediaStream();
videoElem.srcObject = inboundStream;
}
inboundStream.addTrack(ev.track);
}
}
在这里,
track
event handler adds the track to the first stream specified by the event, if a stream is specified. Otherwise, the first time
ontrack
is called, a new stream is created and attached to the video element, and then the track is added to the new stream. From then on, new tracks are added to that stream.
You could also just create a new stream for each track received:
pc.ontrack = ev => {
if (ev.streams && ev.streams[0]) {
videoElem.srcObject = ev.streams[0];
} else {
let inboundStream = new MediaStream(ev.track);
videoElem.srcObject = inboundStream;
}
}
By specifying a stream and allowing
RTCPeerConnection
to create streams for you, the streams' track associations are automatically managed for you by the WebRTC infrastructure. This includes things like changes to the transceiver's
direction
and tracks being halted using
removeTrack()
.
For example, consider this function that an application might use to begin streaming a device's camera and microphone input over an
RTCPeerConnection
to a remote peer:
async openCall(pc) {
const gumStream = await navigator.mediaDevices.getUserMedia(
{video: true, audio: true});
for (const track of gumStream.getTracks()) {
pc.addTrack(track, gumStream);
}
}
The remote peer might then use a
track
event handler that looks like this:
pc.ontrack = ({streams: [stream]} => videoElem.srcObject = stream;
This sets the video element's current stream to the one that contains the track that's been added to the connection.
This method may return either a new
RTCRtpSender
or, under very specific circumstances, an existing compatible sender which has not yet been used to transmit data. Compatible reusable
RTCRtpSender
instances meet these criteria:
RTCRtpTransceiver
associated with the sender has a
RTCRtpReceiver
whose
track
property specifies a
MediaStreamTrack
whose
kind
is the same as the
kind
的
track
parameter specified when calling
RTCPeerConnection.addTrack()
. This ensures that a transceiver only handles audio or video and never both.
RTCRtpTransceiver
's
stopped
特性为
false
.
RTCRtpSender
being considered has never been used to send data. If the transceiver's
currentDirection
has ever been
"sendrecv"
or
"sendonly"
, the sender can't be reused.
If all of those criteria are met, the sender gets reused, which results in these changes occurring to the existing
RTCRtpSender
及其
RTCRtpTransceiver
:
RTCRtpSender
's
track
is set to the specified track.
stream...
.
RTCRtpTransceiver
有它自己的
currentDirection
updated to include sending; if its current value is
"recvonly"
, it becomes
"sendrecv"
, and if its current value is
"inactive"
, it becomes
"sendonly"
.
If no existing sender exists that can be reused, a new one is created. This also results in the creation of the associated objects that must exist. The process of creating a new sender results in these changes:
RTCRtpSender
is created with the specified
track
and set of
stream
(s).
RTCRtpReceiver
is created with a
new
MediaStreamTrack
as its
track
property (not the track specified as a parameter when calling
addTrack()
). This track's
kind
is set to match the
kind
of the track provided as an input parameter.
RTCRtpTransceiver
is created and associated with the new sender and receiver.
direction
被设为
"sendrecv"
.
RTCPeerConnection
's set of transceivers.
This example is drawn from the code presented in the article
Signaling and video calling
and its corresponding sample code. It comes from the
handleVideoOfferMsg()
method there, which is called when an offer message is received from the remote peer.
var mediaConstraints = {
audio: true, // We want an audio track
video: true // ...and we want a video track
};
var desc = new RTCSessionDescription(sdp);
pc.setRemoteDescription(desc).then(function () {
return navigator.mediaDevices.getUserMedia(mediaConstraints);
})
.then(function(stream) {
previewElement.srcObject = stream;
stream.getTracks().forEach(track => pc.addTrack(track, stream));
})
This code takes SDP which has been received from the remote peer and constructs a new
RTCSessionDescription
to pass into
setRemoteDescription()
. Once that succeeds, it uses
MediaDevices.getUserMedia()
to obtain access to the local webcam and microphone.
If that succeeds, the resulting stream is assigned as the source for a
<video>
element which is referenced by the variable
previewElement
.
The final step is to begin sending the local video across the peer connection to the caller. This is done by adding each track in the stream by iterating over the list returned by
MediaStream.getTracks()
and passing them to
addTrack()
along with the
stream
which they're a component of.
| 规范 | 状态 | 注释 |
|---|---|---|
|
WebRTC 1.0: Real-time Communication Between Browsers
The definition of 'RTCPeerConnection.addTrack()' in that specification. |
候选推荐 | 最初的规范。 |
| 桌面 | 移动 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
addTrack
|
Chrome 64 | Edge ≤18 | Firefox 22 | IE No | Opera 51 | Safari 11 | WebView Android 64 | Chrome Android 64 | Firefox Android 44 | Opera Android 47 | Safari iOS Yes | Samsung Internet Android 6.0 |
完整支持
不支持
RTCPeerConnection
canTrickleIceCandidates
connectionState
currentLocalDescription
currentRemoteDescription
getDefaultIceServers()
iceConnectionState
iceGatheringState
localDescription
onaddstream
onconnectionstatechange
ondatachannel
onicecandidate
oniceconnectionstatechange
onicegatheringstatechange
onidentityresult
onidpassertionerror
onidpvalidationerror
onnegotiationneeded
onpeeridentity
onremovestream
onsignalingstatechange
ontrack
peerIdentity
pendingLocalDescription
pendingRemoteDescription
remoteDescription
sctp
signalingState
addIceCandidate()
addStream()
addTrack()
close()
createAnswer()
createDataChannel()
createOffer()
generateCertificate()
getConfiguration()
getIdentityAssertion()
getReceivers()
getSenders()
getStats()
getStreamById()
getTransceivers()
removeStream()
removeTrack()
restartIce()
setConfiguration()
setIdentityProvider()
setLocalDescription()
setRemoteDescription()
MediaDevices.getUserMedia()
Navigator.mediaDevices
RTCCertificate
RTCDTMFSender
RTCDTMFToneChangeEvent
RTCDataChannel
RTCDataChannelEvent
RTCDtlsTransport
RTCErrorEvent
RTCIceCandidate
RTCIceTransport
RTCPeerConnectionIceErrorEvent
RTCPeerConnectionIceEvent
RTCRtpReceiver
RTCRtpSender
RTCRtpTransceiver
RTCSctpTransport
RTCSessionDescription
RTCStatsEvent
RTCStatsReport
RTCTrackEvent