WebRTC는 브라우저에서 오디오 및 비디오 통신을 구현합니다.

개요

WebRTC  (Web Real-Time Communications)는 네트워크 응용 프로그램 또는 사이트가 비디오 스트리밍 및/또는 전송을 달성하기 위해 중개자 없이 브라우저 간에 피어 투 피어(Peer-to-Peer) 연결을 설정할 수 있는 실시간 통신 기술입니다. 오디오 스트림 또는 기타 임의 데이터. WebRTC에 포함된 이러한 표준을 통해 사용자는 플러그인이나 타사 소프트웨어를 설치하지 않고도 피어 투 피어(Peer-to-Peer) 데이터 공유 및 화상 회의를 만들 수 있습니다.

webRTC 프로토콜 소개

얼음

ICE(Interactive Connectivity Establishment)는 웹 브라우저가 피어와 연결할 수 있도록 하는 프레임워크입니다. 피어 A에서 피어 B로의 직접 연결이 작동하지 않는 데는 여러 가지 이유가 있습니다. 개방형 연결을 막는 방화벽을 우회하고, 장치에 공용 IP 주소가 없는 경우 고유한 주소를 제공하고, 라우터가 피어와 직접 통신할 수 없는 경우 서버를 통해 데이터를 릴레이해야 합니다. 연결하다. ICE는 아래에 설명된 대로 이러한 목적으로 STUN 및/또는 TURN 서버를 사용합니다.

충격

STUN(Session Transverse Utility for NAT)은 공용 주소를 검색하고 피어에 대한 직접 연결을 방지하는 라우터의 제한 사항을 식별하는 프로토콜입니다.

클라이언트는 인터넷의 STUN 서버에 요청을 보내고 클라이언트의 공용 주소와 라우터 NAT 뒤에서 클라이언트에 액세스할 수 있는지 여부를 응답합니다.
 

NAT

NAT(Network Address Translation)는 장치에 공용 IP 주소를 제공하는 데 사용됩니다. 라우터에는 공용 IP 주소가 있고 라우터에 연결된 각 장치에는 개인 IP 주소가 있습니다. 요청은 고유한 포트를 사용하여 장치의 개인 IP에서 라우터의 공용 IP로 변환됩니다. 이렇게 하면 각 장치가 고유한 공용 IP를 가질 필요가 없지만 여전히 인터넷에서 검색할 수 있습니다.

일부 라우터는 네트워크의 장치에 연결할 수 있는 사용자를 제한합니다. 이는 STUN 서버에서 찾은 공용 IP 주소가 있더라도 아무도 연결을 생성할 수 없음을 의미할 수 있습니다. 이 경우 핸들을 돌려야 합니다.

회전하다

NAT를 사용하는 일부 라우터는 "대칭 NAT"라는 제한을 사용합니다. 이는 라우터가 이전에 연결한 피어의 연결만 수락함을 의미합니다.

NAT 주변의 릴레이를 사용하는 전송(전송)은 TURN 서버에 대한 연결을 열고 해당 서버를 통해 모든 정보를 릴레이하여 대칭 NAT 제한을 우회하도록 설계되었습니다. TURN 서버에 대한 연결을 생성하고 모든 상대에게 서버로 패킷을 보내도록 지시하면 패킷이 서버로 전달됩니다. 이것은 분명히 약간의 오버헤드가 있으므로 다른 옵션이 없는 경우에만 사용됩니다.
 

SDP

SDP(Session Description Protocol)는 데이터가 전송될 때 두 피어가 서로 이해할 수 있도록 해상도, 형식, 코덱, 암호화 등과 같은 연결의 멀티미디어 콘텐츠를 설명하는 표준입니다. 이것은 기본적으로 미디어 콘텐츠 자체가 아니라 콘텐츠를 설명하는 메타데이터입니다.

따라서 기술적으로 말하면 SDP는 실제로 프로토콜이 아니라 장치 간의 공유 미디어 연결을 설명하는 데 사용되는 데이터 형식입니다.

SDP를 문서화하는 것은 이 문서의 범위를 훨씬 벗어나지만 여기에서 주목할 가치가 있는 몇 가지 사항이 있습니다.

웹RTC API

WebRTC는 주로 브라우저가 세 가지 기능을 갖도록 합니다.

  • 오디오 및 비디오 가져오기
  • 오디오 및 비디오 통신 수행
  • 임의의 데이터 통신

WebRTC는 위의 세 가지 기능에 해당하는 세 가지 API로 나뉩니다.

  • MediaStream(일명 getUserMedia)
  • RTCPeerConnection
  • RTC데이터 채널

getUserMedia

개요

