Hướng dẫn webrtc live streaming nodejs - webrtc phát trực tiếp nodejs

WebRTC là công nghệ giúp chúng ta xây dựng ứng dụng stream audio, video, chia sẻ file, desktop, ... thông qua kết nối peer to peer [kết nối trực tiếp giữa các client mà không cần truyền dữ liệu qua server trung gian]. Loạt bài này sẽ giúp các bạn có thể tích hợp công nghệ WebRTC vào ứng dụng web của bạn.

Bạn chuẩn bị trước các tài khoản các trang sau:  //heroku.com/ //peerjs.com/ //xirsys.com/ //github.com/
//heroku.com/
//peerjs.com/
//xirsys.com/
//github.com/

Project khởi đầu:  //github.com/vanpho93/rtc-start-kit
//github.com/vanpho93/rtc-start-kit

Project kết thúc: //github.com/vanpho93/khoapham-rtc Các bạn có thể theo dõi project cuối mỗi video trong mục commit
//github.com/vanpho93/khoapham-rtc
Các bạn có thể theo dõi project cuối mỗi video trong mục commit


Xem thêm khoá học Lập trình Nodejs tại Khoa Phạm: //khoapham.vn/khoa-hoc-lap-trinh-nodejs.html

Overview

Chúng ta sẽ phát triển ứng dụng demo WebRTC bằng NodeJS.

Nội dung chính

  • Lấy được video từ webcam
  • Stream video với RTCPeerConnection
  • Stream data với RTCDataChannel
  • Cài đặt một signaling service để trao đổi messages
  • Kết hợp peer connection và signaling
  • Chụp ảnh và chia sẻ nó qua một kênh dữ liệu [data channel]

Các service cần cài đặt trước

  • Chrome 47 trở lên
  • NodeJS, npm
  • Hiểu biết cơ bản về HTML, CSS và JavaScript
  • Text editor

Stream video từ webcam

Thêm một thẻ

'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
6 và một thẻ
'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
7 vào file
'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
8 trong thư mục chính như sau:






  Realtime communication with WebRTC

  





  

Realtime communication with WebRTC

Thêm đoạn code sau vào file

'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
9 trong thư mục
navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
0:

'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

Giải thích

Khi

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
1 được gọi, trình duyệt sẽ yêu cầu quyền truy cập camera của người dùng. Nếu thành công, một
navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
2 sẽ được trả về và được sử dụng như một thẻ
navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
3 thông qua thuộc tính
navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
4:

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}

Tham số

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
5 cho phép chỉ định cái mà media sẽ lấy [có thể là video hoặc audio]

var constraints = {
  video: true
};

Có thể sử dụng

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
6 cho các options khác như
navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
7 chẳng hạn:

const hdConstraints = {
  video: {
    width: {
      min: 1280
    },
    height: {
      min: 720
    }
  }
}

MediaTrackConstraints specification liêt kê tất cả

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
8. Nếu resolution yêu cầu không được hỗ trợ bởi camera hiện tại
navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
9 sẽ từ chối với một lỗi
var constraints = {
  video: true
};
0 và người dùng sẽ không có quyền truy cập camera.

Nếu

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];

function handleSuccess[stream] {
  video.srcObject = stream;
}
9 thành công,
var constraints = {
  video: true
};
2 từ webcam sẽ được cài đặt làm
var constraints = {
  video: true
};
3 của thẻ
'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
6.

function handleSuccess[stream] {
  video.srcObject = stream;
}

Như vậy chúng ta đã biết được cách:

  • Lấy video từ webcam
  • Cài đặt media constraints.
  • Hiển thị video với thẻ
    'use strict';
    
    var constraints = {
      video: true
    };
    
    var video = document.querySelector['video'];
    
    function handleSuccess[stream] {
      video.srcObject = stream;
    }
    
    function handleError[error] {
      console.error['getUserMedia error: ', error];
    }
    
    navigator.mediaDevices.getUserMedia[constraints].
      then[handleSuccess].catch[handleError];
    
    6. Một vài chú ý: Đừng quên thêm thuộc tính
    var constraints = {
      video: true
    };
    
    6 cho thẻ
    'use strict';
    
    var constraints = {
      video: true
    };
    
    var video = document.querySelector['video'];
    
    function handleSuccess[stream] {
      video.srcObject = stream;
    }
    
    function handleError[error] {
      console.error['getUserMedia error: ', error];
    }
    
    navigator.mediaDevices.getUserMedia[constraints].
      then[handleSuccess].catch[handleError];
    
    6. Thông tin thêm về
    var constraints = {
      video: true
    };
    
    8 xem thêm ở đây Có thể thêm CSS cho thẻ video để hiện video ko bị tràn màn hình:
video {
  max-width: 100%;
  width: 320px;
}

Stream video với RTCPeerConnection

Stream data với RTCDataChannel

Cài đặt một signaling service để trao đổi messages

Kết hợp peer connection và signaling




Start Call Hang Up

Chụp ảnh và chia sẻ nó qua một kênh dữ liệu [data channel]

Các service cần cài đặt trước

Chrome 47 trở lên


Thêm thông tin về adapter.js

File

'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
8 trông như sau:






  Realtime communication with WebRTC

  





  

Realtime communication with WebRTC

Start Call Hang Up

File

