dieumercimvemba commited on
Commit
468fa58
·
verified ·
1 Parent(s): 05a820e

Create data/generate_subtitles.py

Browse files
Files changed (1) hide show
  1. data/generate_subtitles.py +107 -0
data/generate_subtitles.py ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import stable_whisper
4
+ import json
5
+ import argparse
6
+
7
+ # --- CORRECTIF ERREUR CUDA ---
8
+ os.environ["CUDA_VISIBLE_DEVICES"] = ""
9
+
10
+ def get_style_config(theme_name):
11
+ """
12
+ Configuration des thèmes (ASS BGR).
13
+ Note: On utilise 'DejaVu Sans' ou 'Liberation Sans' qui sont présents par défaut.
14
+ """
15
+ styles = {
16
+ "viral": {
17
+ "font": "DejaVu Sans Bold",
18
+ "font_size": 32,
19
+ "color": "00FFFF",
20
+ "margin_v": 450,
21
+ "outline": 4,
22
+ "shadow": 2,
23
+ "max_chars": 10
24
+ },
25
+ "minimal": {
26
+ "font": "Liberation Sans",
27
+ "font_size": 22,
28
+ "color": "FFFFFF",
29
+ "margin_v": 350,
30
+ "outline": 2,
31
+ "shadow": 1,
32
+ "max_chars": 15
33
+ },
34
+ "default": {
35
+ "font": "DejaVu Sans Bold",
36
+ "font_size": 28,
37
+ "color": "00FFFF",
38
+ "margin_v": 400,
39
+ "outline": 3,
40
+ "shadow": 1.5,
41
+ "max_chars": 12
42
+ }
43
+ }
44
+ return styles.get(theme_name, styles["default"])
45
+
46
+ def run():
47
+ parser = argparse.ArgumentParser()
48
+ parser.add_argument("audio_path")
49
+ parser.add_argument("output_ass")
50
+ parser.add_argument("text")
51
+ parser.add_argument("--theme", default="default")
52
+ parser.add_argument("--font")
53
+ parser.add_argument("--font_size", type=int)
54
+ parser.add_argument("--margin_v", type=int)
55
+ parser.add_argument("--color")
56
+ parser.add_argument("--max_chars", type=int)
57
+
58
+ args, unknown = parser.parse_known_args()
59
+
60
+ # 1. Charger le thème de base
61
+ s = get_style_config(args.theme)
62
+
63
+ # 2. Override dynamique (priorité aux arguments n8n)
64
+ if args.font: s["font"] = args.font
65
+ if args.font_size: s["font_size"] = args.font_size
66
+ if args.margin_v: s["margin_v"] = args.margin_v
67
+ if args.color: s["color"] = args.color
68
+ if args.max_chars: s["max_chars"] = args.max_chars
69
+
70
+ try:
71
+ model = stable_whisper.load_model("base", device="cpu")
72
+
73
+ # --- CHANGEMENT MAJEUR : ALIGNEMENT AU LIEU DE TRANSCRIPTION ---
74
+ # On force Whisper à utiliser le texte exact fourni par n8n
75
+ result = model.align(args.audio_path, args.text, language="fr")
76
+
77
+ # Découpage pour l'esthétique Karaoké
78
+ result.split_by_length(max_chars=s["max_chars"], max_words=3)
79
+
80
+ # Export au format ASS
81
+ result.to_ass(
82
+ args.output_ass,
83
+ word_level=True,
84
+ highlight_color=s["color"],
85
+ primary_color="FFFFFF",
86
+ font=s["font"],
87
+ font_size=s["font_size"],
88
+ margin_v=s["margin_v"],
89
+ outline=s["outline"],
90
+ shadow=s["shadow"],
91
+ alignment=2,
92
+ font_style='Bold=1'
93
+ )
94
+
95
+ print(json.dumps({
96
+ "status": "success",
97
+ "output_file": args.output_ass,
98
+ "applied_params": s,
99
+ "method": "alignment"
100
+ }))
101
+
102
+ except Exception as e:
103
+ print(json.dumps({"status": "error", "message": str(e)}))
104
+ sys.exit(1)
105
+
106
+ if __name__ == "__main__":
107
+ run()