navigator.getUserMedia 메서드는 현재 주로 브라우저에서 오디오(마이크를 통해) 및 비디오(카메라를 통해)를 얻는 데 사용되며 향후 디스크 및 센서와 같은 임의의 데이터 스트림을 얻는 데 사용할 수 있습니다.

다음 코드는 브라우저가 getUserMedia 메서드를 지원하는지 확인하는 데 사용됩니다.

navigator.getUserMedia  = navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia;

if (navigator.getUserMedia) {
    // 支持
} else {
    // 不支持
}

Chrome 21, Opera 18 및 Firefox 17은 이 방법을 지원합니다. 현재 IE는 아직 지원하지 않으며 위 코드의 msGetUserMedia는 향후 호환성을 보장하기 위한 것입니다.

getUserMedia 메소드는 세 개의 매개변수를 허용합니다.

navigator.getUserMedia({
    video: true, 
    audio: true
}, onSuccess, onError);

getUserMedia의 첫 번째 매개변수는 획득할 멀티미디어 장치를 나타내는 객체이며, 위 코드는 카메라와 마이크를 획득함을 나타냅니다. onSuccess는 멀티미디어 장치 획득에 성공했을 때 호출되는 콜백 함수입니다. 멀티미디어 장치를 획득한 경우 실패 시 호출됩니다.

아래는 예시입니다.

var constraints = {video: true};

function onSuccess(stream) {
  var video = document.querySelector("video");
  video.src = window.URL.createObjectURL(stream);
}

function onError(error) {
  console.log("navigator.getUserMedia error: ", error);
}

navigator.getUserMedia(constraints, onSuccess, onError);

웹 페이지에서 getUserMedia 메서드를 사용하는 경우 브라우저는 브라우저가 마이크나 카메라를 호출하도록 허용할지 여부를 사용자에게 묻습니다. 사용자가 동의하면 onSuccess 콜백 함수가 호출되고, 사용자가 거부하면 onError 콜백 함수가 호출됩니다.

onSuccess 콜백 함수의 매개변수는 데이터 스트림 개체 스트림입니다. stream.getAudioTracks 메서드와 stream.getVideoTracks 메서드는 각각 데이터 스트림에 포함된 오디오 트랙과 비디오 트랙을 멤버로 하는 배열을 반환합니다. 사용되는 음원과 카메라의 수에 따라 오디오 및 비디오 트랙의 수가 결정됩니다. 예를 들어 비디오를 캡처하는 데 하나의 카메라만 사용되고 오디오가 없는 경우 비디오 트랙 수는 1이고 오디오 트랙 수는 0입니다. 각 오디오 트랙과 비디오 트랙에는 유형(비디오 또는 오디오)을 나타내는 종류 속성과 FaceTime HD 카메라(내장)와 같은 레이블 속성이 있습니다.

onError 콜백 함수는 Error 객체를 매개변수로 받습니다. Error 객체의 code 속성은 오류 유형을 나타내는 다음 값을 가집니다.

  • PERMISSION_DENIED : 사용자가 정보 제공을 거부했습니다.
  • NOT_SUPPORTED_ERROR : 브라우저가 하드웨어 장치를 지원하지 않습니다.
  • MANDATORY_UNSATISFIED_ERROR : 지정된 하드웨어 장치를 찾을 수 없습니다.

예: 카메라 가져오기

다음으로 getUserMedia 메소드를 통해 카메라로 캡쳐한 이미지를 웹페이지에 출력합니다.

먼저 웹 페이지에 비디오 요소를 배치해야 합니다. 이미지는 이 요소 내에 표시됩니다.

<video id="webcam"></video>

그런 다음 코드를 사용하여 이 요소를 가져옵니다.

function onSuccess(stream) {
    var video = document.getElementById('webcam');
}

그런 다음 이 요소의 src 속성을 데이터 스트림에 바인딩하면 카메라에서 캡처한 이미지를 표시할 수 있습니다.

function onSuccess(stream) {
    var video = document.getElementById('webcam');
    if (window.URL) {
	    video.src = window.URL.createObjectURL(stream);
	} else {
		video.src = stream;
	}

	video.autoplay = true; 
	// 或者 video.play();
}

if (navigator.getUserMedia) {
	navigator.getUserMedia({video:true}, onSuccess);
} else {
	document.getElementById('webcam').src = 'somevideo.mp4';
}

Chrome 및 Opera에서 URL.createObjectURL 메서드는 미디어 데이터 스트림(MediaStream)을 동영상 요소의 src 속성 값으로 사용할 수 있는 바이너리 객체 URL(Blob URL)로 변환합니다. Firefox에서는 미디어 데이터 스트림을 src 속성 값으로 직접 사용할 수 있습니다. 크롬과 오페라는 또한 getUserMedia로 얻은 오디오 데이터를 오디오 또는 비디오 요소의 값으로 직접 사용할 수 있도록 합니다.

