Інтеграція Twilio Video для відеодзвінків на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Інтеграція Twilio Video для відеодзвінків на сайті
Середня
~5 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Інтеграція Twilio Video для відеозвонків на веб-сайті

Twilio Video — WebRTC-платформа з підтримкою групових комнат, записи, підключення телефонії. SDK для JS, iOS, Android. Виділяється гнучкістю: можна будувати як прості P2P звонки, так і комнати до 50 учасників через Group Rooms.

Створення комнати та Access Token на сервері

npm install twilio
import twilio from 'twilio';
const AccessToken = twilio.jwt.AccessToken;
const VideoGrant = AccessToken.VideoGrant;

const client = twilio(
  process.env.TWILIO_ACCOUNT_SID!,
  process.env.TWILIO_AUTH_TOKEN!
);

// Створити комнату
async function createRoom(name: string) {
  const room = await client.video.v1.rooms.create({
    uniqueName: name,
    type: 'group',  // 'go' | 'peer-to-peer' | 'group' | 'group-small'
    maxParticipants: 10,
    recordParticipantsOnConnect: false,
    statusCallback: `${process.env.APP_URL}/api/webhooks/twilio-video`,
    statusCallbackMethod: 'POST',
  });
  return room.sid;
}

// Видати токен учаснику
function generateVideoToken(identity: string, roomName: string): string {
  const token = new AccessToken(
    process.env.TWILIO_ACCOUNT_SID!,
    process.env.TWILIO_API_KEY!,
    process.env.TWILIO_API_SECRET!,
    { identity, ttl: 3600 }
  );

  const grant = new VideoGrant({ room: roomName });
  token.addGrant(grant);

  return token.toJwt();
}

// API ендпоінт
app.post('/api/video/join', authenticate, async (req, res) => {
  const { roomName } = req.body;

  // Переконатися, що комната існує або створити
  try {
    await client.video.v1.rooms(roomName).fetch();
  } catch {
    await createRoom(roomName);
  }

  const token = generateVideoToken(req.user.id, roomName);
  res.json({ token, roomName });
});

React компонент з Twilio Video JS SDK

npm install twilio-video
import { connect, Room, LocalVideoTrack } from 'twilio-video';
import { useEffect, useRef, useState } from 'react';

function TwilioVideoRoom({ token, roomName }: { token: string; roomName: string }) {
  const [room, setRoom] = useState<Room | null>(null);
  const [participants, setParticipants] = useState<string[]>([]);
  const localVideoRef = useRef<HTMLVideoElement>(null);

  useEffect(() => {
    let connectedRoom: Room;

    connect(token, {
      name: roomName,
      audio: true,
      video: { width: 1280, height: 720 },
    }).then((room) => {
      connectedRoom = room;
      setRoom(room);

      // Відобразити локальне відео
      const localTrack = [...room.localParticipant.videoTracks.values()][0]?.track;
      if (localTrack && localVideoRef.current) {
        localVideoRef.current.srcObject = new MediaStream([localTrack.mediaStreamTrack]);
      }

      // Обробка учасників
      room.participants.forEach((p) => {
        setParticipants(prev => [...prev, p.identity]);
      });

      room.on('participantConnected', (p) => {
        setParticipants(prev => [...prev, p.identity]);
        p.on('trackSubscribed', (track) => {
          if (track.kind === 'video') {
            const el = document.getElementById(`participant-${p.identity}`);
            if (el) track.attach(el as HTMLVideoElement);
          }
        });
      });

      room.on('participantDisconnected', (p) => {
        setParticipants(prev => prev.filter(id => id !== p.identity));
      });
    });

    return () => {
      connectedRoom?.disconnect();
    };
  }, [token, roomName]);

  return (
    <div className="grid grid-cols-2 gap-4">
      <div className="relative">
        <video ref={localVideoRef} autoPlay muted playsInline
          className="w-full rounded-xl" />
        <span className="absolute bottom-2 left-2 text-white text-sm bg-black/50 px-2 py-1 rounded">
          Ви
        </span>
      </div>
      {participants.map(identity => (
        <div key={identity} className="relative">
          <video id={`participant-${identity}`} autoPlay playsInline
            className="w-full rounded-xl" />
          <span className="absolute bottom-2 left-2 text-white text-sm bg-black/50 px-2 py-1 rounded">
            {identity}
          </span>
        </div>
      ))}
    </div>
  );
}

Запис звонку

// Увімкнути запис для комнати
async function enableRoomRecording(roomSid: string) {
  await client.video.v1.rooms(roomSid).recordings.create({
    // Записує всіх учасників
  });
}

// Отримати ссилку на запис після звонку
async function getRoomRecordings(roomSid: string) {
  const recordings = await client.video.v1.rooms(roomSid).recordings.list();
  return recordings.map(r => ({
    sid: r.sid,
    duration: r.duration,
    url: `https://video.twilio.com/v1/Recordings/${r.sid}/Media`,
  }));
}

Терміни

Базова інтеграція Twilio Video + React компонент + Access Token — 2–3 дні. З управлінням учасниками, записом та webhooks — 4–5 днів.