שילוב Twilio Video לשיחות וידאו באתר

מורכבויות WebRTC ו-SDK סגורים מעכבים לעיתים קרובות השקת שיחות וידאו באתר, והופכים את האינטגרציה לתהליך ארוך ומסוכן. אנחנו מטפלים בכל המחזור—מעיצוב צד השרת ועד הגדרת ממשק הלקוח—באמצעות Twilio Video לניהול שיחות גמיש. הצוות שלנו מספק את הפרויקט במפתח מלא, ומבטיח פעילות אמינה ותמיכה מתמשכת.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
שילוב Twilio Video לשיחות וידאו באתר
בינוני
~5 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1365
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113
  • פיתוח אתר עבור SBH Partners
    פיתוח אתר עבור SBH Partners
    1201
  • פיתוח אתר עבור Red Pear
    פיתוח אתר עבור Red Pear
    619

שילוב Twilio Video לשיחות וידאו באתר

צוותים נתקלים לעיתים קרובות באתגרים בעת הוספת שיחות וידאו לאתר עם Twilio Video. המורכבות כוללת הגדרת שרת, יצירת טוקנים ובניית רכיב לקוח. טעויות נפוצות כוללות TTL שגוי של טוקן, התעלמות מטיפול בחיבור מחדש ובחירה לא אופטימלית של סוג חדר. לדוגמה, לקוח איבד עד 30% מהפגישות עקב TTL קצר מדי (5 דקות במקום 3600). לאחר יישום רענון וטיפול נכון ב-DisconnectedEvent, הסבילות לתקלות עלתה ל-99.9%. לקוח אחר—שירות טלרפואה—איבד עד 20% מהשיחות עקב טיפול לא נכון בחיבור מחדש. יישמנו מנגנון ניסיון חוזר והרשמה נכונה לאירועים, והעלינו את שיעור השיחות המוצלחות ל-99.5%. ניסיון השילוב שלנו כולל 5+ שנים ו-20+ פרויקטים. אנו מבטיחים פעולה יציבה ותמיכה במהלך הפיתוח.

למה Twilio Video עדיף על פתרונות מוכנים

בניגוד ל-Zoom SDK או Jitsi, Twilio Video נותן לך שליטה מלאה על הממשק והלוגיקה. אתה לא קשור לרשת משתתפים סטנדרטית—אתה יכול ליישם רשת משלך, לעבור בין דוברים, להוסיף אפקטים או מידרציה. בנוסף, המערכת האקולוגית של Twilio מאפשרת לשלב וידאו עם טלפוניה ו-SMS, מה שנוח לשירותי טלרפואה או ייעוץ. אינטגרציית API עם הפלטפורמה פשוטה הודות ל-REST API ו-SDKs. השירות מבוסס על WebRTC, מה שמבטיח תאימות לרוב הדפדפנים והמכשירים הניידים.

כיצד לנהל משתתפים בחדר

לאחר חיבור לחדר, כל משתתף מיוצג על ידי אובייקט RemoteParticipant. האירועים participantConnected ו-participantDisconnected מנוטרים ברמת החדר. עבור כל משתתף מרוחק, הירשם ל-trackSubscribed ו-trackUnsubscribed כדי להוסיף/להסיר זרמי וידאו. זה מאפשר לך לעדכן את הרשת באופן דינמי. חשוב לטפל במקרים שבהם משתתף מחליף מצלמה—המסלול משתנה, ויש לחבר אותו מחדש ל-DOM.

שילוב Twilio Video באפליקציית React

תהליך השילוב כולל מספר שלבים. נעבור על כל אחד באמצעות TypeScript ו-React 18.

שלב 1: הגדרת שרת—יצירת חדרים ויצירת Access Tokens. שלב 2: פיתוח רכיב React—חיבור לחדר והצגת זרמים.

שלב 3: טיפול בהקלטת שיחות—הפעלת הקלטה וקבלת קישורים.

