BackendJunsen / app /services /processor.py
2nzi's picture
update app
16c970a verified
from firebase_admin import firestore
import os
from ..core.config import settings
from ..core.firebase import db
from huggingface_hub import HfApi, create_repo
import tempfile
from .video_processing.hf_upload import HFUploader
from .video_processing.compression import compress_video
from .video_processing.scene_detection import SceneDetector
from .video_processing.scene_classifier import SceneClassifier
from .video_processing.clip_generator import ClipGenerator
from .video_processing.scrape_hf import extract_video_urls
import time
async def process_video(video_uuid: str, content: bytes, user_id: str, sport_id: str):
temp_files = []
try:
video_ref = db.collection('videos').document(video_uuid)
video_data = video_ref.get().to_dict()
hf_uploader = HFUploader()
sport_id = video_data['sport_id']
# Ensure folder structure exists
hf_uploader.ensure_folder_structure(sport_id)
# Create temp files
temp_raw_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
temp_compressed_file = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
temp_files.extend([temp_raw_file.name, temp_compressed_file.name])
# Write raw video and close file
temp_raw_file.write(content)
temp_raw_file.close()
# Compress video
compress_video(temp_raw_file.name, temp_compressed_file.name)
temp_compressed_file.close()
# Detect scenes
scene_detector = SceneDetector()
scene_classifier = SceneClassifier()
scenes_data = scene_detector.detect_scenes(temp_compressed_file.name)
# Classify each scene
for scene in scenes_data["scenes"]:
classification = scene_classifier.classify_scene(
temp_compressed_file.name,
scene
)
scene["recognized_sport"] = classification["recognized_sport"]
scene["confidence"] = classification["confidence"]
# Generate clips
clip_generator = ClipGenerator()
generated_clips = clip_generator.generate_clips(
temp_compressed_file.name,
scenes_data["scenes"],
sport_id
)
# Create and upload clips
final_clips_data = []
user_ref = db.collection("users").document(user_id)
user_data = user_ref.get().to_dict() or {"clips": []}
if "clips" not in user_data:
user_data["clips"] = []
# Upload both versions first
raw_path = f"{sport_id}/raw/{video_uuid}.mp4"
compressed_path = f"{sport_id}/compressed/{video_uuid}.mp4"
hf_uploader.upload_video(temp_raw_file.name, raw_path)
hf_uploader.upload_video(temp_compressed_file.name, compressed_path)
# Attendre que HF indexe les fichiers
time.sleep(3)
# Construire l'URL de base pour le scraping
base_viewer_url = f"https://huggingface.co/datasets/{hf_uploader.repo_id}/viewer/default/files"
# Récupérer toutes les URLs
max_retries = 3
raw_url = None
compressed_url = None
for attempt in range(max_retries):
try:
urls = extract_video_urls(base_viewer_url)
# Chercher les URLs correspondantes
raw_url = next((url for url in urls if raw_path in url), None)
compressed_url = next((url for url in urls if compressed_path in url), None)
if raw_url and compressed_url:
print(f"[SUCCESS] URLs trouvées à la tentative {attempt + 1}")
break
print(f"[RETRY] Tentative {attempt + 1}/{max_retries}")
time.sleep(2)
except Exception as e:
print(f"[ERROR] Tentative {attempt + 1} échouée: {str(e)}")
if attempt == max_retries - 1:
raise e
time.sleep(2)
# Process clips
for clip_data in generated_clips:
clip_number = clip_data["clip_number"]
clip_file_path = clip_data["file_path"]
temp_files.append(clip_file_path)
clip_path = f"{sport_id}/clips/{video_uuid}_clip_{clip_number}.mp4"
hf_uploader.upload_video(clip_file_path, clip_path)
# Attendre et scraper l'URL du clip
time.sleep(2)
clip_url = None
for attempt in range(max_retries):
try:
urls = extract_video_urls(base_viewer_url)
clip_url = next((url for url in urls if clip_path in url), None)
if clip_url:
break
time.sleep(2)
except Exception:
if attempt == max_retries - 1:
raise
time.sleep(2)
if clip_url:
final_clips_data.append({
"clip_id": f"{video_uuid}_clip_{clip_number}",
"video_uuid": video_uuid,
"url": clip_url,
"duration": clip_data["duration"],
"confidence": clip_data["confidence"],
"segments": clip_data["segments"]
})
clip_ref = db.collection("clips").document(f"{video_uuid}_clip_{clip_number}")
clip_ref.set({
"clip_id": f"{video_uuid}_clip_{clip_number}",
"sport_id": sport_id,
"url": clip_url,
"duration": clip_data["duration"]
})
# Update user data
user_ref.set(user_data)
# Update video data with scraped URLs
update_data = {
"scenes": scenes_data,
"clips": final_clips_data,
"clips_count": len(final_clips_data),
"status": "ready",
"last_updated": firestore.SERVER_TIMESTAMP
}
if raw_url:
update_data["raw_video_url"] = raw_url
if compressed_url:
update_data["compressed_video_url"] = compressed_url
video_ref.update(update_data)
except Exception as e:
print(f"Erreur lors du traitement de la vidéo {video_uuid}: {str(e)}")
video_ref.update({"status": "error", "error": str(e)})
finally:
# Clean up temp files
for temp_file in temp_files:
try:
if os.path.exists(temp_file):
os.unlink(temp_file)
except Exception as e:
print(f"[WARNING] Erreur lors de la suppression du fichier temporaire {temp_file}: {str(e)}")