הקלטת שיחות וידאו: יישום בצד השרת ובצד הלקוח

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

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

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

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

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
הקלטת שיחות וידאו: יישום בצד השרת ובצד הלקוח
בינוני
~3-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

תארו לעצמכם: ייעוץ משפטי מקוון — חודש לאחר מכן הלקוח חולק על ההמלצות. ללא הקלטת שיחה, הוכחת עמדתכם בלתי אפשרית. אנו מיישמים הקלטת שיחות וידאו עם לכידה בצד השרת, המאוחסנת ב-S3 ומוגנת מפני שינוי באמצעות hashes בלתי ניתנים לשינוי וחתימות דיגיטליות. זהו הבסיס לעמידה ברגולציה (GDPR, 152-FZ) ולאנליטיקה (ניתוח איכות ייעוץ, הדרכת צוות). עבור EdTech, LegalTech ו-MedTech, היעדר הקלטה משמעותו סיכון גבוה: מקנסות רגולטוריים ועד נזק למוניטין. אנו מספקים פתרון מפתח ב-2–4 ימים באמצעות LiveKit Egress או MediaRecorder.

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

כיצד לבחור שיטת הקלטה: שרת או לקוח?

קיימות שתי דרכים: הקלטת Egress על השרת (LiveKit, Daily) או הקלטה בצד הלקוח באמצעות ממשק MediaRecorder API בדפדפן.

מאפיין שרת (LiveKit Egress) לקוח (MediaRecorder)
אמינות גבוהה — בלתי תלויה בלקוח בינונית — תלויה בדפדפן וברשת
איכות קבועה (720p, 30fps) כפי שהמכשיר מאפשר
עומס על הלקוח אפס בינוני (קידוד)
תמיכה בפורמטים MP4, WebM WebM, MP4 (מוגבל)
עלות תשתית שרת + S3 S3 בלבד

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

מה לעשות עם מהירות אינטרנט נמוכה?

הקלטה בצד הלקוח עם חיבור חלש עלולה לייצר חפצים או לקטוע. הפתרון הוא קצב סיביות אדפטיבי: הפחתת videoBitsPerSecond ל-500 Kbps. או השתמשו בהקלטה בצד השרת — היא אינה תלויה ברשת של המשתתף. בנוסף, ניתן להגדיר גיבוי להקלטת שמע כאשר המהירות יורדת באופן קריטי.

הגדרה שלב אחר שלב של LiveKit Egress

  1. פרוס שרת LiveKit (גרסה 1.4+) עם אחסון S3.
  2. הגדר מפתחות API ונקודת קצה webhook.
  3. השתמש ב-EgressClient כדי להתחיל הקלטת חדר.
  4. עבד את אירוע egress_ended — שמור את קישור ההקלטה.
  5. הודע למשתתפים באמצעות ערוץ נתונים.

מדוע הקלטה בצד השרת אמינה יותר?

LiveKit מקליט את הווידאו המאוחד על השרת — ללא כל מעורבות של דפדפן הלקוח. האלגוריתם מבטיח TTFB מתחת לשנייה אחת. לפי תיעוד LiveKit Egress, Egress תומך בהקלטה ב-MP4 ו-WebM עד רזולוציית 4K. חיסכון בעלויות מוויתור על שרתים יקרים להקלטה בצד הלקוח יכול להגיע ל-60% בהשוואה לגישת השרת.

import { EgressClient, EncodedFileOutput, S3Upload } from 'livekit-server-sdk';

const egressClient = new EgressClient(
  process.env.LIVEKIT_URL!,
  process.env.LIVEKIT_API_KEY!,
  process.env.LIVEKIT_API_SECRET!
);

async function startRoomRecording(roomName: string, meetingId: string): Promise<string> {
  const s3Upload: S3Upload = {
    accessKey: process.env.AWS_ACCESS_KEY_ID!,
    secret: process.env.AWS_SECRET_ACCESS_KEY!,
    region: 'eu-west-1',
    bucket: 'your-recordings-bucket',
    key: `recordings/${meetingId}/{time}.mp4`,
  };

  const egress = await egressClient.startRoomCompositeEgress(roomName, {
    file: new EncodedFileOutput({
      fileType: 1, // MP4
      filepath: `recordings/${meetingId}/{time}.mp4`,
      s3: s3Upload,
    }),
    layout: 'grid-dark',
    encodingOptions: {
      width: 1280,
      height: 720,
      framerate: 30,
      videoBitrate: 3000,
      audioBitrate: 128,
    },
  });

  await db.recordings.create({
    meetingId,
    egressId: egress.egressId,
    status: 'recording',
    startedAt: new Date(),
  });

  return egress.egressId;
}

async function stopRecording(egressId: string): Promise<void> {
  await egressClient.stopEgress(egressId);
  await db.recordings.update(
    { egressId },
    {
      status: 'processing',
      stoppedAt: new Date(),
    }
  );
}

LiveKit Webhook למוכנות הקלטה

app.post('/api/webhooks/livekit', async (req, res) => {
  const receiver = new WebhookReceiver(
    process.env.LIVEKIT_API_KEY!,
    process.env.LIVEKIT_API_SECRET!
  );
  const event = receiver.receive(req.body, req.headers['authorization']);
  if (event.event === 'egress_ended') {
    const { egressId, file } = event.egressInfo;
    const s3Key = file?.location;
    await db.recordings.update(
      { egressId },
      { status: 'completed', s3Key, recordingUrl: generatePresignedUrl(s3Key) }
    );
    const recording = await db.recordings.findByEgressId(egressId);
    await notifyParticipants(recording.meetingId, recording.recordingUrl);
  }
  res.status(200).end();
});

הקלטה בצד הלקוח באמצעות MediaRecorder API

שימו לב: כאשר אין תשתית שרת — הקליטו בדפדפן. MediaRecorder API תומך ב-WebM וב-MP4 מוגבל.

class ClientRecorder {
  private mediaRecorder: MediaRecorder | null = null;
  private chunks: Blob[] = [];

  async start(stream: MediaStream): Promise<void> {
    this.chunks = [];
    const mimeType = [
      'video/webm;codecs=vp9,opus',
      'video/webm;codecs=vp8,opus',
      'video/webm',
      'video/mp4',
    ].find(t => MediaRecorder.isTypeSupported(t)) ?? 'video/webm';

    this.mediaRecorder = new MediaRecorder(stream, {
      mimeType,
      videoBitsPerSecond: 2_500_000,
      audioBitsPerSecond: 128_000,
    });

    this.mediaRecorder.ondataavailable = (e) => {
      if (e.data.size > 0) this.chunks.push(e.data);
    };

    this.mediaRecorder.start(1000);
  }

  stop(): Promise<Blob> {
    return new Promise((resolve) => {
      this.mediaRecorder!.onstop = () => {
        const blob = new Blob(this.chunks, { type: this.mediaRecorder!.mimeType });
        resolve(blob);
      };
      this.mediaRecorder!.stop();
    });
  }
}

// Использование
const recorder = new ClientRecorder();
await recorder.start(combinedStream);
const blob = await recorder.stop();
const formData = new FormData();
formData.append('recording', blob, 'recording.webm');
await fetch(`/api/meetings/${meetingId}/recording`, {
  method: 'POST',
  body: formData
});

הודעת הקלטה והסכמה

מבחינה חוקית — יש להודיע לכל המשתתפים. אנו מיישמים זאת באמצעות באנר וערוץ נתונים:

await room.localParticipant.publishData(
  new TextEncoder().encode(JSON.stringify({ type: 'recording_started' })),
  { reliable: true }
);
if (msg.type === 'recording_started') { toast.warning('Этот звонок записывается', { duration: Infinity, icon: '🔴' }); } 

תהליך ולוח זמנים

שלב משך
ניתוח דרישות וסיכום 1-2 ימים
עיצוב ארכיטקטורת הקלטה 0.5 יום
אינטגרציה של LiveKit או MediaRecorder 1-2 ימים
הגדרת S3 ו-webhooks 0.5 יום
בדיקות וניפוי שגיאות יום אחד
תיעוד 0.5 יום

