import gradio as gr import tempfile import os import json import shutil import base64 try: from moviepy.editor import VideoFileClip MOVIEPY_AVAILABLE = True except ImportError: print("MoviePy не установлен, используем альтернативный метод") MOVIEPY_AVAILABLE = False # Глобальная переменная для хранения созданных уроков current_lesson_dir = None def add_segment(lecture_video, correct_video, wrong_video, option1_text, option2_text, correct_option, segments_state): """Добавляет сегмент: видео лекции + видео реакций + текст вариантов""" if lecture_video is None or correct_video is None or wrong_video is None: return segments_state, "⚠️ Загрузите все три видео (лекция, правильная реакция, неправильная реакция)", None, None, None if not option1_text or not option2_text: return segments_state, "⚠️ Введите оба варианта ответа", None, None, None if correct_option is None: return segments_state, "⚠️ Выберите правильный вариант", None, None, None # Получаем длительность лекции try: if MOVIEPY_AVAILABLE: clip = VideoFileClip(lecture_video) duration = clip.duration clip.close() else: # Альтернативный метод через subprocess import subprocess result = subprocess.run( ['ffprobe', '-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', lecture_video], stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) duration = float(result.stdout) except Exception as e: print(f"Ошибка получения длительности: {e}") duration = 10 # Значение по умолчанию # Сохраняем оригинальные пути new_segment = { 'lecture_path': lecture_video, 'correct_path': correct_video, 'wrong_path': wrong_video, 'options': [option1_text, option2_text], 'correct_answer': 0 if correct_option == "Вариант 1" else 1, # Переименовали ключ 'duration': duration } segments_state.append(new_segment) info = f"✅ **Всего сегментов: {len(segments_state)}**\n\n" for i, seg in enumerate(segments_state, 1): info += f"**Сегмент {i}:** ({seg['duration']:.1f} сек)\n" info += f"- 🎯 Вариант 1: {seg['options'][0]}\n" info += f"- 🎯 Вариант 2: {seg['options'][1]}\n" info += f"- ✅ Правильный: Вариант {seg['correct_answer'] + 1}\n\n" # Очищаем поля ввода return segments_state, info, None, None, None def create_lesson(segments_state): """Подготавливает урок - копирует файлы и создает метаданные""" global current_lesson_dir if not segments_state: return "⚠️ Нет добавленных сегментов", None # Создаем временную директорию для урока lesson_dir = tempfile.mkdtemp(prefix="lesson_") current_lesson_dir = lesson_dir # Сохраняем глобально timestamps = [] for i, seg in enumerate(segments_state): # Копируем видео в директорию урока lecture_new = os.path.join(lesson_dir, f"lecture_{i}.mp4") correct_new = os.path.join(lesson_dir, f"correct_{i}.mp4") wrong_new = os.path.join(lesson_dir, f"wrong_{i}.mp4") # Копируем файлы shutil.copy2(seg['lecture_path'], lecture_new) shutil.copy2(seg['correct_path'], correct_new) shutil.copy2(seg['wrong_path'], wrong_new) timestamps.append({ 'index': i, 'lecture_file': f"lecture_{i}.mp4", # Переименовали ключи для ясности 'correct_file': f"correct_{i}.mp4", 'wrong_file': f"wrong_{i}.mp4", 'duration': seg['duration'], 'options': seg['options'], 'correct_answer': seg['correct_answer'] # Здесь храним индекс правильного ответа }) # Сохраняем метаданные metadata = { 'timestamps': timestamps, 'total_segments': len(segments_state), 'lesson_dir': lesson_dir # Сохраняем путь к директории } meta_path = os.path.join(lesson_dir, 'metadata.json') with open(meta_path, 'w', encoding='utf-8') as f: json.dump(metadata, f, ensure_ascii=False, indent=2) total_duration = sum(seg['duration'] for seg in segments_state) return (f"✅ Урок создан!\n- Всего сегментов: {len(segments_state)}\n- Примерная длительность: {total_duration:.1f} сек\n- Путь: {lesson_dir}", meta_path) def generate_player_html(meta_path): """Генерирует HTML плеер с интерактивными кнопками""" global current_lesson_dir if not meta_path or not os.path.exists(meta_path): return "
⚠️ Сначала создайте урок!
" with open(meta_path, 'r', encoding='utf-8') as f: metadata = json.load(f) # Используем сохраненную директорию lesson_dir = metadata.get('lesson_dir', current_lesson_dir) if not lesson_dir or not os.path.exists(lesson_dir): return "⚠️ Файлы урока не найдены. Создайте урок заново.
" # Конвертируем все видео в base64 video_data = {} for segment in metadata['timestamps']: idx = segment['index'] # Используем правильные ключи для имен файлов lecture_path = os.path.join(lesson_dir, segment['lecture_file']) correct_path = os.path.join(lesson_dir, segment['correct_file']) wrong_path = os.path.join(lesson_dir, segment['wrong_file']) try: with open(lecture_path, 'rb') as f: video_data[f'lecture_{idx}'] = base64.b64encode(f.read()).decode() with open(correct_path, 'rb') as f: video_data[f'correct_{idx}'] = base64.b64encode(f.read()).decode() with open(wrong_path, 'rb') as f: video_data[f'wrong_{idx}'] = base64.b64encode(f.read()).decode() except Exception as e: print(f"Ошибка чтения файла: {e}") return f"⚠️ Ошибка загрузки видео: {str(e)}
" # Создаем структуру данных для JavaScript segments_json = json.dumps([{ 'index': seg['index'], 'duration': seg['duration'], 'options': seg['options'], 'correct': seg['correct_answer'] # Используем правильный ключ } for seg in metadata['timestamps']], ensure_ascii=False) # Создаем словарь с видео для JavaScript videos_json = json.dumps(video_data) html = f"""