Сегодня, специально к старту нового потока по веб-разработке, поделимся с вами туториалом, из которого вы узнаете, как создать видеочат с помощью JavaScript и NodeJS. Также вы научитесь использовать PeerJS, WebRTC и Socket.io.
Здесь вы можете увидеть живой пример приложения, которое вы будете создавать.
Подготовка к проекту
Вот что вам понадобится:
-
NodeJS: посетите официальный веб-сайт Node.js, чтобы загрузить и установить Node;
-
NPM: программа NPM устанавливается на ваш компьютер при установке Node.js.
Настройка проекта
Весь код этого проекта можно найти в репозитории GitHub.
-
Создайте пустой каталог с именем video-chat-app.
-
Откройте консоль, перейдите в наш новый каталог и запустите npm init.
-
Заполните необходимую информацию для инициализации нашего проекта.
-
Запустите npm install express ejs socket.io uuid peer. Команда установит все зависимости, необходимые для создания этого приложения.
-
А также в качестве dev-зависимости установите Nodemon. Нужно выполнить npm install-dev nodemon. Это установит nodemon как dev-зависимость.
-
Создайте файл server.js в этом файле будет храниться вся ваша серверная логика.
Теперь, когда у вас настроен наш проект, вы можете приступить к созданию приложения!
Создание сервера (с Express JS)
Первое, что вам нужно сделать, это запустить ваш сервер. Мы собираемся использовать для этого Express. Express это минималистичный веб-фреймворк для Node.js. Express позволяет очень легко создавать и запускать веб-сервер с помощью Node.
Давайте создадим шаблонный файл начального приложения Express.
// server.jsconst express = require(express);const app = express();const server = require(http).Server(app);app.get(/, (req, res) => { res.status(200).send(Hello World);});server.listen(3030);
Теперь ваш сервер запущен, вы можете протестировать его, запустив:
> nodemon server.js
Теперь откройте свой браузер и перейдите по адресу: localhost:3000, вы должны увидеть Hello World.
Создание первой страницы
Вместо того чтобы выводить текст, когда кто-то посещает ваш корневой маршрут, вы хотели бы присылать HTML. Для этого нужно использовать EJS (встроенный JavaScript). EJS это язык шаблонов.
Чтобы использовать EJS в Express, вам нужно настроить ваш шаблонизатор. Для настройки добавьте эту строку кода в файл server.js.
app.set(view engine, ejs)
Доступ к EJS по умолчанию осуществляется в каталоге views. Теперь создайте новую папку views в каталоге. В этой папке добавьте файл с именем room.ejs. Пока что думайте о нашем файле room.ejs как о HTML-файле.
Вот как выглядит ваша файловая структура:
|-- video-chat-app |-- views |-- room.ejs |-- package.json |-- server.js
Теперь добавьте HTML-код в файл room.ejs.
Как только вы скопируете приведённый выше код, нужно немного поменять app.js:
app.get(/, function (req, res) { // OLD CODE res.status(200).send("Hello World");})
Выше приведён старый код, в котором вы отправляете клиенту текст Hello World!. Вместо этого вы хотите отправить файл room.ejs:
app.get(/, function (req, res) { // NEW CODE res.render(room);})
Теперь откройте браузер и перейдите по адресу: localhost:3030, и вы увидите, что отображается файл room.ejs!
Добавление CSS
Выглядит не очень хорошо, правда? Это потому, что в вашем проекте нет стилей. Итак, добавьте немного CSS.
Нам нужно будет добавить новую папку в проект под названием public. В этой папке создайте файлы style.css и script.js. Вот ваша новая файловая структура:
|-- weather-app |-- views |-- index.ejs |-- public |-- style.css |-- script.js |-- package.json |-- server.js
Express не даёт доступа к этому файлу по умолчанию, поэтому вам нужно открыть его с помощью следующей строки кода:
app.use(express.static(public));
Этот код позволяет вам получить доступ ко всем статическим файлам в папке public. Наконец, вам нужен CSS. Поскольку это не курс по CSS, я не буду вдаваться в подробности, но если вы хотите использовать мои стили, вы можете скопировать их отсюда.
После того как вы добавили CSS, вы можете посетить: localhost:3030. Вы заметите, что приложение выглядит немного лучше.
Настройка комнат
К настоящему моменту ваш файл server.js должен выглядеть так:
У вас есть один GET-роут и запуск сервера. Однако, чтобы ваше приложение работало, нужно всякий раз, когда новый пользователь посещает ваш роут по умолчанию, перенаправлять его на уникальный URL-адрес. Следует использовать библиотеку uuid для создания случайного уникального URL-адреса для каждой комнаты.
UUID это библиотека javascript, которая позволяет вам создавать уникальные идентификаторы. В вашем приложении вы будете использовать uuid версии 4 для создания уникального URL. Но сначала импортируйте uuid в server.js.
const { v4: uuidv4 } = require("uuid");
Теперь нужно использовать uuid для создания случайного уникального идентификатора для каждой комнаты и перенаправлять пользователя в эту комнату.
app.get(/, (req, res) => { res.redirect(`/${uuidv4()}`);});
И, прежде чем вы протестируете это, я также хотел добавить страницу для каждой уникальной комнаты, и вы передадите текущий URL этой странице.
app.get(/:room, (req, res) => { res.render(room, { roomId: req.param.room });});
Вы передали roomId в room.ejs на этом закончили настройку ваших комнат. А теперь, если вы посетите localhost:3030, вы будете перенаправлены на уникальный URL.
Добавление видео пользователя
Вы будете работать с файлом script.js, который вы создали ранее. script.js будет содержать весь клиентский код приложения.
Итак, вот что необходимо сделать: нужно получить видеопоток, а затем добавить этот поток в элемент видео.
let myVideoStream;const videoGrid = document.getElementById("video-grid");const myVideo = document.createElement("video");myVideo.muted = true;navigator.mediaDevices.getUserMedia({ audio: true, video: true,}).then((stream) => { myVideoStream = stream; addVideoStream(myVideo, stream);});
Теперь создайтем функцию addVideoStream, которая добавит поток к видеоэлементу.
const addVideoStream = (video, stream) => { video.srcObject = stream; video.addEventListener("loadedmetadata", () => { video.play(); videoGrid.append(video); });};
Этот код добавит пользовательский поток к видеоэлементу. Вы можете проверить это, посетив localhost:3030, и вы увидите всплывающее окно с видео
Добавление возможности разрешить другим пользователям транслировать свои видео в потоковом режиме.
Пришло время использовать Socket.io и PeerJS. Для тех, кто не знает, Socket.io позволяет взаимодействовать серверу и клиенту в режиме реального времени. PeerJS позволяют реализовать WebRTC.
Сначала импортируйте socket.io и peerjs в server.js и прослушайте событие соединения.
// server.jsconst express = require(express);const app = express();const server = require(http).Server(app);const { v4: uuidv4 } = require(uuid);app.set(view engine, ejs);const io = require(socket.io)(server);const { ExpressPeerServer } = require(peer);const peerServer = ExpressPeerServer(server, { debug: true,});app.use(/peerjs, peerServer);app.use(express.static(public));app.get(/, (req, res) => { res.redirect(`/${uuidv4()}`);});app.get(/:room, (req, res) => { res.render(room, { roomId: req.param.room });});io.on(connection, (socket) => { socket.on(join-room, (roomId, userId) => { socket.join(roomId); socket.to(roomId).broadcast.emit(user-connected, userId); });});server.listen(3030);
Теперь ваш сервер прослушивает событие присоединения к комнате. Далее настройте ваш script.js.
// public/script.jsconst socket = io(/);const videoGrid = document.getElementById(video-grid);const myVideo = document.createElement(video);myVideo.muted = true;var peer = new Peer(undefined, { path: /peerjs, host: /, port: 3030,});let myVideoStream;navigator.mediaDevices .getUserMedia({ audio: true, video: true,}).then((stream) => { myVideoStream = stream; addVideoStream(myVideo, stream); peer.on(call, (call) => { call.answer(stream); const video = document.createElement(video); call.on(stream, (userVideoStream) => { addVideoStream(video, userVideoStream); }); }); socket.on(user-connected, (userId) => { connectToNewUser(userId, stream); });});const connectToNewUser = (userId, stream) => { const call = peer.call(userId, stream); const video = document.createElement(video); call.on(stream, (userVideoStream) => { addVideoStream(video, userVideoStream); });};peer.on(open, (id) => { socket.emit(join-room, ROOM_ID, id);});const addVideoStream = (video, stream) => { video.srcObject = stream; video.addEventListener(loadedmetadata, () => { video.play(); videoGrid.append(video); });};
Теперь, если в комнату войдёт новый пользователь, вы увидите его видео.
Создание пользовательского интерфейса
С видеочастью закончили. А теперь займитесь стилизацией. Но сначала добавьте контент в файл room.ejs. (Добавьте CDN font-awesome внутри тега head.)
// views/room.ejs<body> <div class="header"> <div class="logo"> <h3>Video Chat</h2> </div> </div> <div class="main"> <div class="main__left"> <div class="videos__group"> <div id="video-grid"></div> </div> <div class="options"> <div class="options__left"> <div class="options__button"> <i class="fa fa-video-camera" aria-hidden="true"></i> </div> <div class="options__button"> <i class="fa fa-microphone" aria-hidden="true"></i> </div> </div> <div class="options__right"> <div class="options__button background__red"> <i class="fa fa-phone" aria-hidden="true"></i> </div> </div> </div> </div> <div class="main__right"> <div class="main__chat_window"> <ul class="messages"></ul> </div> <div class="main__message_container"> <input id="chat_message" type="text" placeholder="Type message here..."> <div class="options__button"> <i class="fa fa-plus" aria-hidden="true"></i> </div> </div> </div> </div></body>
Затем откройте файл style.css и добавьте немного CSS.
@import url(http://personeltest.ru/aways/fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap");:root { main-darklg: #1d2635; main-dark: #161d29; primary-color: #2f80ec; main-light: #eeeeee; font-family: Poppins, sans-serif;}* { margin: 0; padding: 0;}.header { display: flex; justify-content: center; align-items: center; height: 8vh; width: 100%; background-color: var( main-darklg);}.logo > h3 { color: var( main-light);}.main { overflow: hidden; height: 92vh; display: flex;}.main__left { flex: 0.7; display: flex; flex-direction: column;}.videos__group { flex-grow: 1; display: flex; justify-content: center; align-items: center; padding: 1rem; background-color: var( main-dark);}video { height: 300px; border-radius: 1rem; margin: 0.5rem; width: 400px; object-fit: cover; transform: rotateY(180deg); -webkit-transform: rotateY(180deg); -moz-transform: rotateY(180deg);}.options { padding: 1rem; display: flex; background-color: var( main-darklg);}.options__left { display: flex;}.options__right { margin-left: auto;}.options__button { display: flex; justify-content: center; align-items: center; background-color: var( primary-color); height: 50px; border-radius: 5px; color: var( main-light); font-size: 1.2rem; width: 50px; margin: 0 0.5rem;}.background__red { background-color: #f6484a;}.main__right {flex: 0.3; background-color: #242f41;}.main__chat_window { flex-grow: 1;}.main__message_container { padding: 1rem; display: flex; align-items: center; justify-content: center;}.main__message_container > input { height: 50px; flex: 1; border-radius: 5px; padding-left: 20px; border: none;}#video-grid { display: flex; justify-content: center; flex-wrap: wrap;}
Вот и всё! Поздравляем, вы успешно создали видеочат! Теперь вы можете развернуть его на Heroku и показать его всему миру. Демо и исходный код.
Это лишь небольшой пример того, какие вещи может делать веб-разработчик, причем в одиночку. Сделать just for fun экспорт музыки в Spotify и получить известность, пока огромная компания долго думает над решением задачи без проблем. За один вечер набросать и выкатить расширение для браузера, которое упростит жизнь миллионам пользователей тоже по силам. На что еще способна веб-разработка зависит только от фантазии программиста. Приходите учиться, чтобы освоить дзюцу веб-разработки и стать настоящим самураем интернета.
Узнайте, как прокачаться в других специальностях или освоить их с нуля:
ПРОФЕССИИ
КУРС