'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
9 như sau:

'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
0

Tạo một cuộc gọi

Mở file

'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
8, click button
function handleSuccess[stream] {
  video.srcObject = stream;
}
2 để get video từ webcam và click
function handleSuccess[stream] {
  video.srcObject = stream;
}
3 to tạo một
function handleSuccess[stream] {
  video.srcObject = stream;
}
4. Chúng ta sẽ thấy 2 video giống nhau. WebRTC sử dụng RTCPeerConnection API to cài đặt một connection to stream video giữa các WebRTC clients được biết như
function handleSuccess[stream] {
  video.srcObject = stream;
}
5. Trong ví dụ này, 2 RTCPeerConnection object ở cùng 1 trang: pc1 và pc2

Cài đặt một cuộc gọi giữa 2 WebRTC peers bao gồm 3 bước sau:

  • Tạo một RTCPeerConnection cho mỗi client và thêm
    const hdConstraints = {
      video: {
        width: {
          min: 1280
        },
        height: {
          min: 720
        }
      }
    }
    
    4 từ getUserMedia[]`.
  • Lấy và chia sẻ thông tin
    function handleSuccess[stream] {
      video.srcObject = stream;
    }
    
    7 được biết như là
    function handleSuccess[stream] {
      video.srcObject = stream;
    }
    
    8
  • Lấy và chia sẻ local và remote description, metadata về local media in SDP format

Tưởng tượng rằng Alice và Bob muốn sử dụng RTCPeerConnection để cài đặt một cuộc gọi video: Đầu tiên, Alice và Bob trao đổi các thông tin về network.

function handleSuccess[stream] {
  video.srcObject = stream;
}
9 chính là quá trình tìm kiếm
video {
  max-width: 100%;
  width: 320px;
}
0 và
video {
  max-width: 100%;
  width: 320px;
}
1 sử dụng ICE framework.

  1. Alice tạo một
    video {
      max-width: 100%;
      width: 320px;
    }
    
    2 với một
    video {
      max-width: 100%;
      width: 320px;
    }
    
    3:
'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
1
  1. Alice gọi getUserMedia[] và thêm
    video {
      max-width: 100%;
      width: 320px;
    }
    
    4 thông qua:
'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
2
  1. Đối tượng
    video {
      max-width: 100%;
      width: 320px;
    }
    
    3 từ bước 1 được gọi khi
    video {
      max-width: 100%;
      width: 320px;
    }
    
    6 available.
  2. Alice gửi dữ liệu candidate đã được mã hóa cho Bob. Trên thực tế , quá trình này [được biết như là signaling] xảy ra thông quá một tin nhắn dịch vụ [messaging service]. Ở đây 2 RTCPeerConnection object trên cùng một page nên nó có thể kết nối trực tiếp mà không cần một external messaging service.
  3. When Bob nhận được một
    video {
      max-width: 100%;
      width: 320px;
    }
    
    7 từ Alice, anh ấy sẽ gọi
    video {
      max-width: 100%;
      width: 320px;
    }
    
    8 để thêm candidate vào remote peer description:
'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
3

WebRTC peers cũng cần tìm và trao đổi thông tin local và remote audio và video media như resolution, dung lượng codec. Signaling trao đổi thông tin media configuration bởi trao đổi metadata được gọi là một

video {
  max-width: 100%;
  width: 320px;
}
9 và một



Start Call Hang Up
0 sử dụng



Start Call Hang Up
1 format, gọi tắt là SDP

Alice run phương thức




Start Call Hang Up
2 . Promise trả về một



Start Call Hang Up
3 [Alice's local session description]:

'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
4
  1. Nếu thành công, Alice sẽ set một
    
    
    
    
    Start Call Hang Up
    4 sử dụng
    
    
    
    
    Start Call Hang Up
    5 và sau đó gửi
    
    
    
    
    Start Call Hang Up
    6 này tới Bob thông qua
    
    
    
    
    Start Call Hang Up
    7.
  2. Bob sẽ set
    
    
    
    
    Start Call Hang Up
    8 mà Alice đã gửi như một
    
    
    
    
    Start Call Hang Up
    9 sử dụng
    
    
    0.
  3. Bob run phương thức
    
    
    1, truyền tham số là
    
    
    
    
    Start Call Hang Up
    9 mà nhận được từ Alice, Sau đó một
    
    
    3 thích hợp được sinh ra.
    
    
    4 truyền một
    
    
    
    
    Start Call Hang Up
    3 : Bob sets nó như
    
    
    
    
    Start Call Hang Up
    4 và gửi nó cho Alice.
  4. Khi Alice nhận session description của Bob, cô ấy set nó như một
    
    
    
    
    Start Call Hang Up
    9 với phương thức
    
    
    0.
'use strict';

var constraints = {
  video: true
};

var video = document.querySelector['video'];

function handleSuccess[stream] {
  video.srcObject = stream;
}

function handleError[error] {
  console.error['getUserMedia error: ', error];
}

navigator.mediaDevices.getUserMedia[constraints].
  then[handleSuccess].catch[handleError];
5

Như vậy chúng ta đã hiểu rõ các bước kết nối và thiết lập các kết nối peer trong WebRTC. Phần sau mình sẽ giới thiệu cách stream qua


9.

Bài Viết Liên Quan

Chủ Đề