카메라를 얻는 주요 용도 중 하나는 사용자가 카메라로 자신의 사진을 찍을 수 있도록 하는 것입니다. Canvas API에는 비디오 프레임을 캔버스 요소로 변환할 수 있는 ctx.drawImage(video, 0, 0) 메서드가 있습니다. 이렇게 하면 스크린샷을 매우 쉽게 찍을 수 있습니다.

<video autoplay></video>
<img src="">
<canvas style="display:none;"></canvas>

<script>
  var video = document.querySelector('video');
  var canvas = document.querySelector('canvas');
  var ctx = canvas.getContext('2d');
  var localMediaStream = null;

  function snapshot() {
    if (localMediaStream) {
      ctx.drawImage(video, 0, 0);
      // “image/webp”对Chrome有效,
      // 其他浏览器自动降为image/png
      document.querySelector('img').src = canvas.toDataURL('image/webp');
    }
  }

  video.addEventListener('click', snapshot, false);

  navigator.getUserMedia({video: true}, function(stream) {
    video.src = window.URL.createObjectURL(stream);
    localMediaStream = stream;
  }, errorCallback);
</script>

예: 마이크 사운드 캡처

브라우저를 통해 사운드를 캡처하려면 Web Audio API가 필요합니다.

window.AudioContext = window.AudioContext ||
                      window.webkitAudioContext;

var context = new AudioContext();

function onSuccess(stream) {
	var audioInput = context.createMediaStreamSource(stream);
	audioInput.connect(context.destination);
}

navigator.getUserMedia({audio:true}, onSuccess);

캡처 자격

getUserMedia 메서드의 첫 번째 매개 변수는 캡처 개체를 지정하는 것 외에도 고화질(또는 VGA 표준) 비디오 녹화를 제한하는 것과 같은 몇 가지 제한 사항을 지정할 수 있습니다.

var hdConstraints = {
  video: {
    mandatory: {
      minWidth: 1280,
      minHeight: 720
    }
  }
};

navigator.getUserMedia(hdConstraints, onSuccess, onError);

var vgaConstraints = {
  video: {
    mandatory: {
      maxWidth: 640,
      maxHeight: 360
    }
  }
};

navigator.getUserMedia(vgaConstraints, onSuccess, onError);

MediaStreamTrack.getSources()

머신에 여러 카메라/마이크가 있는 경우 MediaStreamTrack.getSources 메서드를 사용하여 사용할 카메라/마이크를 지정해야 합니다.

MediaStreamTrack.getSources(function(sourceInfos) {
  var audioSource = null;
  var videoSource = null;

  for (var i = 0; i != sourceInfos.length; ++i) {
    var sourceInfo = sourceInfos[i];
    if (sourceInfo.kind === 'audio') {
      console.log(sourceInfo.id, sourceInfo.label || 'microphone');

      audioSource = sourceInfo.id;
    } else if (sourceInfo.kind === 'video') {
      console.log(sourceInfo.id, sourceInfo.label || 'camera');

      videoSource = sourceInfo.id;
    } else {
      console.log('Some other kind of source: ', sourceInfo);
    }
  }

  sourceSelected(audioSource, videoSource);
});

function sourceSelected(audioSource, videoSource) {
  var constraints = {
    audio: {
      optional: [{sourceId: audioSource}]
    },
    video: {
      optional: [{sourceId: videoSource}]
    }
  };

  navigator.getUserMedia(constraints, onSuccess, onError);
}

위의 코드는 MediaStreamTrack.getSources 메서드의 콜백 함수가 로컬 카메라 및 마이크 목록을 가져온 다음 사용할 마지막 카메라 및 마이크를 지정할 수 있음을 나타냅니다.

RTCPeerConnectionl,RTCDataChannel

RTCPeerConnectionl

RTCPeerConnection의 역할은 브라우저 간에 데이터 "피어 투 피어" 통신을 설정하는 것입니다. 즉, 브라우저에서 얻은 마이크 또는 카메라 데이터를 다른 브라우저로 전송하는 것입니다. 여기에는 신호 처리, 멀티미디어 인코딩/디코딩, 점대점 통신, 데이터 보안, 대역폭 관리 등과 같은 많은 복잡한 작업이 포함됩니다.

서로 다른 클라이언트 간의 오디오/비디오 전송은 서버를 거칠 필요가 없습니다. 그러나 두 클라이언트 간의 연결은 서버를 거쳐야 합니다. 서버는 주로 두 종류의 데이터를 전송합니다.

  • 통신 내용의 메타데이터: 세션을 열고 닫는 명령, 미디어 파일의 메타데이터(인코딩 형식, 미디어 유형 및 대역폭) 등
  • 네트워크 통신 메타데이터: IP 주소, NAT 네트워크 주소 변환 및 방화벽 등

