# گزارش ادغام رکوردر با سیستم PlugNMeet و Django این گزارش شامل تمام مراحل فنی طی شده جهت راه‌اندازی، اتصال، رفع باگ و بهینه‌سازی رکوردر جلسات آنلاین (`plugNmeet-recorder`) و ادغام کامل آن با پنل مدیریتی جنگو است. --- ## ۱. راه‌اندازی و شبیه‌سازی محلی (Cloning & Docker Setup) برای بالا آوردن سیستم ضبط به صورت ایزوله و ارتباط آن با سرور کلاس‌ها، کارهای زیر انجام شد: * **شبیه‌سازی رکوردر**: مخزن رسمی رکوردر در مسیر موازی پروژه تحت عنوان `plugNmeet-recorder` کلون گردید. * **پیکربندی شبکه (Docker Compose)**: در فایل `docker-compose.yml` مربوط به سرور ویدیو کنفرانس، کانتینر رکوردر به کانتینرهای دیگر متصل شد: * به کانتینرها اجازه دسترسی به شبکه اشتراکی پروژه (`imam-javad_backend_imam-javad`) داده شد تا رکوردر بتواند به وب‌هوک جنگو و سرور nats متصل شود. * با استفاده از `extra_hosts` آی‌پی دامنه کلاس‌ها به گیت‌وی کانتینرها مپ شد تا مرورگر داخلی رکوردر (Chrome بدون واسط گرافیکی) بتواند بدون مشکل با دامنه کلاس کار کند: ```yaml extra_hosts: - "meet.imamjavad.online:host-gateway" ``` * تنظیم ولوم مشترک برای فایل‌های ذخیره‌شده ضبط (`plugnmeet-recordings`) صورت گرفت. --- ## ۲. تنظیمات رکوردر (`recorder_config.yaml`) پیکربندی فایل تنظیمات رکوردر برای سازگاری کامل با سیستم محلی به شرح زیر انجام شد: * تنظیم شناسه رکوردر به `node_01` و حالت اجرایی به `both` (انجام همزمان ضبط زنده و فشرده‌سازی پس از اتمام ضبط). * اتصال به وب‌سرویس nats از طریق: ```yaml nats_info: nats_urls: - "nats://plugnmeet-nats:4222" ``` * تنظیم اعتبارسنجی اتصال به API در بخش `plugNmeet_info` با استفاده از `api_key` و `api_secret` مشترک و هماهنگ‌شده با جنگو. * آدرس‌دهی فایل خروجی رکوردر به پوشه اشتراکی `/recording_files`. --- ## ۳. پیاده‌سازی گیرنده وب‌هوک زنده (Django Webhook) در فایل [webhook.py](file:///f:/WORK/CODE/WORK/imam-javad/backend/apps/course/views/webhook.py)، تغییرات اساسی جهت دریافت اطلاعات فایل نهایی و وضعیت کاربران اعمال شد: ### الف) رفع باگ مسیر رویداد ضبط (Webhook Routing) سرور PlugNMeet رویداد اتمام ضبط و آماده‌سازی فایل فشرده‌شده را با کلید `recording_proceeded` (حروف کوچک) ارسال می‌کرد. مسیردهی متناظر در جنگو اصلاح شد تا متد پردازشی درست فراخوانی گردد. ### ب) اعتبارسنجی دوگانه امنیت (Signature Verification) بررسی امنیتی پیام‌های دریافتی مجهز به دو لایه شد: 1. **اعتبارسنجی JWT (استاندارد PlugNMeet)**: بررسی صحت امضا با توکن رمزنگاری‌شده با الگوریتم HS256 و کلید `PLUGNMEET_API_SECRET`. 2. **بررسی پشتیبان HMAC-SHA256**: برای سناریوهای تستی و کلاینت‌های قدیمی که توکن JWT خام ارسال می‌کنند. ### ج) دانلود و پردازش خودکار فایل ویدیویی درون متد `_handle_recording_proceeded` فرآیند زیر پیاده شد: 1. **دانلود امن**: توکن موقت دانلود از API دریافت شده و فایل ویدیویی از آدرس وب‌سرویس دانلود و در حافظه موقت سیستم ذخیره می‌گردد. 2. **محاسبه مدت زمان ویدیو (Video Duration)**: با اجرای ابزار سیستم `ffprobe` در پس‌زمینه، طول دقیق ویدیو به صورت پویا استخراج می‌شود. 3. **ثبت در پایگاه داده**: فایل در مدل `LiveSessionRecording` ذخیره می‌گردد. 4. **تولید خودکار کاور تصویر (Thumbnail)**: با استفاده از دستورات `ffmpeg` فریمی در ثانیه اول ویدیو استخراج و تغییر سایز داده شده و به عنوان پیش‌نمایش در فیلد مربوطه ذخیره می‌شود. --- ## ۴. ثبت خودکار درس در دوره آموزشی (Django Signals) پس از ثبت فایل ضبط شده، یک پروسه اتوماتیک در فایل [signals.py](file:///f:/WORK/CODE/WORK/imam-javad/backend/apps/course/signals.py) از طریق سیگنال `post_save` روی مدل `LiveSessionRecording` فعال می‌شود: 1. **جلوگیری از ثبت تکراری**: با فیلتر کردن نام فایلی که ثبت می‌شود، تضمین می‌گردد وب‌هوک‌های همزمان یا ذخیره‌سازی‌های مجدد باعث ایجاد درس‌های تکراری نشوند. 2. **ساخت هوشمند چپتر**: تاریخ ضبط جلسه استخراج شده و به عنوان نام چپتر (به فرمت `YYYY-MM-DD`) ثبت می‌شود. در صورتی که این چپتر از قبل برای این دوره وجود داشته باشد، از همان چپتر استفاده می‌شود. 3. **نام‌گذاری خودکار درس‌ها (Part n)**: * تعداد درس‌های موجود در **همان چپتر مشخص** شمرده می‌شود. * بر اساس فرمول `تعداد درس‌ها + ۱` نام درس به عنوان بخش بعدی (مثلا `Part 4` در صورتی که ۳ درس در چپتر باشد) تعیین می‌شود. 4. **ساخت شیء درس و انتساب به دوره**: آبجکت `Lesson` ساخته شده و به مدل واسط `CourseLesson` مرتبط می‌گردد. --- ## ۵. سیستم پایش حضور و غیاب مطمئن (Fail-safe Participant Tracking) وب‌هوک‌های LiveKit مربوط به ملحق شدن و خروج کاربران در زمان تست‌های محلی ممکن است به دلیل مسائل شبکه یا فایروال به درستی کار نکنند. به همین منظور مکانیزم پشتیبان (Fail-safe) زیر طراحی شد: * **ثبت زودهنگام حضور (در [live_session.py](file:///f:/WORK/CODE/WORK/imam-javad/backend/apps/course/views/live_session.py))**: در متد `CourseLiveSessionTokenAPIView.post` که توکن دسترسی برای کاربران تولید می‌کند، درست قبل از ورود کاربر به کلاس، یک رکورد حضور در مدل `LiveSessionUser` با وضعیت آنلاین ایجاد/بروزرسانی می‌شود. * **ثبت خودکار خروج در زمان بسته شدن کلاس**: در متد پایش فعالِ کلاس (`_verify_room_is_active`) و متد دریافت اتمام رویداد وب‌هوک، به محض اینکه سرور تشخیص دهد کلاس به اتمام رسیده است، وضعیت تمام کاربران حاضر در آن جلسه به صورت خودکار آفلاین (`is_online=False`) شده و زمان خروج آن‌ها در فیلد `exited_at` ثبت می‌گردد. * **نادیده گرفتن ربات‌های سیستمی**: رویدادهای کاربرانی نظیر `RECORDER_BOT` (که مرورگر رکوردر است) به دلیل عدم همخوانی با شناسه‌های کاربری عددی از محاسبات پایگاه داده فیلتر و نادیده گرفته می‌شوند تا پایگاه داده با خطای تبدیل نوع (Type Casting) روبرو نشود. --- > [!TIP] > برای اجرای تست سناریوها در محیط توسعه محلی بدون نیاز به اجرای دستی مرورگرها، می‌توانید از اسکریپت به‌روزشده `backend/scripts/test_webhook.py` همراه با شناسه رویدادهای مختلف نظیر `RECORDING_PROCEEDED` استفاده نمایید.