277 lines
8.5 KiB
Python
277 lines
8.5 KiB
Python
"""
|
||
Сериализаторы для видеоконференций.
|
||
"""
|
||
from rest_framework import serializers
|
||
from .models import VideoRoom, VideoParticipant, VideoCallLog, ScreenRecording
|
||
from apps.schedule.serializers import LessonSerializer
|
||
from apps.users.serializers import UserSerializer
|
||
|
||
|
||
class VideoParticipantSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор участника видео."""
|
||
|
||
user = UserSerializer(read_only=True)
|
||
duration = serializers.SerializerMethodField()
|
||
|
||
class Meta:
|
||
model = VideoParticipant
|
||
fields = [
|
||
'id',
|
||
'user',
|
||
'is_connected',
|
||
'is_audio_enabled',
|
||
'is_video_enabled',
|
||
'is_screen_sharing',
|
||
'joined_at',
|
||
'left_at',
|
||
'duration',
|
||
'reconnection_count'
|
||
]
|
||
read_only_fields = [
|
||
'joined_at',
|
||
'left_at',
|
||
'reconnection_count'
|
||
]
|
||
|
||
def get_duration(self, obj):
|
||
"""Получить длительность в секундах."""
|
||
return obj.total_duration
|
||
|
||
|
||
class VideoRoomSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор видеокомнаты."""
|
||
|
||
lesson = LessonSerializer(read_only=True)
|
||
mentor = UserSerializer(read_only=True)
|
||
client = UserSerializer(read_only=True)
|
||
participants = VideoParticipantSerializer(many=True, read_only=True)
|
||
actual_duration = serializers.IntegerField(read_only=True)
|
||
is_active = serializers.BooleanField(read_only=True)
|
||
|
||
class Meta:
|
||
model = VideoRoom
|
||
fields = [
|
||
'id',
|
||
'room_id',
|
||
'lesson',
|
||
'mentor',
|
||
'client',
|
||
'status',
|
||
'started_at',
|
||
'ended_at',
|
||
'duration',
|
||
'actual_duration',
|
||
'is_recording',
|
||
'recording_url',
|
||
'is_active',
|
||
'participants',
|
||
'quality_rating',
|
||
'quality_issues',
|
||
'created_at'
|
||
]
|
||
read_only_fields = [
|
||
'room_id',
|
||
'started_at',
|
||
'ended_at',
|
||
'duration',
|
||
'created_at'
|
||
]
|
||
|
||
|
||
class VideoRoomCreateSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор создания видеокомнаты."""
|
||
|
||
lesson_id = serializers.IntegerField(write_only=True)
|
||
|
||
class Meta:
|
||
model = VideoRoom
|
||
fields = [
|
||
'lesson_id',
|
||
'is_recording',
|
||
'max_participants'
|
||
]
|
||
|
||
def validate_lesson_id(self, value):
|
||
"""Проверка занятия."""
|
||
from apps.schedule.models import Lesson
|
||
|
||
try:
|
||
lesson = Lesson.objects.get(id=value)
|
||
except Lesson.DoesNotExist:
|
||
raise serializers.ValidationError('Занятие не найдено')
|
||
|
||
# Проверяем что комната еще не создана
|
||
if hasattr(lesson, 'video_room'):
|
||
raise serializers.ValidationError('Видеокомната для этого занятия уже существует')
|
||
|
||
# Проверяем что занятие запланировано или в процессе (не отменено)
|
||
if lesson.status == 'cancelled':
|
||
raise serializers.ValidationError('Нельзя создать видеокомнату для отмененного занятия')
|
||
|
||
return value
|
||
|
||
def create(self, validated_data):
|
||
"""Создание видеокомнаты."""
|
||
from apps.schedule.models import Lesson
|
||
|
||
lesson_id = validated_data.pop('lesson_id')
|
||
lesson = Lesson.objects.get(id=lesson_id)
|
||
|
||
video_room = VideoRoom.objects.create(
|
||
lesson=lesson,
|
||
mentor=lesson.mentor,
|
||
client=lesson.client,
|
||
**validated_data
|
||
)
|
||
|
||
return video_room
|
||
|
||
|
||
class VideoRoomStartSerializer(serializers.Serializer):
|
||
"""Сериализатор начала видеозвонка."""
|
||
|
||
def validate(self, attrs):
|
||
"""Валидация."""
|
||
room = self.instance
|
||
|
||
if room.status != 'waiting':
|
||
raise serializers.ValidationError('Комната уже начата или завершена')
|
||
|
||
return attrs
|
||
|
||
def save(self):
|
||
"""Начать звонок."""
|
||
self.instance.start()
|
||
return self.instance
|
||
|
||
|
||
class VideoRoomEndSerializer(serializers.Serializer):
|
||
"""Сериализатор завершения видеозвонка."""
|
||
|
||
quality_rating = serializers.IntegerField(
|
||
min_value=1,
|
||
max_value=5,
|
||
required=False,
|
||
help_text='Оценка качества связи от 1 до 5'
|
||
)
|
||
quality_issues = serializers.CharField(
|
||
required=False,
|
||
allow_blank=True,
|
||
help_text='Описание проблем с качеством'
|
||
)
|
||
|
||
def validate(self, attrs):
|
||
"""Валидация."""
|
||
room = self.instance
|
||
|
||
if room.status != 'active':
|
||
raise serializers.ValidationError('Комната не активна')
|
||
|
||
return attrs
|
||
|
||
def save(self):
|
||
"""Завершить звонок."""
|
||
room = self.instance
|
||
room.end()
|
||
|
||
# Обновляем качество если указано
|
||
if 'quality_rating' in self.validated_data:
|
||
room.quality_rating = self.validated_data['quality_rating']
|
||
if 'quality_issues' in self.validated_data:
|
||
room.quality_issues = self.validated_data['quality_issues']
|
||
|
||
room.save()
|
||
return room
|
||
|
||
|
||
class VideoCallLogSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор лога видеозвонка."""
|
||
|
||
room = VideoRoomSerializer(read_only=True)
|
||
|
||
class Meta:
|
||
model = VideoCallLog
|
||
fields = [
|
||
'id',
|
||
'room',
|
||
'total_participants',
|
||
'total_duration',
|
||
'average_bitrate',
|
||
'packet_loss_rate',
|
||
'average_jitter',
|
||
'connection_issues',
|
||
'audio_issues',
|
||
'video_issues',
|
||
'metadata',
|
||
'created_at'
|
||
]
|
||
read_only_fields = '__all__'
|
||
|
||
|
||
class ScreenRecordingSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор записи видео."""
|
||
|
||
room_id = serializers.UUIDField(source='room.room_id', read_only=True)
|
||
lesson_title = serializers.CharField(source='room.lesson.title', read_only=True)
|
||
is_expired = serializers.BooleanField(read_only=True)
|
||
|
||
class Meta:
|
||
model = ScreenRecording
|
||
fields = [
|
||
'id',
|
||
'room_id',
|
||
'lesson_title',
|
||
'file_path',
|
||
'file_size',
|
||
'duration',
|
||
'url',
|
||
'status',
|
||
'is_public',
|
||
'is_expired',
|
||
'expires_at',
|
||
'created_at',
|
||
'processed_at'
|
||
]
|
||
read_only_fields = [
|
||
'file_path',
|
||
'file_size',
|
||
'duration',
|
||
'status',
|
||
'created_at',
|
||
'processed_at'
|
||
]
|
||
|
||
|
||
class ScreenRecordingCreateSerializer(serializers.Serializer):
|
||
"""Сериализатор создания записи."""
|
||
|
||
room_id = serializers.UUIDField()
|
||
|
||
def validate_room_id(self, value):
|
||
"""Проверка комнаты."""
|
||
try:
|
||
room = VideoRoom.objects.get(room_id=value)
|
||
except VideoRoom.DoesNotExist:
|
||
raise serializers.ValidationError('Комната не найдена')
|
||
|
||
# Проверяем что комната активна
|
||
if not room.is_active:
|
||
raise serializers.ValidationError('Комната не активна')
|
||
|
||
# Проверяем что запись включена
|
||
if not room.is_recording:
|
||
raise serializers.ValidationError('Запись не включена для этой комнаты')
|
||
|
||
return value
|
||
|
||
def create(self, validated_data):
|
||
"""Создание записи."""
|
||
room = VideoRoom.objects.get(room_id=validated_data['room_id'])
|
||
|
||
recording = ScreenRecording.objects.create(
|
||
room=room,
|
||
status='processing'
|
||
)
|
||
|
||
return recording
|