WebRTC (Web Real Time Communication) là tập hợp các tiêu chuẩn và giao thức cho phép các trình duyệt Web thực hiện trực tiếp các tính năng truyền thông đa phương tiện thời gian thực như gọi điện, tin nhắn hình, truyền dữ liệu bằng các API JavaScript.
Ý tưởng về WebRTC được đưa ra bởi nhóm phát triển Google Hangouts từ năm 2009. Tại thời điểm đó, để thực hiện truyền thông đa phương tiện trên nền Web, người sử dụng phải cài đặt Flash và các plugin khác. Năm 2010, Google mua lại hai công ty là On2 và Global IP Solutions (GIPS). Sau đó họ chuyển các công nghệ liên quan đến RTC của hai công ty này thành mã nguồn mở và kết hợp với IETF và W3C để đưa ra WebRTC vào năm 2011.
WebRTC cung cấp 3 API JavaScript :
Để viết một ứng dụng WebRTC ta sử dụng 3 API này để lấy được dữ liệu từ camera, microphone, thiết lập phiên truyền thông và truyền tải dữ liệu audio, video cũng như dữ liệu bất kỳ. Ngoài ra, bước quan trọng là báo hiệu cho phiên truyền thông được thực hiện bên ngoài WebRTC bằng một phương thức do người lập trình lựa chọn.
Sau đây là 1 vài demo:
STEP 1: Create index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>getUserMedia</title>
<link href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://webrtc.github.io/samples/src/css/main.css">
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
</head>
<body>
<div id="container">
<h1>
<a href="#" title="WebRTC samples homepage">WebRTC samples</a>
<span>getUserMedia</span></h1>
<video id="gum-local" autoplay playsinline></video>
<button id="showVideo">Open camera</button>
<div id="errorMsg"></div>
<p class="warning"><strong>Warning:</strong> if you're not using headphones, pressing play will cause feedback.</p>
<p>Display the video stream from <code>getUserMedia()</code> in a video element.</p>
<p>The <code>MediaStream</code> object <code>stream</code> passed to the <code>getUserMedia()</code> callback is in
global scope, so you can inspect it from the console.</p>
</div>
Layout
STEP 2: Add javascript
<script type="text/javascript">
'use strict';
// Put variables in global scope to make them available to the browser console.
const constraints = window.constraints = {
audio: false,
video: true
};
function handleSuccess(stream) {
const video = document.querySelector('video');
const videoTracks = stream.getVideoTracks();
console.log('Got stream with constraints:', constraints);
console.log(`Using video device: ${videoTracks[0].label}`);
window.stream = stream; // make variable available to browser console
video.srcObject = stream;
}
function handleError(error) {
if (error.name === 'ConstraintNotSatisfiedError') {
let v = constraints.video;
errorMsg(`The resolution ${v.width.exact}x${v.height.exact} px is not supported by your device.`);
} else if (error.name === 'PermissionDeniedError') {
errorMsg('Permissions have not been granted to use your camera and ' +
'microphone, you need to allow the page access to your devices in ' +
'order for the demo to work.');
}
errorMsg(`getUserMedia error: ${error.name}`, error);
}
function errorMsg(msg, error) {
const errorElement = document.querySelector('#errorMsg');
errorElement.innerHTML += `<p>${msg}</p>`;
if (typeof error !== 'undefined') {
console.error(error);
}
}
async function init(e) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleSuccess(stream);
e.target.disabled = true;
} catch (e) {
handleError(e);
}
}
document.querySelector('#showVideo').addEventListener('click', e => init(e));
</script>
Giải thích chút:
STEP3: DEMO
Create recording.html
<html>
<head>
<title>MediaStream Recording</title>
<link href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://webrtc.github.io/samples/src/css/main.css">
<link rel="stylesheet" href="https://webrtc.github.io/samples/src/content/getusermedia/record/css/main.css">
</head>
<body>
<div id="container">
<h1><a href="" title="WebRTC samples homepage">WebRTC samples</a>
<span>MediaRecorder</span></h1>
<p>For more information see the MediaStream Recording API <a
href="http://w3c.github.io/mediacapture-record/MediaRecorder.html"
title="W3C MediaStream Recording API Editor's Draft">Editor's Draft</a>.</p>
<video id="gum" playsinline autoplay muted></video>
<video id="recorded" playsinline loop></video>
<div>
<button id="start">Start camera</button>
<button id="record" disabled>Start Recording</button>
<button id="play" disabled>Play</button>
<button id="download" disabled>Download</button>
</div>
<div>
<h4>Media Stream Constraints options</h4>
<p>Echo cancellation: <input type="checkbox" id="echoCancellation"></p>
</div>
<div>
<span id="errorMsg"></span>
</div>
<a href="" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a>
</div>
<!-- include adapter for srcObject shim -->
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
</body>
</html>
**add js **
// This code is adapted from
// https://rawgit.com/Miguelao/demos/master/mediarecorder.html
'use strict';
/* globals MediaRecorder */
const mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
let mediaRecorder;
let recordedBlobs;
let sourceBuffer;
const errorMsgElement = document.querySelector('span#errorMsg');
const recordedVideo = document.querySelector('video#recorded');
const recordButton = document.querySelector('button#record');
recordButton.addEventListener('click', () => {
if (recordButton.textContent === 'Start Recording') {
startRecording();
} else {
stopRecording();
recordButton.textContent = 'Start Recording';
playButton.disabled = false;
downloadButton.disabled = false;
}
});
const playButton = document.querySelector('button#play');
playButton.addEventListener('click', () => {
const superBuffer = new Blob(recordedBlobs, {type: 'video/webm'});
recordedVideo.src = null;
recordedVideo.srcObject = null;
recordedVideo.src = window.URL.createObjectURL(superBuffer);
recordedVideo.controls = true;
recordedVideo.play();
});
const downloadButton = document.querySelector('button#download');
downloadButton.addEventListener('click', () => {
const blob = new Blob(recordedBlobs, {type: 'video/webm'});
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'test.webm';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
});
function handleSourceOpen(event) {
console.log('MediaSource opened');
sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
console.log('Source buffer: ', sourceBuffer);
}
function handleDataAvailable(event) {
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
}
function startRecording() {
recordedBlobs = [];
let options = {mimeType: 'video/webm;codecs=vp9'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: 'video/webm;codecs=vp8'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: 'video/webm'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: ''};
}
}
}
try {
mediaRecorder = new MediaRecorder(window.stream, options);
} catch (e) {
console.error('Exception while creating MediaRecorder:', e);
errorMsgElement.innerHTML = `Exception while creating MediaRecorder: ${JSON.stringify(e)}`;
return;
}
console.log('Created MediaRecorder', mediaRecorder, 'with options', options);
recordButton.textContent = 'Stop Recording';
playButton.disabled = true;
downloadButton.disabled = true;
mediaRecorder.onstop = (event) => {
console.log('Recorder stopped: ', event);
};
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start(10); // collect 10ms of data
console.log('MediaRecorder started', mediaRecorder);
}
function stopRecording() {
mediaRecorder.stop();
console.log('Recorded Blobs: ', recordedBlobs);
}
function handleSuccess(stream) {
recordButton.disabled = false;
console.log('getUserMedia() got stream:', stream);
window.stream = stream;
const gumVideo = document.querySelector('video#gum');
gumVideo.srcObject = stream;
}
async function init(constraints) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleSuccess(stream);
} catch (e) {
console.error('navigator.getUserMedia error:', e);
errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
}
}
document.querySelector('button#start').addEventListener('click', async () => {
const hasEchoCancellation = document.querySelector('#echoCancellation').checked;
const constraints = {
audio: {
echoCancellation: {exact: hasEchoCancellation}
},
video: {
width: 1280, height: 720
}
};
console.log('Using media constraints:', constraints);
await init(constraints);
});
Demo
Trên chỉ là vd cơ bản, còn rất nhiều chức năng hay của WebRTC
Một trong những trang web được biết đến khá nhiều trong giới lập trình viên WebRTC đó là https://appear.in/ ra mắt hồi năm 2012, hay https://meet.google.com/. Dịch vụ này hỗ trợ người dùng tạo một phòng chat video cực kì nhanh chóng chỉ bằng cách dùng Chrome hoặc Firefox, không cần phải cài thêm bất kì một plugin nào.
WebRTC thật tuyệt vời, Nó sẽ giúp việc kết nối giữa người dùng với nhau trở nên dễ dàng hơn bao giờ hết, và tất cả mọi thứ đều chỉ cần trình duyệt mà thôi.
Nguồn tham khảo: https://webrtc.github.io/samples/