Files changed (1) hide show
  1. app.py +99 -0
app.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os, requests, json, subprocess
3
+ import boto3
4
+ from groq import Groq
5
+ import google.generativeai as genai
6
+
7
+ # SECRETS HF - Settings > Variables and Secrets
8
+ GROQ_KEY = os.getenv("GROQ_API_KEY")
9
+ GEMINI_KEY = os.getenv("GEMINI_API_KEY")
10
+ R2_ACCESS = os.getenv("R2_ACCESS")
11
+ R2_SECRET = os.getenv("R2_SECRET")
12
+ R2_BUCKET = os.getenv("R2_BUCKET")
13
+ R2_BUCKET_URL = os.getenv("R2_BUCKET_URL") # https://xxx.r2.cloudflarestorage.com
14
+ R2_PUBLIC = os.getenv("R2_PUBLIC_URL") # https://pub-xxx.r2.dev
15
+ LWS_WEBHOOK = "https://opus.dostodgroup.com/webhook.php?token=change_moi_12345_opus"
16
+
17
+ genai.configure(api_key=GEMINI_KEY)
18
+ groq_client = Groq(api_key=GROQ_KEY)
19
+
20
+ def upload_r2(local_path, remote_name):
21
+ s3 = boto3.client('s3',
22
+ endpoint_url=R2_BUCKET_URL,
23
+ aws_access_key_id=R2_ACCESS,
24
+ aws_secret_access_key=R2_SECRET
25
+ )
26
+ s3.upload_file(local_path, R2_BUCKET, remote_name)
27
+ return f"{R2_PUBLIC}/{remote_name}"
28
+
29
+ def factory(job_id, video_url):
30
+ try:
31
+ tmp_in = f"/tmp/{job_id}.mp4"
32
+ gr.Info(f"Download {video_url}...")
33
+ with requests.get(video_url, stream=True, timeout=120) as r:
34
+ r.raise_for_status()
35
+ with open(tmp_in, 'wb') as f:
36
+ for chunk in r.iter_content(chunk_size=1024*1024):
37
+ if chunk: f.write(chunk)
38
+
39
+ gr.Info("Transcription Whisper...")
40
+ from faster_whisper import WhisperModel
41
+ model = WhisperModel("small", device="cpu", compute_type="int8")
42
+ segments, _ = model.transcribe(tmp_in, language="fr")
43
+ full_text = " ".join([s.text for s in segments])[:8000]
44
+
45
+ if not full_text.strip():
46
+ return "❌ Transcription vide"
47
+
48
+ gr.Info("Analyse virale Groq...")
49
+ prompt = f"""Tu es Opus.pro. Trouve 10 clips viraux 30-60s max score viral.
50
+ Format JSON STRICT sans texte autour, juste le tableau: [{{"start":12.5,"end":45.2,"title":"Hook choc","score":92}}]
51
+ Transcription: {full_text}"""
52
+
53
+ comp = groq_client.chat.completions.create(
54
+ model="llama-3.3-70b-versatile",
55
+ messages=[{"role":"user","content":prompt}],
56
+ temperature=0.7
57
+ )
58
+ txt = comp.choices[0].message.content.replace("```json","").replace("```","").strip()
59
+ clips = json.loads(txt)
60
+
61
+ final_for_lws = []
62
+ gr.Info(f"{len(clips)} clips detectes, rendu 1080p...")
63
+ for i, c in enumerate(clips[:10]):
64
+ out = f"/tmp/{job_id}_clip{i+1}_1080p.mp4"
65
+ cmd = [
66
+ "ffmpeg","-ss",str(c['start']),"-to",str(c['end']),"-i",tmp_in,
67
+ "-vf","crop=1080:1920:(in_w-1080)/2:0,scale=1080:1920:flags=lanczos",
68
+ "-c:v","libx264","-crf","18","-preset","ultrafast","-c:a","aac","-b:a","128k","-y",out
69
+ ]
70
+ subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
71
+
72
+ if os.path.exists(out) and os.path.getsize(out) > 10000:
73
+ remote = f"finales/{job_id}_clip{i+1}_1080p.mp4"
74
+ r2_url = upload_r2(out, remote)
75
+ final_for_lws.append({
76
+ "url": r2_url,
77
+ "title": c.get('title',''),
78
+ "score": c.get('score',0)
79
+ })
80
+
81
+ # Envoie à LWS
82
+ gr.Info(f"Envoi {len(final_for_lws)} clips vers LWS...")
83
+ requests.post(LWS_WEBHOOK, json={"job_id": job_id, "clips": final_for_lws}, timeout=60)
84
+
85
+ return f"✅ {len(final_for_lws)} clips 1080p envoyés sur opus.dostodgroup.com/videos/finales/\n\n" + "\n".join([f"{x['score']} - {x['title']} -> {x['url']}" for x in final_for_lws])
86
+
87
+ except Exception as e:
88
+ import traceback
89
+ return f"❌ Erreur: {str(e)}\n{traceback.format_exc()}"
90
+
91
+ with gr.Blocks(title="OPUS 1080p Factory") as demo:
92
+ gr.Markdown("# 🏭 OPUS 1080p - Usine Gratuite ZeroGPU\nR2 -> 10 clips viraux 1080p -> LWS opus.dostodgroup.com")
93
+ job_id = gr.Textbox(label="job_id (ex: job_123)", value="job_test_1")
94
+ video_url = gr.Textbox(label="URL video longue R2 (https://pub-.../video.mp4)", placeholder="https://pub-xxx.r2.dev/uploads/...")
95
+ btn = gr.Button("🚀 RENDRE 10 CLIPS 1080p", variant="primary")
96
+ output = gr.Textbox(label="Logs", lines=15)
97
+ btn.click(factory, [job_id, video_url], output)
98
+
99
+ demo.launch()