Spec-Zone.ru › Web APIs

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. Соответствующий приемник будет заглушен (что означает, что он не может доставлять пакеты), пока и до тех пор, пока один или несколько потоков не будут добавлены к приемнику удалённым участником.

Исключения

InvalidAccessError DOMException

Выбрасывается, если указанный трек (или все его базовые потоки) уже является частью RTCPeerConnection.

InvalidStateError DOMException

Выбрасывается, если 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 , частью которого они являются.

Технические характеристики

Спецификация
WebRTC: Реальное взаимодействие в браузере
# dom-rtcpeerconnection-addtrack

Совместимость с браузерами

Рабочий стол Мобильные устройства
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

См. также

  • WebRTC
  • Введение в протокол реального времени (RTP)
  • track

© 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API