Я создаю приложение WebRTC, в котором пользователи могут делиться своей камерой и своим экраном. Когда клиент получает поток / дорожку, ему необходимо знать, является ли это потоком камеры или потоком записи экрана. Это различие очевидно на передающей стороне, но различие теряется к тому времени, когда треки достигают принимающего партнера.
Вот пример кода из моего приложения:
// Note the distinction between streams is obvious at the sending end.
const localWebcamStream = await navigator.mediaDevices.getUserMedia({ ... });
const screenCaptureStream = await navigator.mediaDevices.getDisplayMedia({ ... });
// This is called by signalling logic
function addLocalTracksToPeerConn(peerConn) {
// Our approach here loses information because our two distinct streams
// are added to the PeerConnection's homogeneous bag of streams
for (const track of screenCaptureStream.getTracks()) {
peerConn.addTrack(track, screenCaptureStream);
}
for (const track of localWebcamStream.getTracks()) {
peerConn.addTrack(track, localWebcamStream);
}
}
// This is called by signalling logic
function handleRemoteTracksFromPeerConn(peerConn) {
peerConn.ontrack = ev => {
const stream = ev.streams[0];
if (stream is a camera stream) { // FIXME how to distinguish reliably?
remoteWebcamVideoEl.srcObject = stream;
}
else if (stream is a screen capture) { // FIXME how to distinguish reliably?
remoteScreenCaptureVideoEl.srcObject = stream;
}
};
}
Мой идеальный воображаемый API позволил бы добавить .label
к дорожке или потоку, например:
// On sending end, add arbitrary metadata
track.label = "screenCapture";
peerConn.addTrack(track, screenCaptureStream);
// On receiving end, retrieve arbitrary metadata
peerConn.ontrack = ev => {
const trackType = ev.track.label; // get the label when receiving the track
}
Но этого API на самом деле не существует. Есть свойство MediaStreamTrack.label
, но оно читается - только и не сохранился в передаче. Экспериментируя, свойство .label на отправляющей стороне является информативным (например, label: "FaceTime HD Camera (Built-in) (05ac:8514)"
). Но на принимающей стороне .label
для того же трека не сохраняется. (Кажется, он заменен на .id
трека - по крайней мере, в Chrome.)
В этой статье Кевина Морленда описывается та же проблема, и рекомендует умеренно устрашающее решение: подключите SDP к отправляющей стороне, а затем выполните grep с SDP на принимающей стороне. Но это решение кажется очень хрупким и низкоуровневым.
Я знаю, что есть свойство MediaStreamTrack.id
. Также есть свойство MediaStream.id
. Оба они, похоже, сохраняются при передаче. Это означает, что я мог отправлять метаданные по побочному каналу, например сигнальному каналу или DataChannel
. Со стороны отправки я бы отправил { "myStreams": { "screen": "<some stream id>", "camera": "<another stream id>" } }
. Принимающая сторона будет ждать, пока у нее появятся и метаданные, и поток, прежде чем что-либо отображать. Однако этот подход вводит побочный канал (и неизбежные проблемы параллелизма, связанные с этим), где побочный канал кажется ненужным.
Я ищу идиоматическое надежное решение. Как мне пометить / идентифицировать MediaStreams на отправляющей стороне, чтобы принимающая сторона знала, какой поток какой?