RTCPeerConnection: метод addTrack()
Базовая Широко доступная
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с января 2020 года.
Метод addTrack() интерфейса RTCPeerConnection добавляет новый медиа-трек в набор треков, которые будут переданы другому участнику.
Примечание: Добавление трека к подключению запускает переподключение, вызывая событие negotiationneeded. Подробности см. в разделе Начало переподключения.
Синтаксис
addTrack(track) addTrack(track, stream1) addTrack(track, stream1, stream2) addTrack(track, stream1, stream2, /* …, */ streamN)
Параметры
track-
Объект
MediaStreamTrack, представляющий медиа-трек, который нужно добавить к подключению. stream1, …,streamNНеобязательно-
Один или несколько локальных объектов
MediaStream, к которым должен быть добавлен трек.
Указанный track необязательно должен уже быть частью любого из указанных stream. Вместо этого stream — способ группировать треки на принимающей стороне подключения, гарантируя их синхронизацию. Все треки, добавленные к одному потоку на локальном конце подключения, будут в том же потоке на удаленном конце.
Возвращаемое значение
Объект RTCRtpSender, который будет использоваться для передачи медиаданных.
Примечание: Каждый RTCRtpSender сопоставляется с RTCRtpReceiver, образуя RTCRtpTransceiver. Соответствующий приемник будет заглушен (что означает, что он не может доставлять пакеты), пока и до тех пор, пока один или несколько потоков не будут добавлены к приемнику удалённым участником.
Исключения
-
InvalidAccessErrorDOMException -
Выбрасывается, если указанный трек (или все его базовые потоки) уже является частью
RTCPeerConnection. -
InvalidStateErrorDOMException -
Выбрасывается, если
RTCPeerConnectionзакрыт.
Примечания по использованию
Добавление треков к нескольким потокам
После параметра track можно необязательно указать один или несколько объектов MediaStream, чтобы добавить в них трек. Только треки передаются от одного участника к другому, а не потоки. Поскольку потоки специфичны для каждого участника, указание одного или нескольких потоков означает, что другой участник автоматически создаст соответствующий поток (или потоки) на другом конце подключения и затем автоматически добавит полученный трек в эти потоки.
Треки без потоков
Если потоки не указаны, то трек является беспотоковым. Это вполне допустимо, хотя удалённому участнику придётся решить, в какой поток вставить трек, если таковой есть. Это очень распространённый способ использования addTrack() при создании многих типов простых приложений, где нужен только один поток. Например, если вы делитесь с удалённым участником только одним потоком с аудио- и видеотреками, вам не нужно управлять тем, какой трек в каком потоке, поэтому вы можете просто позволить трансиверу обработать это за вас.
Вот пример функции, которая использует getUserMedia() для получения потока с камеры и микрофона пользователя, а затем добавляет каждый трек из потока к подключению, не указывая поток для каждого трека:
async function openCall(pc) {
const gumStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
});
for (const track of gumStream.getTracks()) {
pc.addTrack(track);
}
}
Результат — набор треков, передаваемых удалённому участнику, без ассоциаций с потоками. Обработчик события track на удалённом участнике будет отвечать за определение потока, в который добавить каждый трек, даже если это означает добавление всех их в один поток. Обработчик события ontrack может выглядеть так:
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 добавляет трек к первому указанному потоку в событии, если таковой указан. В противном случае, в первый раз при вызове ontrack, создаётся новый поток и прикрепляется к элементу видео, а затем трек добавляется к новому потоку. Далее новые треки добавляются к этому потоку.
Вы также можете создавать новый поток для каждого полученного трека:
pc.ontrack = (ev) => {
if (ev.streams && ev.streams[0]) {
videoElem.srcObject = ev.streams[0];
} else {
let inboundStream = new MediaStream(ev.track);
videoElem.srcObject = inboundStream;
}
};
Связывание треков со специфическими потоками
Указывая поток и позволяя RTCPeerConnection создавать потоки за вас, ассоциации треков с потоками автоматически управляются инфраструктурой WebRTC. Это включает изменения в direction трансивера и остановку треков с помощью removeTrack().
Например, рассмотрим функцию, которую приложение может использовать для начала потоковой передачи ввода с камеры и микрофона устройства через RTCPeerConnection к удалённому участнику:
async function openCall(pc) {
const gumStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
});
for (const track of gumStream.getTracks()) {
pc.addTrack(track, gumStream);
}
}
Удалённый участник затем может использовать обработчик события track, который выглядит так:
pc.ontrack = ({ streams: [stream] }) => (videoElem.srcObject = stream);
Это устанавливает текущий поток элемента видео на тот, который содержит трек, который был добавлен к подключению.
Переиспользуемые отправители
Этот метод возвращает новый RTCRtpSender или существующий экземпляр для повторного использования. Экземпляр RTCRtpSender совместим для повторного использования только в том случае, если он соответствует следующим критериям:
- Трек не связан с отправителем.
- Трансивер
RTCRtpTransceiver, связанный с отправителем, имеет приемникRTCRtpReceiver, у которого свойствоtrackуказывает наMediaStreamTrack, у которого свойствоkindсовпадает с типомkindпараметраtrackпри вызовеRTCPeerConnection.addTrack(). Это гарантирует, что трансивер обрабатывает только аудио или видео, а не оба. - Свойство
RTCRtpTransceiver.currentDirectionне равно"stopped". - Рассматриваемый
RTCRtpSenderникогда не использовался для отправки данных. Если свойствоcurrentDirectionтрансивера когда-либо было"sendrecv"или"sendonly", отправитель не может быть повторно использован.
Если все эти критерии выполнены, отправитель переиспользуется, что приводит к этим изменениям в существующем RTCRtpSender и его RTCRtpTransceiver:
- Свойство
trackотправителя устанавливается на указанный трек. - Набор связанных потоков отправителя устанавливается в список потоков, переданных в этот метод,
stream.... - Связанный
RTCRtpTransceiverобновляется, чтобы указать, что он отправляет; если его текущее значение"recvonly", оно становится"sendrecv", а если"inactive", оно становится"sendonly".
Новые отправители
Если не существует существующего отправителя, который можно переиспользовать, создается новый. Это также приводит к созданию необходимых связанных объектов. Процесс создания нового отправителя приводит к следующим изменениям:
- Создаётся новый
RTCRtpSenderс указанным треком и набором потока(ов). - Создаётся новый
RTCRtpReceiverс новымMediaStreamTrackкак свойствоtrack(не тот трек, который указан в качестве параметра при вызовеaddTrack()). Типkindэтого трека устанавливается в соответствии с типомkindвходного параметра. - Создаётся новый
RTCRtpTransceiverи связывается с новым отправителем и приемником. - Направление
directionнового трансивера устанавливается в"sendrecv". - Новый трансивер добавляется в набор трансиверов
RTCPeerConnection.
Примеры
Этот пример взят из кода, представленного в статье Сигнальные сообщения и видеозвонки, и соответствующем примере кода. Он взят из метода handleVideoOfferMsg() , который вызывается при получении сообщения с предложением от удалённого узла.
const mediaConstraints = {
audio: true, // We want an audio track
video: true, // And we want a video track
};
const desc = new RTCSessionDescription(sdp);
pc.setRemoteDescription(desc)
.then(() => navigator.mediaDevices.getUserMedia(mediaConstraints))
.then((stream) => {
previewElement.srcObject = stream;
stream.getTracks().forEach((track) => pc.addTrack(track, stream));
});
Этот код принимает SDP, полученный от удалённого узла, и создаёт новый RTCSessionDescription для передачи в setRemoteDescription(). После успешного выполнения этой операции, используется MediaDevices.getUserMedia() для получения доступа к локальной веб-камере и микрофону.
Если операция успешна, полученный поток назначается источником для элемента <video>, на который ссылается переменная previewElement.
Окончательным этапом является начало отправки локального видео через соединение между узлами к звонящему. Это делается путём добавления каждого трека в поток, перебирая список, возвращаемый MediaStream.getTracks(), и передавая их в addTrack() вместе с stream , частью которого они являются.
Технические характеристики
Совместимость с браузерами
| Рабочий стол | Мобильные устройства | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox для Android | Opera Android | Safari на IOS | Samsung Internet | WebView Android | |
addTrack |
64 | 79 | 22 | 51 | 11 | 64 | 24 | 47 | 11 | 9.0 | 64 |
См. также
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTrack