ویدیورایان
خانه / مستندات
مستندات رسمی

با ویدیورایان بسازید — از «لینک جلسه» تا قابلیت محصول

هر آنچه برای رفتن از یک لینک ساده به یک قابلیت واقعی در محصولتان لازم دارید: مفاهیم، دو جریان یکپارچه‌سازی گام‌به‌گام، نکات امنیتی و جدول عیب‌یابی خطاها. این راهنما را کنار مرجع API بخوانید تا شکل دقیق پاسخ‌ها را داشته باشید.

شروع سریع

دو مسیر جلوی شماست

هر دو سطح در نهایت یک چیز می‌سازند: توکن LiveKit برای wss://rtc.videorayan.ir. از هرکدام که امروز به کارتان می‌آید شروع کنید؛ بعداً بدون تغییر کد کلاینت می‌توانید عوضش کنید.

بدون کلید

لینک‌محور — ۵ دقیقه‌ای

با curl یا صفحهٔ ساخت جلسه یک اتاق بسازید، لینک /r/{roomId} را به اشتراک بگذارید — تمام. مهمان‌ها فقط نام نمایشی می‌دهند و وارد می‌شوند. مناسب جلسات، مشاوره‌ها و ابزارهای داخلی.

کلید Bearer

اتاق‌های متعلق به شما — یک بعدازظهر

بک‌اند شما اتاق‌های اجاره‌ای می‌سازد، برای هر کاربر توکن host/guest ضرب می‌کند و چرخهٔ عمر را کنترل می‌کند. مناسب محصولاتی که تماس در آن‌ها «قابلیت» است، نه فقط یک لینک.

fastest-possible-demo.sh
# create a room and open the hosted UI — that's the whole demo
ROOM=$(curl -s -X POST https://api.videorayan.ir/v1/public/rooms \
  -H "Content-Type: application/json" -d '{"name":"my-first-room"}' | jq -r .roomId)

open "https://videorayan.ir/r/$ROOM"   # macOS (linux: xdg-open)
مفاهیم

چهار مفهوم، ۹۵٪ پلتفرم

این چهار تا را بفهمید؛ بقیه فقط پارامتر است.

اتاق (Room)

ظرف جلسه با چرخهٔ عمر (active → ended/expired). اتاق رایگان: نامش دستگیرهٔ عمومی است و ۱۲ ساعت زنده می‌ماند. اتاق اجاره‌ای: UUID به‌همراه externalId خودتان، با عمر تا ۲۴ ساعت.

مرجع (Ref)

راه آدرس‌دادن به اتاق: UUID آن، یا برای اتاق‌های عمومی، نامش. در /v1/public/rooms/{ref}، /v1/guest/rooms/{ref}/tokens و رابط میزبانی‌شدهٔ /r/{ref} کار می‌کند.

توکن (Token)

یک JWT امضاشدهٔ LiveKit که دقیقاً به یک اتاق محدود است و حداقل دسترسی‌ها را دارد. پیش‌فرض حدود ۱۰ دقیقه اعتبار دارد و قابل تمدید نیست — به‌ازای هر جلسه تازه ضرب کنید و مثل یک اعتبارنامه با آن رفتار کنید.

شناسهٔ شرکت‌نده (Identity)

نام یکتای شرکت‌نده درون اتاق (۱ تا ۴۰ نویسه در سطح مهمان). شناسهٔ تکراری در یک اتاق ممکن نیست — اتصال جدیدتر جایگزین قدیمی‌تر می‌شود.

نقش‌ها: توکن‌های اجاره‌ای می‌توانند host یا guest باشند؛ توکن‌های سطح مهمان همیشه guestاند. نقش‌ها سمت سرور به دسترسی‌های LiveKit نگاشت می‌شوند — کلاینت نمی‌تواند خودش را ارتقا دهد.
راهنما

جریان ورود از مرورگر (سطح عمومی)

این دقیقاً همان جریانی است که صفحهٔ پیوستنِ میزبانی‌شده پیاده کرده — وقتی صفحهٔ ورود خودتان را می‌سازید همین را بازسازی کنید.

  • مرجع را resolve کنید. GET /v1/public/rooms/{ref} ← roomId واقعی، name و اینکه needsPassword true است یا نه. فیلد رمز را فقط در صورت نیاز نشان دهید.
  • هویت و رضایت رسانه. نام نمایشی بگیرید و با getUserMedia دوربین/میکروفن را request کنید تا کاربر قبل از ورود پیش‌نمایش ببیند؛ انتخابش را یاد بگیرید و بعد از اتصال اعمال کنید.
  • توکن ضرب کنید. POST /v1/guest/rooms/{roomId}/tokens با identity (و password در صورت نیاز).
  • نتیجه‌ها را صریح مدیریت کنید. 201 ← اتصال؛ 403 wrong_password ← رمز را دوباره بپرسید؛ 409 ← اتاق پر/پایان‌یافته؛ 404 ← لینک نامعتبر، کاربر را به خانه بفرستید.
  • وصل شوید. new Room().connect('wss://rtc.videorayan.ir', token) — برای خطاهای گذرا یک تلاش مجدد کافی است.
join-flow.js (browser)
const API = 'https://api.videorayan.ir/v1';

async function joinRoom(ref, identity, password) {
  // 1 — resolve (validates the link before asking the user anything)
  const info = await fetch(`${API}/public/rooms/${encodeURIComponent(ref)}`).then(r => r.json());
  if (!info.roomId) throw new Error('room_not_found');

  // 2 + 3 — mint the token (password only when the room needs one)
  const res = await fetch(`${API}/guest/rooms/${info.roomId}/tokens`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ identity, ...(info.needsPassword ? { password } : {}) })
  });

  // 4 — handle outcomes explicitly
  if (res.status === 403) throw new Error('wrong_password');
  if (res.status === 409) throw new Error('room_full_or_ended');
  if (!res.ok) throw new Error('token_failed_' + res.status);
  const { token } = await res.json();

  // 5 — connect (single retry on transient failure)
  const { Room } = await import('livekit-client');
  const room = new Room({ adaptiveStream: false, dynacast: true });
  await room.connect('wss://rtc.videorayan.ir', token);
  return room;
}
راهنما

جریان بک‌اند (اجاره‌ای) برای اتاق‌هایی که مال شماست

کلید API فقط در محیط بک‌اند شما زندگی می‌کند — مرورگر هرگز آن را نمی‌بیند.

  • ۱ — هنگام رخداد دامنه، اتاق بسازید. نوبت رزرو شد، تیکت پشتیبانی تشدید شد، مسابقه شروع شد — همان‌جا با یک Idempotency-Key اتاق بسازید تا retry هرگز اتاق دوبله نسازد.
  • ۲ — برای هر شرکت‌نده و هر جلسه، توکن ضرب کنید. درست قبل از ورود، از بک‌اند.
  • ۳ — فرانت‌اند با توکن وصل شود. توکن و wsUrl را از بک‌اند خودتان بگیرید و به SDK بدهید.
  • ۴ — جلسه که تمام شد، اتاق را پایان دهید. DELETE /v1/rooms/{roomId} همه را قطع می‌کند، توکن‌های جدید را رد می‌کند و ورود مجدد را می‌بندد (وضعیت: ended یا با sweeper: expired).
create-room.js (your backend)
async function ensureRoom(appointmentId) {
  const res = await fetch('https://api.videorayan.ir/v1/rooms', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.VIDEORAYAN_KEY}`,  // backend only
      'Content-Type': 'application/json',
      'Idempotency-Key': `apt-${appointmentId}`  // same key → same room
    },
    body: JSON.stringify({
      externalId: appointmentId,  // your correlation ID
      maxParticipants: 3,
      expiresInSeconds: 3600      // 1-hour window
    })
  });
  if (!res.ok) throw new Error('room create failed: ' + res.status);
  return res.json();  // { roomId, status, ... }
}
mint-token.js (your backend)
async function joinAs(roomId, user) {
  const res = await fetch(`https://api.videorayan.ir/v1/rooms/${roomId}/tokens`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.VIDEORAYAN_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      identity: user.id,            // unique per room
      name: user.name,
      role: user.isHost ? 'host' : 'guest',
      ttlSeconds: 600
    })
  });
  return res.json();  // { token, wsUrl, identity, expiresAt }
}
در اتصال مجدد، توکن تازه ضرب کنید. اگر کاربر وسط تماس صفحه را refresh کند، توکن قبلی معمولاً هنوز معتبر است — اما هرگز توکن را بین جلسات cache نکنید. به‌ازای هر ورود، یک توکن.
امنیت

رسانه‌هایتان را جدی گرفته‌ایم

چند تمرین ساده سمت شما، مدل امنیتی پلتفرم را کامل می‌کند.

کلیدها فقط سمت سرور

کلیدهای اجاره‌ای rtck_… هرگز نباید در کد فرانت‌اند، باندل موبایل یا گیت ظاهر شوند. اگر لو رفت، از طریق اپراتور بچرخانیدش (rotate).

رمز اتاق سمت سرور بررسی می‌شود

اتاق‌های خصوصیِ عمومی، رمز را هنگام صدور توکن بررسی می‌کنند — کلاینت نمی‌تواند دورش بزند. خطا هم قطعی است: 403 wrong_password.

404 ضد-کاوش

دسترسی بین‌اجاره‌ای همان پاسخ «وجود ندارد» را می‌دهد: 404 room_not_found. UIای نسازید که به تمایز این دو وابسته باشد.

انتقال رمزنگاری‌شده

رسانه با DTLS-SRTP بین شرکت‌کنندگان و SFU خودمیزبان محافظت می‌شود و سیگنالینگ روی WSS می‌رود. E2EE در نسخهٔ اول فعال نیست — به کاربران چنین ادعایی نکنید.