WebRTC 프로토콜은 서버와의 통신 방식을 지정하지 않기 때문에 WebSocket 등 다양한 방식을 사용할 수 있습니다. 서버를 통해 두 클라이언트는 SDP 프로토콜(Session Description Protocol)에 따라 양 당사자의 메타 데이터를 교환합니다.

아래는 예시입니다.

var signalingChannel = createSignalingChannel();
var pc;
var configuration = ...;

// run start(true) to initiate a call
function start(isCaller) {
    pc = new RTCPeerConnection(configuration);

    // send any ice candidates to the other peer
    pc.onicecandidate = function (evt) {
        signalingChannel.send(JSON.stringify({ "candidate": evt.candidate }));
    };

    // once remote stream arrives, show it in the remote video element
    pc.onaddstream = function (evt) {
        remoteView.src = URL.createObjectURL(evt.stream);
    };

    // get the local stream, show it in the local video element and send it
    navigator.getUserMedia({ "audio": true, "video": true }, function (stream) {
        selfView.src = URL.createObjectURL(stream);
        pc.addStream(stream);

        if (isCaller)
            pc.createOffer(gotDescription);
        else
            pc.createAnswer(pc.remoteDescription, gotDescription);

        function gotDescription(desc) {
            pc.setLocalDescription(desc);
            signalingChannel.send(JSON.stringify({ "sdp": desc }));
        }
    });
}

signalingChannel.onmessage = function (evt) {
    if (!pc)
        start(false);

    var signal = JSON.parse(evt.data);
    if (signal.sdp)
        pc.setRemoteDescription(new RTCSessionDescription(signal.sdp));
    else
        pc.addIceCandidate(new RTCIceCandidate(signal.candidate));
};

RTCPeerConnection에는 브라우저 접두사, Chrome 브라우저의 webkitRTCPeerConnection 및 Firefox 브라우저가 있습니다.

mozRTCPeerConnection. Google은 브라우저 간의 차이점을 추상화하기 위해 함수 라이브러리 adapter.js를 유지 관리합니다.

RTC데이터 채널

RTCDataChannel의 기능은 피어 간에 임의의 데이터를 전송하는 것입니다. API는 WebSocket과 동일합니다.

아래는 예시입니다.

 

var pc = new webkitRTCPeerConnection(servers,
  {optional: [{RtpDataChannels: true}]});

pc.ondatachannel = function(event) {
  receiveChannel = event.channel;
  receiveChannel.onmessage = function(event){
    document.querySelector("div#receive").innerHTML = event.data;
  };
};

sendChannel = pc.createDataChannel("sendDataChannel", {reliable: false});

document.querySelector("button#send").onclick = function (){
  var data = document.querySelector("textarea#send").value;
  sendChannel.send(data);
};

Chrome 25, Opera 18 및 Firefox 22는 RTCDataChannel을 지원합니다.

외부 함수 라이브러리

이 두 API의 복잡성으로 인해 일반적으로 외부 함수 라이브러리가 작업에 사용됩니다. 현재 화상채팅용 함수 라이브러리로는 SimpleWebRTC , easyRTC , webRTC.io 가 있으며 P2P 통신용 함수 라이브러리로는 PeerJS , Sharefest 가 있습니다 .

다음은 SimpleWebRTC의 예입니다.
 

var webrtc = new WebRTC({
  localVideoEl: 'localVideo',
  remoteVideosEl: 'remoteVideos',
  autoRequestMedia: true
});

webrtc.on('readyToCall', function () {
    webrtc.joinRoom('My room name');
});

다음은 PeerJS의 예입니다.

var peer = new Peer('someid', {key: 'apikey'});
peer.on('connection', function(conn) {
  conn.on('data', function(data){
    // Will print 'hi!'
    console.log(data);
  });
});

// Connecting peer
var peer = new Peer('anotherid', {key: 'apikey'});
var conn = peer.connect('someid');
conn.on('open', function(){
  conn.send('hi!');
});

원본  WebRTC는 브라우저에서 오디오 및 비디오 통신을 구현합니다 - Nuggets

★기사 말미에 있는 명함은 (FFmpeg, webRTC, rtmp, hls, rtsp, ffplay, srs) 및 오디오 및 비디오 학습 로드맵 등을 포함한 오디오 및 비디오 개발 학습 자료를 무료로 받을 수 있습니다.

아래 참조!

 

추천

출처blog.csdn.net/yinshipin007/article/details/132212115