טעויות יישום אופייניות

  • בחירת codec לא תואם: MediaRecorder אינו תומך ב-MP4 בכל הדפדפנים — השתמשו ב-WebM עם VP8/VP9.
  • היעדר הודעת הקלטה: מפר דרישות חוקיות.
  • אחזור העלאה גבוה: השתמשו בהעלאה מקוטעת ל-S3.
  • webhooks לא מוגדרים: אירועי import { EgressClient, EncodedFileOutput, S3Upload } from 'livekit-server-sdk'; const egressClient = new EgressClient( process.env.LIVEKIT_URL!, process.env.LIVEKIT_API_KEY!, process.env.LIVEKIT_API_SECRET! ); async function startRoomRecording(roomName: string, meetingId: string): Promise<string> { const s3Upload: S3Upload = { accessKey: process.env.AWS_ACCESS_KEY_ID!, secret: process.env.AWS_SECRET_ACCESS_KEY!, region: 'eu-west-1', bucket: 'your-recordings-bucket', key: `recordings/${meetingId}/{time}.mp4`, }; const egress = await egressClient.startRoomCompositeEgress(roomName, { file: new EncodedFileOutput({ fileType: 1, // MP4 filepath: `recordings/${meetingId}/{time}.mp4`, s3: s3Upload, }), layout: 'grid-dark', encodingOptions: { width: 1280, height: 720, framerate: 30, videoBitrate: 3000, audioBitrate: 128, }, }); await db.recordings.create({ meetingId, egressId: egress.egressId, status: 'recording', startedAt: new Date(), }); return egress.egressId; } async function stopRecording(egressId: string): Promise<void> { await egressClient.stopEgress(egressId); await db.recordings.update({ egressId }, { status: 'processing', stoppedAt: new Date(), }); } שהוחמצו מובילים לאובדן הקלטות.

מה כלול

  • עיצוב ארכיטקטורת הקלטה (שרת/לקוח).
  • אינטגרציה של שרת LiveKit או MediaRecorder.
  • אחסון S3 והגדרת webhooks אוטומטית.
  • יישום בקרת גישה (presigned URLs, RBAC).
  • תיעוד (סכימה, הוראות תפעול).
  • תמיכה לאחר השקה — חודש אחד.
פרטים טכניים נוספים

להקלטה בצד השרת, אנו משתמשים ב-Egress עם תצורת app.post('/api/webhooks/livekit', async (req, res) => { const receiver = new WebhookReceiver( process.env.LIVEKIT_API_KEY!, process.env.LIVEKIT_API_SECRET! ); const event = receiver.receive(req.body, req.headers['authorization']); if (event.event === 'egress_ended') { const { egressId, file } = event.egressInfo; const s3Key = file?.location; await db.recordings.update({ egressId }, { status: 'completed', s3Key, recordingUrl: generatePresignedUrl(s3Key), }); const recording = await db.recordings.findByEgressId(egressId); await notifyParticipants(recording.meetingId, recording.recordingUrl); } res.status(200).end(); }); כדי ללכוד מספר משתתפים. להקלטה בצד הלקוח, אנו מיישמים class ClientRecorder { private mediaRecorder: MediaRecorder | null = null; private chunks: Blob[] = []; async start(stream: MediaStream): Promise<void> { this.chunks = []; const mimeType = [ 'video/webm;codecs=vp9,opus', 'video/webm;codecs=vp8,opus', 'video/webm', 'video/mp4', ].find(t => MediaRecorder.isTypeSupported(t)) ?? 'video/webm'; this.mediaRecorder = new MediaRecorder(stream, { mimeType, videoBitsPerSecond: 2_500_000, audioBitsPerSecond: 128_000, }); this.mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) this.chunks.push(e.data); }; this.mediaRecorder.start(1000); } stop(): Promise<Blob> { return new Promise((resolve) => { this.mediaRecorder!.onstop = () => { const blob = new Blob(this.chunks, { type: this.mediaRecorder!.mimeType }); resolve(blob); }; this.mediaRecorder!.stop(); }); } } // Использование const recorder = new ClientRecorder(); await recorder.start(combinedStream); const blob = await recorder.stop(); const formData = new FormData(); formData.append('recording', blob, 'recording.webm'); await fetch(`/api/meetings/${meetingId}/recording`, { method: 'POST', body: formData }); לסנכרון רצועות שמע. בשני המקרים, אנו מגדירים ניטור באמצעות Prometheus/Grafana.

המומחיות שלנו

אנו מבטיחים יציבות: למעלה מ-10 שנות ניסיון בהקלטת שיחות וידאו. המומחים המוסמכים שלנו עבדו עם WebRTC, LiveKit, Daily. השלמנו 50+ פרויקטים עבור EdTech ו-LegalTech. צרו קשר — נבחן את הפרויקט שלכם ונציע לוחות זמנים. הזמינו פיתוח של הקלטת שיחות וידאו, ונכין פתרון לתקציב שלכם.

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

הקלטה בצד השרת באמצעות LiveKit Egress + S3 + webhooks — 2–3 ימים. הקלטה בצד הלקוח MediaRecorder + העלאה — 1–2 ימים. העלות מחושבת באופן אישי לפי מורכבות האינטגרציה. חיסכון בעלויות מוויתור על שרתים יקרים להקלטה בצד הלקוח — עד 60%. קבלו ייעוץ לפרויקט שלכם.