محدودیت نرخ، دوست شماست: ۱۲۰ درخواست در دقیقه به‌ازای هر IP. پاسخ اتاق‌ها را cache کنید؛ اتاقی را که خودتان ساخته‌اید polling نکنید.
عیب‌یابی

خطاهای واقعی و راه‌حلشان

بدنه‌های خطا قطعی‌اند — روی فیلد error در JSON شاخه بزنید.

نشانهعلتراه‌حل
429 هنگام ساخت اتاقسقف نرخ هر IP پر شده (NAT مشترک، تست بار)بک‌آف نمایی؛ برای تست بار از اپراتور کلید اجاره‌ای اختصاصی بخواهید
403 روی توکن مهمانرمز اتاق اشتباه یا ناموجوداول اتاق را resolve کنید و وقتی needsPassword true است رمز بگیرید
409 روی توکناتاق پر (سقف) یا پایان‌یافته/منقضی«اتاق پر است / تمام شده» را نشان دهید؛ برای جلسهٔ بعد اتاق تازه بسازید
404 روی resolveلینک بد یا اتاق منقضی (پیش‌فرض ۱۲ ساعت برای اتاق‌های رایگان)اتاق تازه بسازید؛ room_not_found را retryable ندانید
400 روی ساختاعتبارسنجی بدنه رد شده (طول فیلدها، فیلد ناشناخته)بدنهٔ invalid_input را طبق مستندات اصلاح کنید
توکن محلی کار می‌کند، در تولید نهتوکن برای اتاق دیگری ضرب شده یا در مسیر منقضی شدهبه‌ازای هر ورود ضرب کنید و فوراً مصرفش کنید
رسانه وصل است ولی صدای یک نفر نیستمیکروفن مجوز نداده یا در سطح OS بی‌صدا استخطاهای getUserMedia را بررسی کنید؛ پلتفرم در هر ورود صدا را request می‌کند
سوالات متداول

پرسش‌هایی که همه می‌پرسند

برای تست ویدیورایان به کلید API نیاز دارم؟

نه. سطح عمومیِ اتاق‌ها باز است: با یک نام اتاق بسازید، لینک /r/{roomId} را به اشتراک بگذارید و مهمان‌ها با نام نمایشی وارد می‌شوند. کلید فقط برای اتاق‌های اجاره‌ای با نقش و سقف سمت سرور لازم است.

توکن‌های ورود چقدر اعتبار دارند؟

پیش‌فرض حدود ۱۰ دقیقه — زمان دقیق را در فیلد expiresAt پاسخ ببینید. توکن قابل تمدید نیست؛ برای هر جلسه از بک‌اند (یا اندپوینت مهمان برای اتاق‌های رایگان) توکن تازه ضرب کنید.

یک اتاق چند شرکت‌کننده می‌تواند داشته باشد؟

اتاق‌های اجاره‌ای در حال حاضر تا ۳ شرکت‌کننده — و برای کاربردهای واقعی از طریق درخواست منابع قابل افزایش است. اتاق‌های رایگان طبق سیاست رسانه‌ای فعلی سرو می‌شوند.

آیا رسانه رمزنگاری می‌شود؟

بله — همهٔ رسانه با DTLS-SRTP بین شرکت‌کنندگان و SFU خودمیزبان محافظت می‌شود و سیگنالینگ روی WSS اجرا می‌شود. E2EE در نسخهٔ اول فعال نیست.

می‌توانم ویدیورایان را در محصول خودم جاسازی کنم؟

بله. یا به رابط میزبانی‌شدهٔ /r/{roomId} لینک دهید، یا با هر SDK سازگار LiveKit و توکنی که بک‌اند شما ضرب کرده، مستقیم از فرانت‌اند خودتان وصل شوید — هر دو از همان اتاق‌ها استفاده می‌کنند.

وقتی اتاق منقضی شود چه اتفاقی می‌افتد؟

یک sweeper هر ۶۰ ثانیه اتاق‌های منقضی را علامت می‌زند و از سرور رسانه حذف می‌کند، پس توکن‌های کهنه دیگر ورود نمی‌کنند. اتاق‌های رایگان ۱۲ ساعت زنده می‌مانند و چون ساخت با نام idempotent است، ورود بعدی دوباره همان اتاق را می‌سازد — برای جلسهٔ بعدی فقط دوباره سر بزنید.

جامعه و بازخورد

زنده حرف بزنیم — و مسیر را با هم بسازیم

سؤال‌تان در مستندات جواب نگرفت؟ به اتاق اجتماعی بیایید — صدا، تصویر و چتِ مرورگری بدون حساب. هر نکته یا کمبودی هم دیدید، خط بازخورد جلوی ما باز است.

سؤال‌ها جواب گرفت؟ حالا بسازید.

همین حالا یک اتاق رایگان بسازید — کل سطح عمومی باز است، بدون ثبت‌نام.