Изменение MediaStream RTCPeerConnection

Я хочу перейти с аудио- / видеопотока на поток с разделением экрана:

peerConnection.removeStream(streamA) // __o_j_sep... in Screenshots below
peerConnection.addStream(streamB)  // SSTREAM in Screenshots below
  • streamA это видео / аудио поток с моей камеры и микрофона.
  • streamB это скриншот, который я получаю от моего расширения.
  • Оба объекта MediaStream выглядят так:

streamA

streamB

* 1 замечание

Но если я уберу streamA от peerConnection а также addStream(streamB) вроде выше ничего не происходит.

Следующее работает как ожидалось (поток на обоих концах удален и повторно добавлен)

peerConnection.removeStream(streamA) // __o_j_sep...
peerConnection.addStream(streamA) // __o_j_sep...

Подробнее

Я нашел этот пример, который делает "наоборот" (переключение с захвата экрана на аудио / видео с камеры), но не может заметить существенную разницу.

peerConnection Объект RTCPeerConnection фактически создается этим исходным кодом библиотеки SIPML, доступным здесь. И я получаю к нему доступ так:

var peerConnection = stack.o_stack.o_layer_dialog.ao_dialogs[1].o_msession_mgr.ao_sessions[0].o_pc

(Да, это выглядит неправильно, но нет официального способа получить доступ к одноранговому соединению, см. Обсуждение здесь) и здесь.

Первоначально я пытался просто (ex) изменить videoTracks streamA с видео-треком streamB, Смотрите вопрос здесь. Мне было предложено попытаться пересмотреть одноранговое соединение (удалив / добавив к нему потоки), потому что addTrack не вызывает повторное пометку.

Я также попросил помощи здесь, но сопровождающий кажется очень занятым и не имел возможности ответить.


* 1 Примечание: почему streamB не иметь videoTracks имущество? Поток играет в HTML <video> элемент и, кажется, "работает". Вот как я это понял:

navigator.webkitGetUserMedia({
  audio: false,
  video: {
    mandatory: {
      chromeMediaSource:  'desktop',
      chromeMediaSourceId: streamId,
      maxWidth: window.screen.width,
      maxHeight: window.screen.height
      //,   maxFrameRate: 3
    }
  }
  // success callback
}, function(localMediaStream) {
  SSTREAM = localMediaStream; //streamB

  // fail callback
}, function(error) {
  console.log(error);
});

это также, кажется, имеет videoTrack:

videoTrack из streamB

Я бегу:

  • OS X 10.9.3
  • Версия Chrome 35.0.1916.153

2 ответа

Решение

Чтобы ответить на ваш первый вопрос, при изменении MediaStream в активном одноранговом соединении объект однорангового соединения вызовет onnegotiationneeded событие. Вы должны обработать это событие и повторно обменять свои SDP. Основная причина этого заключается в том, что обе стороны знают, какие потоки передаются между ними. Когда SDP обмениваются, включается идентификатор mediaStream, и, если есть новый поток с новым идентификатором (событие при прочих равных условиях), необходимо выполнить повторное согласование.

Для вас второй вопрос (о SSTREAM). Он действительно содержит видео-треки, но нет атрибута видеотрека для webkitMediaStreams, Вы можете получить треки через их ID, однако.

Поскольку существует возможность иметь множество дорожек для каждого типа мультимедиа, для видеотрека или аудиотрека нет отдельного атрибута, а вместо этого имеется массив таких. .getVideoTracks() Вызов возвращает массив текущих videoTracks. Таким образом, вы МОЖЕТЕ получить определенную видео дорожку, указав ее индекс .getVideoTracks()[0],

Я делаю нечто подобное, нажимая на кнопку, я удаляю активный поток и добавляю другой.

Это то, как я это делаю, и это прекрасно работает для меня,

_this.rtc.localstream.stop();
_this.rtc.pc.removeStream(_this.rtc.localstream);

gotStream = function (localstream_aud){
var constraints_audio={
    audio:true
   }

_this.rtc.localstream_aud = localstream_aud;
_this.rtc.mediaConstraints= constraints_audio;   
_this.rtc.createOffer();
}
getUserMedia(constraints_audio, gotStream);

gotStream = function (localstream){
var constraints_screen={
        audio:false,
        video:{
            mandatory:{
                chromeMediaSource: 'screen'
            }
        }
    }
  _this.rtc.localstream = localstream;
  _this.rtc.mediaConstraints=constraints_video;


  _this.rtc.createStream();  
  _this.rtc.createOffer();
}
getUserMedia(constraints_video, gotStream);

Chrome не поддерживает звук вместе с "экраном", поэтому я создаю для него отдельный поток. Вам нужно будет сделать наоборот, чтобы переключиться обратно на ваш старый видеопоток или фактически на любой другой поток, который вы хотите.

Надеюсь это поможет

Другие вопросы по тегам