שלב 1: יצירת חדר ו-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 endpoint
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 });
});

שלב 2: רכיב 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>
  );
}

שלב 3: הקלטת שיחות

// Включить запись для комнаты
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`,
  }));
}

בחירת סוג חדר

בחירת סוג החדר תלויה בתרחיש. Peer-to-Peer (P2P) מתאים לשיחות וידאו אחד-על-אחד: זמן השהיה מתחת ל-150 אלפיות השנייה, ללא עיבוד שרת, אך מוגבל ל-2 משתתפים. Group Small תומך בעד 4 משתתפים עם זמן השהיה בינוני. Group תומך בעד 50 משתתפים, הקלטה ומעקב, אך זמן השהיה עד 300 אלפיות השנייה. אם אתה מתכנן סמינרים מקוונים, השתמש ב-Group והפעל הקלטה.

השוואת סוגי חדרים

סוג חדר מקסימום משתתפים זמן השהיה תכונות
Peer-to-Peer 2 <150 אלפיות השנייה זמן השהיה נמוך, ללא עיבוד שרת
Group Small 4 <200 אלפיות השנייה איזון בין ביצועים למספר משתתפים
Group 50 <300 אלפיות השנייה ועידות מלאות, הקלטה, מעקב

פרמטרי תצורה מרכזיים

פרמטר ערך הערה
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 endpoint 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 }); }); , 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`, })); } 2-50 מקסימום משתתפים בו-זמנית
type 3600 (שניות) אורך חיים של Access Token, מומלץ שעה אחת
peer-to-peer group-small/group הקלטה אוטומטית בעת חיבור
maxParticipants 1280x720 רזולוציית וידאו, משפיעה על רוחב הפס

מה כלול בעבודת השילוב

  • הגדרת חשבון Twilio ומפתחות API
  • נקודות קצה בשרת ליצירת חדרים ויצירת טוקנים
  • רכיב React עם ממשק משתמש מותאם להצגת משתתפים
  • הקלטת שיחות ושילוב webhooks לטיפול באירועים
  • פריסה ותיעוד תמיכה
  • הדרכת צוות על שימוש ב-SDK

טעויות נפוצות וכיצד להימנע מהן

  • פגות טוקן במהלך שיחה: הגדר ttl ל-3600 שניות לפחות ויישם מנגנון רענון באמצעות אירועי שרת.
  • שאילתות N+1 בעת שליפת רשימת הקלטות: השתמש ב-recordParticipantsOnConnect או בפאג'ינציה.
  • רשת וידאו לא מסונכרנת: הירשם ל-true לעדכוני DOM נכונים.
  • התעלמות מטיפול באובדן חיבור: השתמש במנגנון ניסיון חוזר עם backoff אקספוננציאלי. אם אתה נתקל בבעיות דומות, צור קשר—נעזור לך לפתור אותן.

לוחות זמנים ועלות

שילוב Twilio Video בסיסי + רכיב React + Access Token — 2–3 ימים. עם ניהול משתתפים, הקלטה ו-webhooks — 4–5 ימים. עלות השילוב נעה בדרך כלל בין $2,500 ל-$5,000 לפתרון מותאם מלא, תלוי במורכבות הממשק ובתכונות נוספות כמו הקלטה או מידרציה מותאמת. צור קשר לייעוץ חינמי והערכה מדויקת.

גורמים המשפיעים על העלות

עלות השילוב תלויה במורכבות הממשק המותאם, בצורך בהקלטה ו-webhooks, במספר סוגי החדרים ובשילוב עם שירותים אחרים. אנו מחשבים את העלות באופן אישי לאחר ניתוח הדרישות. עלויות לדקה לשימוש בווידאו נעות בין $0.004 ל-$0.01 למשתתף, תלוי ברזולוציה ובהקלטה. צור קשר להערכה מדויקת.

לפרטים נוספים, ראה בדוק את התיעוד הרשמי.