[JavaScript, Программирование, Конференции, Видеоконференцсвязь] Видеочат с возможностью совместного редактирования текста при помощи Twilio Sync (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Представьте, что вам нужно создать видеочат, функционал которого должен находиться под вашим контролем, например для закрытой группы людей со своими специфическими требованиями. При этом чат нужен вчера, начинать писать его с нуля уже поздно. В этом материале, переводом которого мы решили поделиться к старту курса о Frontend-разработке, рассказывается, как разработать программируемый видеочат на основе Twilio. В статье вы найдёте две ветки кода на Github, первая содержит простую основу чата, о которой пойдёт речь в материале, а вторая — завершённый пример чата.ПодготовкаЧто вам будет нужно:
- Бесплатная учётная запись Twilio. Если вы зарегистрируетесь здесь, вы получите 10 долларов в качестве кредита Twilio при переходе на платную учётную запись.
- Node.js (версия 14.16.1 или выше) и npm.
- Код из этого репозитория.
Скачайте и запустите код видеоблокнотаЧтобы скачать код, выберите место на вашем компьютере, где вы хотите работать с проектом. Затем откройте окно терминала и выполните следующую команду, чтобы клонировать ветку start:
git clone -b start https://github.com/adjeim/video-note-collab.git
Затем перейдите в корневой каталог проекта и установите необходимые зависимости, выполнив следующие команды:
cd video-note-collab
npm install
Скопируйте файл .env для переменных среды такой командой:
cp .env.template .env
Затем откройте файл .env в редакторе кода и замените значения переменных своими учётными данными:
TWILIO_ACCOUNT_SID
TWILIO_SYNC_SERVICE_SID
TWILIO_API_KEY_SID
TWILIO_API_KEY_SECRET
Найти свои учётные данные вы можете в консоли Twilio, на странице Twilio Sync Service и на странице Twilio API Keys. В качестве значения переменной TWILIO_SYNC_SERVICE_SID можно использовать SID по умолчанию. Теперь, когда вы ввели свои учётные данные, запустите сервер Express:
npm start
Если вы перейдёте по адресу http://localhost:3000/ в своём браузере, то увидите заметку:
Протестируйте приложение, набрав несколько слов в блокноте. При вводе пробела, клавиши ввода или знаков препинания запускается синхронизация. Если вы откроете второе окно браузера по адресу http://localhost:3000/ и одновременно посмотрите на них, вы должны увидеть, что текст, который вы вводите в одном окне, отображается и в другом:
Как это происходит? Это приложение использует Twilio Sync для синхронизации состояния и данных между браузерами и устройствами в режиме реального времени. Здесь у вас есть документ Sync, который называется notepad. Когда страница загружается, создаётся новый токен доступа, который передаётся Sync клиенту. Если документ существует, его содержимое загружается в <textarea>. Приложение отслеживает обновления документа, обновляя положение курсора и содержимое блокнота. Если вы откроете инструменты разработчика своего браузера, вы также сможете увидеть изменения в контенте, который записывается в консоль.Идея здесь аналогична идее других инструментов совместной работы с заметками, таким как Google Docs или Notion. С помощью этого типа приложения вы можете вместе с другим человеком просматриватьодин и тот же документ и вместе редактировать его в режиме реального времени. Запустите приложение — и переходите к следующему шагуОбновите макет приложенияПервое, что вам нужно сделать, — это немного обновить макет вашего приложения. Если вы прямо сейчас откроете public/index.html в редакторе кода, то увидите, что Tailwind CSS и Twilio Sync уже подключены в проект. Обновите элемент <head>, добавив в него библиотеку Twilio Video, как показано в приведённом ниже коде:
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<link href='https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css' rel='stylesheet'>
<script type="text/javascript" src="https://media.twiliocdn.com/sdk/js/sync/v2.0/twilio-sync.min.js"></script>
<script src='https://sdk.twilio.com/js/video/releases/2.15.0/twilio-video.min.js'></script>
<title>Video Collaboration with Notes</title>
</head>
Обновите элемент <body>. Сначала добавьте элемент <form>, в котором пользователь может ввести своё имя и нажать кнопку, чтобы присоединиться к комнате.
<body class='bg-grey-100 p-10 flex flex-wrap container'>
<form id='login' class='w-full max-h-20 flex items-center py-2'>
<input class='appearance-none bg-transparent border-b border-green-500 mr-3 py-1 px-2 focus:outline-none'
id='identity' type='text' placeholder='Enter your name...' required>
<button id='joinOrLeaveRoom' class='bg-green-500 hover:bg-green-700 text-white py-1 px-4 rounded' type='submit'>
Join Video Call
</button>
</form>
<textarea id='notepad' class='h-44 w-full shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea>
Замените элемент <textarea>. В этом проекте вы отключите взаимодействие с документом и установите для него серый цвет фона при первой загрузке приложения.
</form>
<textarea disabled id='notepad' class='bg-gray-200 h-140 w-6/12 shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea>
Затем чуть ниже <textarea> добавьте элемент <div> для вывода видео участников:
<textarea disabled id='notepad' class='bg-gray-200 h-140 w-6/12 shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea>
<div id='container' class='w-5/12 bg-green-100'>
<div id='participantsContainer'>
<div id='localParticipant'>
<div id='localVideoTrack' class='participant'></div>
</div>
<div id='remoteParticipants'>
<!-- Remote participants will be added here as they join the call -->
</div>
</div>
</div>
Теперь, когда у вас в интерфейсе есть место для отображения видео участников, пришло время добавить отображающий это видео код.Обновите генерацию токена доступаЕсли вы откроете index.js в своём редакторе кода, вы увидите, что у вас уже есть код для предоставления токена доступа и что к этим токенам доступа будет добавлен SyncGrant. Чтобы задействовать видео, вам также понадобится VideoGrant.Под вашей константой для SyncGrant также укажите константу для VideoGrant. Пока вы в этой части кода, убедитесь, что ваше приложение может парсить JSON из тела запроса при помощи функции express.json():
const AccessToken = require('twilio').jwt.AccessToken;
const SyncGrant = AccessToken.SyncGrant;
const VideoGrant = AccessToken.VideoGrant;
app.use(express.json());
Обновите свой роутер для получения токена, чтобы он был асинхронным и чтобы получить идентификационные данные пользователя и имя видеокомнаты из запроса POST. Здесь вы также добавите VideoGrant к токену доступа.
app.post('/token', async (req, res) => {
if (!req.body.identity || !req.body.room) {
return res.status(400);
}
// Get the user's identity from the request
const identity = req.body.identity;
// Create a 'grant' identifying the Sync service instance for this app.
const syncGrant = new SyncGrant({
serviceSid: process.env.TWILIO_SYNC_SERVICE_SID
});
// Create a video grant
const videoGrant = new VideoGrant({
room: req.body.room
})
// Create an access token which we will sign and return to the client,
// containing the grant we just created and specifying their identity.
const token = new AccessToken(
process.env.TWILIO_ACCOUNT_SID,
process.env.TWILIO_API_KEY_SID,
process.env.TWILIO_API_KEY_SECRET,
);
token.addGrant(syncGrant);
token.addGrant(videoGrant);
token.identity = identity;
// Serialize the token to a JWT string and include it in a JSON response
res.send({
identity: identity,
token: token.toJwt()
});
});
Теперь ваш токен предоставит пользователям вашего приложения доступ к синхронизации и к видео. Теперь, когда вы обновили серверную часть приложения, пора вернуться на клиентскую сторону и отобразить видео в окне браузера.Подключение и вывод видео участниковВернитесь в public/index.html в редакторе кода. Посмотрите на код в последнем теге <script> в конце файла. Вы увидите, что когда приложение загружается в браузере, этот код получает токен доступа из вашего запроса на токен, затем подключает клиент синхронизации и обновляет блокнот. Чтобы добавить видео в этот проект, нужно изменить этот код таким образом, чтобы приложение получило токен после того, как пользователь введёт своё имя и нажмёт кнопку «Join Video Call» в пользовательском интерфейсе. Затем этот токен будет использоваться для подключения пользователя к синхронизированному блокноту и видеозвонку. Чуть ниже вашей переменной notepad добавьте ещё несколько переменных, чтобы упростить обращение к другим элементам в вашем пользовательском интерфейсе:
<script>
const notepad = document.getElementById('notepad');
const localVideoTrack = document.getElementById('localVideoTrack');
const login = document.getElementById('login');
const identityInput = document.getElementById('identity');
const joinLeaveButton = document.getElementById('joinOrLeaveRoom');
const localParticipant = document.getElementById('localParticipant');
const remoteParticipants = document.getElementById('remoteParticipants');
let connected = false;
let room;
let syncDocument;
let twilioSyncClient;
Теперь вы сможете обращаться к различным частям видеочата, а также отслеживать, подключён ли локальный пользователь к видеозвонку. Вы также сможете отслеживать, открыт ли синхронизированный документ, с которым пользователь может взаимодействовать. Чтобы сделать предварительный просмотр видеозвонка, добавьте функцию addLocalVideo чуть ниже списка переменных, которые вы обновили выше:
const addLocalVideo = async () => {
const videoTrack = await Twilio.Video.createLocalVideoTrack();
const trackElement = videoTrack.attach();
localVideoTrack.appendChild(trackElement);
};
Вызовите эту функцию в конце файла, непосредственно перед закрывающим тегом <script>:
addLocalVideo();
</script>
Затем создайте новую функцию с именем connectOrDisconnect, которая будет обрабатывать событие, когда пользователь нажимает кнопку «Join Video Call». Если пользователь ещё не подключён к звонку, эта функция подключит их. Если пользователь уже подключён, эта функция отключит его. Добавьте следующий код чуть ниже функции addLocalVideo:
const connectOrDisconnect = async (event) => {
event.preventDefault();
if (!connected) {
const identity = identityInput.value;
joinLeaveButton.disabled = true;
joinLeaveButton.innerHTML = 'Connecting...';
try {
await connect(identity);
} catch (error) {
console.log(error);
alert('Failed to connect to video room.');
joinLeaveButton.innerHTML = 'Join Video Call';
joinLeaveButton.disabled = false;
}
}
else {
disconnect();
}
};
Непосредственно перед закрывающим тегом <script> добавьте ещё один слушатель событий, на этот раз в форму входа. Этот слушатель будет вызывать connectOrDisconnect всякий раз, когда пользователь отправляет форму:
// Add listener
notepad.addEventListener('keyup', (event) => {
// Define array of triggers to sync (space, enter, and punctuation)
// Otherwise sync will fire every time
const syncKeys = [32, 13, 8, 188, 190];
if (syncKeys.includes(event.keyCode)) {
syncNotepad(twilioSyncClient);
}
})
login.addEventListener('submit', connectOrDisconnect);
Затем замените блок fetch('/token') следующей функцией подключения, которая примет идентификатор, переданный в форму, получит токен для этого пользователя с сервера, загрузит и включит документ и подключит этого локального пользователя в видеочат:
const connect = async (identity) => {
const response = await fetch('/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({'identity': identity, room: 'My Video Room'})
});
const data = await response.json();
const token = data.token;
// Set up sync document
twilioSyncClient = new Twilio.Sync.Client(token);
notepad.disabled = false;
notepad.classList.remove('bg-gray-200');
syncDocument = await twilioSyncClient.document('notepad');
// Load the existing Document
notepad.value = syncDocument.data.content || '';
// Listen to updates on the Document
syncDocument.on('updated', (event) => {
// Update the cursor position
let cursorStartPos = notepad.selectionStart;
let cursorEndPos = notepad.selectionEnd;
notepad.value = event.data.content;
// Reset the cursor position
notepad.selectionEnd = cursorEndPos;
console.log('Received Document update event. New value:', event.data.content);
})
// Set up the video room
room = await Twilio.Video.connect(token);
const identityDiv = document.createElement('div');
identityDiv.setAttribute('class', 'identity');
identityDiv.innerHTML = identity;
localParticipant.appendChild(identityDiv);
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
connected = true;
joinLeaveButton.innerHTML = 'Leave Video Call';
joinLeaveButton.disabled = false;
identityInput.style.display = 'none';
};
Как только локальный участник подключится к звонку, эта видеокомната будет назначена глобальной переменной для room. Видео локального пользователя будет отображаться в пользовательском интерфейсе, и слушатели событий будут отслеживать, когда другие участники присоединяются к видеовстрече или выйдут из неё. Кнопка «Join Video Call» также изменится на «Leave Video Call», а поле ввода для имени будет скрыто. Теперь, когда вы добавили функцию подключения, добавьте функцию отключения чуть ниже:
const disconnect = () => {
room.disconnect();
let removeParticipants = remoteParticipants.getElementsByClassName('participant');
while (removeParticipants[0]) {
remoteParticipants.removeChild(removeParticipants[0]);
}
joinLeaveButton.innerHTML = 'Join Video Call';
connected = false;
identityInput.style.display = 'inline-block';
localParticipant.removeChild(localParticipant.lastElementChild);
syncDocument.close();
twilioSyncClient = null;
notepad.value = '';
notepad.disabled = true;
notepad.classList.add('bg-gray-200');
};
Функция disconnect будет обрабатывать отключение участника от видеозвонка, когда он нажимает кнопку «Leave Video Call». Она также будет проходить через других участников видеозвонка и удалять видео из пользовательского интерфейса для отключённого участника. Состояние подключения снова устанавливается на false, поле ввода имени пользователя появляется снова, а кнопка «Leave Video Call» меняется на «Join Video Call». Кроме того, блокнот будет очищен и отключён для локального участника, как только кто-то отключится от видеозвонка, он также будет отключён от общего блокнота.Затем вы захотите поработать с тем, что происходит, когда удалённые участники подключаются к звонку или отключаются от него. Начните с добавления функции ParticipantConnected, которая создаст новый <div> для подключённого участника, показывая имя пользователя участника в качестве его идентификатора и прикрепляя их видео и аудиодорожки к <div>, если локальный участник подписан на них.Эта функция также создаёт обработчики событий для управления действиями по подписке, относящимися к аудио- и видеодорожкам участников. Если удалённый участник отключает свой аудио- или видеопоток, хочется иметь возможность реагировать на это событие и при необходимости подключать или отключать эти дорожки. Добавьте функцию participantConnected чуть ниже вашей функции отключения в public/index.html:
const participantConnected = (participant) => {
const participantDiv = document.createElement('div');
participantDiv.setAttribute('id', participant.sid);
participantDiv.setAttribute('class', 'participant');
const tracksDiv = document.createElement('div');
participantDiv.appendChild(tracksDiv);
const identityDiv = document.createElement('div');
identityDiv.setAttribute('class', 'identity');
identityDiv.innerHTML = participant.identity;
participantDiv.appendChild(identityDiv);
remoteParticipants.appendChild(participantDiv);
participant.tracks.forEach(publication => {
if (publication.isSubscribed) {
trackSubscribed(tracksDiv, publication.track);
}
});
participant.on('trackSubscribed', track => trackSubscribed(tracksDiv, track));
participant.on('trackUnsubscribed', trackUnsubscribed);
};
Пришло время добавить функцию ParticipantDisconnected для ситуации, когда удалённый участник покидает видеозвонок. Это функция, которая находит участника по его sid (уникальному идентификатору) и удаляет его div из DOM. Добавьте функцию participantDisconnected сразу под вашей функцией ParticipantConnected:
const participantDisconnected = (participant) => {
document.getElementById(participant.sid).remove();
};
А теперь добавим код для ситуации, когда локальный участник подписывается на аудио- или видеодорожки удалённого участника или отписывается от них. Добавьте следующие функции trackSubscribed и trackUnsubscribed в public/index.html чуть ниже вашего кода для participantDisconnected:
const trackSubscribed = (div, track) => {
const trackElement = track.attach();
div.appendChild(trackElement);
};
const trackUnsubscribed = (track) => {
track.detach().forEach(element => {
element.remove()
});
};
У вас есть весь код проекта. Теперь протестируем блокнот с видео.Тестирование вашего приложенияПерейдите по адресу http://localhost:3000/. Вы должны увидеть сайт, похожий на показанный ниже, с блокнотом слева и видеопотоком локального участника справа:
Введите своё имя в поле ввода и нажмите «Join Video Call». Вы увидите своё имя под видео. Если хотите, можете попробовать набрать текст в блокноте. Откройте другую вкладку браузера по адресу http://localhost:3000/ и присоединитесь к видеозвонку под другим именем. Как только вы это сделаете, вы увидите два изображения, а это означает, что вы можете общаться друг с другом и делиться блокнотом:
Если вы введёте текст в блокнот на одной вкладке, а затем переключитесь на другую, вы увидите, что текст между ними синхронизирован.Что будет дальше с инструментом для совместной работы с заметками?У этого блокнота очень много возможностей: от совместной работы над письменным проектом до совместного ведения заметок во время видеовстречи. Чтобы просмотреть весь код, пройдите в основную ветку этого репозитория GitHub.Вот так просто сегодня можно создать видеочат в вебе. Это означает, что веб в силу универсальности продолжает развиваться и, конечно, он давно уже перестал быть просто гипертекстом — удобством для чтения научных публикаций, как это было на заре его истории. Если вы не хотите оставаться в стороне от развития веб-технологий, то можете обратить внимание на наш курс о Frontend-разработке, а если вам не хочется ограничиваться фронтендом и есть желание понимать сеть глуюже, то вы можете присмотреться к нашему курсу о Fullstack-разработке на Python, где студенты получают все практические и теоретические знания, необходимые для начала карьеры разработчика на этом языке.
Узнайте, как прокачаться и в других специальностях или освоить их с нуля:
Другие профессии и курсыПРОФЕССИИ
- Профессия Fullstack-разработчик на Python
- Профессия Java-разработчик
- Профессия QA-инженер на JAVA
- Профессия Frontend-разработчик
- Профессия Этичный хакер
- Профессия C++ разработчик
- Профессия Разработчик игр на Unity
- Профессия Веб-разработчик
- Профессия iOS-разработчик с нуля
- Профессия Android-разработчик с нуля
КУРСЫ
- Курс по Machine Learning
- Курс «Machine Learning и Deep Learning»
- Курс «Математика для Data Science»
- Курс «Математика и Machine Learning для Data Science»
- Курс «Python для веб-разработки»
- Курс «Алгоритмы и структуры данных»
- Курс по аналитике данных
- Курс по DevOps
===========
Источник:
habr.com
===========
===========
Автор оригинала: Mia Adjei
===========Похожие новости:
- [Разработка игр, Управление продуктом, Карьера в IT-индустрии] Pet-проекты: прихоть, инструмент самосовершенствования или попытка отвлечься?
- [IT-инфраструктура, Конференции, Будущее здесь, IT-компании] ЦИПР-2021: бизнес, власть, NFT и немного 18+
- [Программирование, Софт] 6 вещей, которые бизнес-лидеры должны знать о RPA в 2021 году (перевод)
- [Конференции] МИК ВАК совместно с российскими ведущими вузами проведет серию вебинаров о вакцинах, их разработке и использовании
- [Информационная безопасность, C++, Системное программирование, Конференции] Онлайн-конференция KasperskyOS Night: доклады о нестандартных задачах
- [JavaScript, Разработка мобильных приложений, Разработка под Tizen, Производство и разработка электроники, Мониторы и ТВ] Разработка Tizen-приложений для Samsung Smart TV: полный гайд для Javascript-разработчиков
- [Производство и разработка электроники, IT-компании] Фабрики Samsung начнут массовый выпуск микросхем по техпроцессу 3 нм не раньше 2024 года
- GitHub начал тестирование AI-ассистента, помогающего при написании кода
- [Ненормальное программирование, Программирование, Совершенный код, C++, C] Металингвистический совратитель Си. Опус III: Садистская машина
- [Информационная безопасность, Разработка для интернета вещей] Приглашаем на летнюю конференцию KasperskyOS Night
Теги для поиска: #_javascript, #_programmirovanie (Программирование), #_konferentsii (Конференции), #_videokonferentssvjaz (Видеоконференцсвязь), #_skillfactory, #_twilio, #_js, #_razrabotka (разработка), #_konferentsii (конференции), #_videosvjaz (видеосвязь), #_sinhronizatsija (синхронизация), #_open_source, #_github, #_svjaz (связь), #_blog_kompanii_skillfactory (
Блог компании SkillFactory
), #_javascript, #_programmirovanie (
Программирование
), #_konferentsii (
Конференции
), #_videokonferentssvjaz (
Видеоконференцсвязь
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 02:45
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Представьте, что вам нужно создать видеочат, функционал которого должен находиться под вашим контролем, например для закрытой группы людей со своими специфическими требованиями. При этом чат нужен вчера, начинать писать его с нуля уже поздно. В этом материале, переводом которого мы решили поделиться к старту курса о Frontend-разработке, рассказывается, как разработать программируемый видеочат на основе Twilio. В статье вы найдёте две ветки кода на Github, первая содержит простую основу чата, о которой пойдёт речь в материале, а вторая — завершённый пример чата.ПодготовкаЧто вам будет нужно:
git clone -b start https://github.com/adjeim/video-note-collab.git
cd video-note-collab
npm install cp .env.template .env
TWILIO_ACCOUNT_SID
TWILIO_SYNC_SERVICE_SID TWILIO_API_KEY_SID TWILIO_API_KEY_SECRET npm start
Протестируйте приложение, набрав несколько слов в блокноте. При вводе пробела, клавиши ввода или знаков препинания запускается синхронизация. Если вы откроете второе окно браузера по адресу http://localhost:3000/ и одновременно посмотрите на них, вы должны увидеть, что текст, который вы вводите в одном окне, отображается и в другом: Как это происходит? Это приложение использует Twilio Sync для синхронизации состояния и данных между браузерами и устройствами в режиме реального времени. Здесь у вас есть документ Sync, который называется notepad. Когда страница загружается, создаётся новый токен доступа, который передаётся Sync клиенту. Если документ существует, его содержимое загружается в <textarea>. Приложение отслеживает обновления документа, обновляя положение курсора и содержимое блокнота. Если вы откроете инструменты разработчика своего браузера, вы также сможете увидеть изменения в контенте, который записывается в консоль.Идея здесь аналогична идее других инструментов совместной работы с заметками, таким как Google Docs или Notion. С помощью этого типа приложения вы можете вместе с другим человеком просматриватьодин и тот же документ и вместе редактировать его в режиме реального времени. Запустите приложение — и переходите к следующему шагуОбновите макет приложенияПервое, что вам нужно сделать, — это немного обновить макет вашего приложения. Если вы прямо сейчас откроете public/index.html в редакторе кода, то увидите, что Tailwind CSS и Twilio Sync уже подключены в проект. Обновите элемент <head>, добавив в него библиотеку Twilio Video, как показано в приведённом ниже коде: <html>
<head> <meta name='viewport' content='width=device-width, initial-scale=1.0' /> <link href='https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css' rel='stylesheet'> <script type="text/javascript" src="https://media.twiliocdn.com/sdk/js/sync/v2.0/twilio-sync.min.js"></script> <script src='https://sdk.twilio.com/js/video/releases/2.15.0/twilio-video.min.js'></script> <title>Video Collaboration with Notes</title> </head> <body class='bg-grey-100 p-10 flex flex-wrap container'>
<form id='login' class='w-full max-h-20 flex items-center py-2'> <input class='appearance-none bg-transparent border-b border-green-500 mr-3 py-1 px-2 focus:outline-none' id='identity' type='text' placeholder='Enter your name...' required> <button id='joinOrLeaveRoom' class='bg-green-500 hover:bg-green-700 text-white py-1 px-4 rounded' type='submit'> Join Video Call </button> </form> <textarea id='notepad' class='h-44 w-full shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea> </form>
<textarea disabled id='notepad' class='bg-gray-200 h-140 w-6/12 shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea> <textarea disabled id='notepad' class='bg-gray-200 h-140 w-6/12 shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea>
<div id='container' class='w-5/12 bg-green-100'> <div id='participantsContainer'> <div id='localParticipant'> <div id='localVideoTrack' class='participant'></div> </div> <div id='remoteParticipants'> <!-- Remote participants will be added here as they join the call --> </div> </div> </div> const AccessToken = require('twilio').jwt.AccessToken;
const SyncGrant = AccessToken.SyncGrant; const VideoGrant = AccessToken.VideoGrant; app.use(express.json()); app.post('/token', async (req, res) => {
if (!req.body.identity || !req.body.room) { return res.status(400); } // Get the user's identity from the request const identity = req.body.identity; // Create a 'grant' identifying the Sync service instance for this app. const syncGrant = new SyncGrant({ serviceSid: process.env.TWILIO_SYNC_SERVICE_SID }); // Create a video grant const videoGrant = new VideoGrant({ room: req.body.room }) // Create an access token which we will sign and return to the client, // containing the grant we just created and specifying their identity. const token = new AccessToken( process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_API_KEY_SID, process.env.TWILIO_API_KEY_SECRET, ); token.addGrant(syncGrant); token.addGrant(videoGrant); token.identity = identity; // Serialize the token to a JWT string and include it in a JSON response res.send({ identity: identity, token: token.toJwt() }); }); Теперь ваш токен предоставит пользователям вашего приложения доступ к синхронизации и к видео. Теперь, когда вы обновили серверную часть приложения, пора вернуться на клиентскую сторону и отобразить видео в окне браузера.Подключение и вывод видео участниковВернитесь в public/index.html в редакторе кода. Посмотрите на код в последнем теге <script> в конце файла. Вы увидите, что когда приложение загружается в браузере, этот код получает токен доступа из вашего запроса на токен, затем подключает клиент синхронизации и обновляет блокнот. Чтобы добавить видео в этот проект, нужно изменить этот код таким образом, чтобы приложение получило токен после того, как пользователь введёт своё имя и нажмёт кнопку «Join Video Call» в пользовательском интерфейсе. Затем этот токен будет использоваться для подключения пользователя к синхронизированному блокноту и видеозвонку. Чуть ниже вашей переменной notepad добавьте ещё несколько переменных, чтобы упростить обращение к другим элементам в вашем пользовательском интерфейсе: <script>
const notepad = document.getElementById('notepad'); const localVideoTrack = document.getElementById('localVideoTrack'); const login = document.getElementById('login'); const identityInput = document.getElementById('identity'); const joinLeaveButton = document.getElementById('joinOrLeaveRoom'); const localParticipant = document.getElementById('localParticipant'); const remoteParticipants = document.getElementById('remoteParticipants'); let connected = false; let room; let syncDocument; let twilioSyncClient; const addLocalVideo = async () => {
const videoTrack = await Twilio.Video.createLocalVideoTrack(); const trackElement = videoTrack.attach(); localVideoTrack.appendChild(trackElement); }; addLocalVideo();
</script> const connectOrDisconnect = async (event) => {
event.preventDefault(); if (!connected) { const identity = identityInput.value; joinLeaveButton.disabled = true; joinLeaveButton.innerHTML = 'Connecting...'; try { await connect(identity); } catch (error) { console.log(error); alert('Failed to connect to video room.'); joinLeaveButton.innerHTML = 'Join Video Call'; joinLeaveButton.disabled = false; } } else { disconnect(); } }; // Add listener
notepad.addEventListener('keyup', (event) => { // Define array of triggers to sync (space, enter, and punctuation) // Otherwise sync will fire every time const syncKeys = [32, 13, 8, 188, 190]; if (syncKeys.includes(event.keyCode)) { syncNotepad(twilioSyncClient); } }) login.addEventListener('submit', connectOrDisconnect); const connect = async (identity) => {
const response = await fetch('/token', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({'identity': identity, room: 'My Video Room'}) }); const data = await response.json(); const token = data.token; // Set up sync document twilioSyncClient = new Twilio.Sync.Client(token); notepad.disabled = false; notepad.classList.remove('bg-gray-200'); syncDocument = await twilioSyncClient.document('notepad'); // Load the existing Document notepad.value = syncDocument.data.content || ''; // Listen to updates on the Document syncDocument.on('updated', (event) => { // Update the cursor position let cursorStartPos = notepad.selectionStart; let cursorEndPos = notepad.selectionEnd; notepad.value = event.data.content; // Reset the cursor position notepad.selectionEnd = cursorEndPos; console.log('Received Document update event. New value:', event.data.content); }) // Set up the video room room = await Twilio.Video.connect(token); const identityDiv = document.createElement('div'); identityDiv.setAttribute('class', 'identity'); identityDiv.innerHTML = identity; localParticipant.appendChild(identityDiv); room.participants.forEach(participantConnected); room.on('participantConnected', participantConnected); room.on('participantDisconnected', participantDisconnected); connected = true; joinLeaveButton.innerHTML = 'Leave Video Call'; joinLeaveButton.disabled = false; identityInput.style.display = 'none'; }; const disconnect = () => {
room.disconnect(); let removeParticipants = remoteParticipants.getElementsByClassName('participant'); while (removeParticipants[0]) { remoteParticipants.removeChild(removeParticipants[0]); } joinLeaveButton.innerHTML = 'Join Video Call'; connected = false; identityInput.style.display = 'inline-block'; localParticipant.removeChild(localParticipant.lastElementChild); syncDocument.close(); twilioSyncClient = null; notepad.value = ''; notepad.disabled = true; notepad.classList.add('bg-gray-200'); }; const participantConnected = (participant) => {
const participantDiv = document.createElement('div'); participantDiv.setAttribute('id', participant.sid); participantDiv.setAttribute('class', 'participant'); const tracksDiv = document.createElement('div'); participantDiv.appendChild(tracksDiv); const identityDiv = document.createElement('div'); identityDiv.setAttribute('class', 'identity'); identityDiv.innerHTML = participant.identity; participantDiv.appendChild(identityDiv); remoteParticipants.appendChild(participantDiv); participant.tracks.forEach(publication => { if (publication.isSubscribed) { trackSubscribed(tracksDiv, publication.track); } }); participant.on('trackSubscribed', track => trackSubscribed(tracksDiv, track)); participant.on('trackUnsubscribed', trackUnsubscribed); }; const participantDisconnected = (participant) => {
document.getElementById(participant.sid).remove(); }; const trackSubscribed = (div, track) => {
const trackElement = track.attach(); div.appendChild(trackElement); }; const trackUnsubscribed = (track) => { track.detach().forEach(element => { element.remove() }); }; Введите своё имя в поле ввода и нажмите «Join Video Call». Вы увидите своё имя под видео. Если хотите, можете попробовать набрать текст в блокноте. Откройте другую вкладку браузера по адресу http://localhost:3000/ и присоединитесь к видеозвонку под другим именем. Как только вы это сделаете, вы увидите два изображения, а это означает, что вы можете общаться друг с другом и делиться блокнотом: Если вы введёте текст в блокнот на одной вкладке, а затем переключитесь на другую, вы увидите, что текст между ними синхронизирован.Что будет дальше с инструментом для совместной работы с заметками?У этого блокнота очень много возможностей: от совместной работы над письменным проектом до совместного ведения заметок во время видеовстречи. Чтобы просмотреть весь код, пройдите в основную ветку этого репозитория GitHub.Вот так просто сегодня можно создать видеочат в вебе. Это означает, что веб в силу универсальности продолжает развиваться и, конечно, он давно уже перестал быть просто гипертекстом — удобством для чтения научных публикаций, как это было на заре его истории. Если вы не хотите оставаться в стороне от развития веб-технологий, то можете обратить внимание на наш курс о Frontend-разработке, а если вам не хочется ограничиваться фронтендом и есть желание понимать сеть глуюже, то вы можете присмотреться к нашему курсу о Fullstack-разработке на Python, где студенты получают все практические и теоретические знания, необходимые для начала карьеры разработчика на этом языке. Узнайте, как прокачаться и в других специальностях или освоить их с нуля: Другие профессии и курсыПРОФЕССИИ
=========== Источник: habr.com =========== =========== Автор оригинала: Mia Adjei ===========Похожие новости:
Блог компании SkillFactory ), #_javascript, #_programmirovanie ( Программирование ), #_konferentsii ( Конференции ), #_videokonferentssvjaz ( Видеоконференцсвязь ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 02:45
Часовой пояс: UTC + 5