You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

7.8 KiB

PlugNMeet Webhook Integration - Quick Setup Guide

Overview

This project implements automatic webhook integration with PlugNMeet to handle live session events in real-time.

Features

Room Management

  • Automatically close sessions when room ends
  • Real-time session status updates

Participant Tracking

  • Track when users join/leave sessions
  • Maintain accurate online status

Recording Management

  • Automatically download completed recordings
  • Generate video thumbnails
  • Save to database with metadata

Prerequisites

Required Software

# Install FFmpeg (required for video thumbnail generation)
sudo apt-get update
sudo apt-get install ffmpeg

# Verify installation
ffmpeg -version

Django Settings

Ensure these settings are configured in your settings.py:

# PlugNMeet Configuration
PLUGNMEET_SERVER_URL = "https://your-plugnmeet-server.com"
PLUGNMEET_API_KEY = "your-api-key"
PLUGNMEET_API_SECRET = "your-api-secret"
PLUGNMEET_TIMEOUT = 10.0

# Media files (for recordings)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

PlugNMeet Server Configuration

Configure webhook in your PlugNMeet server settings:

# plugnmeet config.yaml
webhooks:
  - url: "https://your-django-backend.com/api/course/plugnmeet/webhook/"
    events:
      - room_finished
      - participant_joined
      - participant_left
      - end_recording

Webhook Endpoint

URL: https://your-domain.com/api/course/plugnmeet/webhook/

Method: POST

Security: HMAC SHA256 signature verification

Events Handled

1. room_finished

  • Closes the live session
  • Marks all participants as offline
  • Sets ended_at timestamp

2. participant_joined

  • Creates LiveSessionUser entry
  • Sets user as online
  • Records join timestamp

3. participant_left

  • Updates LiveSessionUser entry
  • Sets user as offline
  • Records exit timestamp

4. end_recording

  • Fetches recording from PlugNMeet
  • Downloads recording file
  • Saves to LiveSessionRecording model
  • Generates video thumbnail (if applicable)

Testing

Using the Test Script

# Test room_finished event
python scripts/test_webhook.py room_finished

# Test participant_joined event
python scripts/test_webhook.py participant_joined

# Test participant_left event
python scripts/test_webhook.py participant_left

# Test end_recording event
python scripts/test_webhook.py end_recording

# Dry run (show payload without sending)
python scripts/test_webhook.py room_finished --dry-run

Manual Testing with cURL

#!/bin/bash

# Configuration
SECRET="your-api-secret"
URL="https://your-domain.com/api/course/plugnmeet/webhook/"

# Sample payload
PAYLOAD='{
  "event": "room_finished",
  "room": {
    "identity": "test-room-20240101120000"
  }
}'

# Calculate signature
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" -hex | cut -d' ' -f2)

# Send request
curl -X POST "$URL" \
  -H "Content-Type: application/webhook+json" \
  -H "Hash-Token: $SIGNATURE" \
  -d "$PAYLOAD"

Monitoring

Check Logs

# Django logs
tail -f logs/django.log | grep "PlugNMeet Webhook"

# Specific events
tail -f logs/django.log | grep "end_recording"
tail -f logs/django.log | grep "participant_joined"

Log Messages

[PlugNMeet Webhook] Received webhook request
[PlugNMeet Webhook] Processing event=room_finished
[PlugNMeet Webhook] Session closed - session_id=123 room_id=test-room
[PlugNMeet Webhook] User sessions closed - session_id=123 count=5
[PlugNMeet Webhook] Event processed successfully - event=room_finished

Recording Download Logs

[PlugNMeet Webhook] end_recording - room_id=test-room recording_id=rec_123
[PlugNMeet Webhook] Fetching recording info - recording_id=rec_123
[PlugNMeet Webhook] Getting download token - recording_id=rec_123
[PlugNMeet Webhook] Downloading recording file - recording_id=rec_123
[PlugNMeet Webhook] File downloaded - size=524288000 bytes
[PlugNMeet Webhook] Recording saved - recording_id=456 file=recording.mp4
[PlugNMeet Webhook] Thumbnail generated - recording_id=456

Database Models

CourseLiveSession

{
    'id': 123,
    'course': Course instance,
    'room_id': 'test-room-20240101120000',
    'subject': 'Test Session',
    'started_at': datetime,
    'ended_at': datetime,  # Set by webhook
}

LiveSessionUser

{
    'id': 456,
    'session': CourseLiveSession instance,
    'user': User instance,
    'role': 'participant' or 'moderator',
    'entered_at': datetime,  # Set by webhook
    'exited_at': datetime,   # Set by webhook
    'is_online': True/False,  # Updated by webhook
}

LiveSessionRecording

{
    'id': 789,
    'session': CourseLiveSession instance,
    'title': 'Test Session - Recording',
    'file': FileField,  # Downloaded by webhook
    'file_time': DurationField,
    'recording_type': 'video' or 'voice',
    'thumbnail': ImageField,  # Generated by webhook
    'is_active': True,
}

Troubleshooting

Webhook Not Receiving Events

  1. Check PlugNMeet server configuration
  2. Verify webhook URL is accessible from PlugNMeet server
  3. Check firewall rules
  4. Review PlugNMeet server logs

Signature Verification Failed

  1. Ensure PLUGNMEET_API_SECRET matches PlugNMeet config
  2. Check for extra whitespace in settings
  3. Verify request is coming from PlugNMeet server

Recording Download Failed

  1. Check PlugNMeet server is accessible
  2. Verify recording exists: POST /auth/recording/recordingInfo
  3. Check disk space
  4. Review media directory permissions

Thumbnail Generation Failed

  1. Verify ffmpeg is installed: ffmpeg -version
  2. Check ffmpeg has permissions to read/write temp files
  3. Review video file format (mp4, webm, mkv supported)
  4. Check server resources (CPU, memory)

File Upload Errors

# Check media directory permissions
ls -la media/
chmod -R 755 media/

# Check Django settings
python manage.py shell
>>> from django.conf import settings
>>> print(settings.MEDIA_ROOT)
>>> print(settings.MEDIA_URL)

Performance Considerations

Disk Space

  • Monitor disk space for recordings
  • Implement cleanup policy for old recordings
  • Consider using external storage (S3, MinIO)

Processing Time

  • Large recordings may take time to download
  • Thumbnail generation adds 1-3 seconds per video
  • Consider async processing for large files (Celery)

Concurrent Webhooks

  • Django handles webhooks synchronously by default
  • For high-traffic scenarios, consider:
    • Queue system (Celery, RQ)
    • Async views (Django 4.1+)
    • Horizontal scaling

Migration from Polling

The old polling approach has been deprecated and commented out:

# OLD (Deprecated) - in apps/course/views/course.py
# def _sync_room_status_with_plugnmeet(self, course: Course):
#     client = PlugNMeetClient()
#     response = client.is_room_active(active_session.room_id)
#     ...

# NEW (Webhook-based)
# Room status is automatically updated via webhooks
# No polling required

Security Best Practices

  1. Signature Verification: Always enabled (HMAC SHA256)
  2. HTTPS Only: Webhook endpoint requires HTTPS
  3. IP Whitelist: Consider restricting to PlugNMeet server IP
  4. Rate Limiting: Implement rate limiting on webhook endpoint
  5. Input Validation: All webhook payloads are validated
  6. Error Handling: Comprehensive error handling and logging

Support

For issues or questions:

  1. Check logs: logs/django.log
  2. Review documentation: docs/plugnmeet_webhook.md
  3. Test with script: scripts/test_webhook.py
  4. Check PlugNMeet docs: https://www.plugnmeet.org/docs

References