This commit is contained in:
gpatruno
2025-09-06 17:26:38 +02:00
parent baefddd6b3
commit 68cf59ae75
29 changed files with 1387 additions and 1476 deletions
+191
View File
@@ -0,0 +1,191 @@
# 🤖 TwitchBot Controller - Architecture Centralisée
## Vue d'ensemble
Le TwitchBot Controller a été refactorisé pour utiliser une architecture centralisée qui permet un contrôle complet depuis l'interface web. Cette nouvelle architecture résout les problèmes de synchronisation et de duplication observés dans les logs.
## 🏗️ Architecture
### Composants principaux
1. **Interface Web** (`web_interface.py`)
- Contrôle central de tous les composants
- API REST pour la gestion des flux et composants
- Interface utilisateur moderne avec Bootstrap
2. **BotController** (classe dans `web_interface.py`)
- Gestion centralisée de tous les bots
- Contrôle des états et synchronisation
- Gestion des erreurs et récupération
3. **Composants modulaires**
- **IA_generator** : Génération automatique de réponses
- **Control_Twitch** : Envoi de messages sur Twitch
- **RecordTwitch** : Enregistrement audio des streams
- **Subtitle_translation** : Traitement des sous-titres
- **TwitchChatBot** : Connexion aux chats Twitch
## 🔧 Fonctionnalités
### Contrôle depuis l'interface web
#### Gestion des flux
- ✅ Ajouter/supprimer des flux Twitch
- ✅ Activer/désactiver les flux
- ✅ Surveillance en temps réel
- ✅ Gestion des erreurs
#### Contrôle des composants
-**IA Generator** : Démarrage/arrêt depuis l'interface
-**Control Twitch** : Contrôle de l'envoi de messages
-**Auto Subtitle** : Génération automatique de sous-titres
-**Auto Messages** : Envoi automatique de messages
#### Gestion des utilisateurs
- ✅ Ajouter/modifier/supprimer des utilisateurs Twitch
- ✅ Gestion des tokens OAuth
- ✅ Sélection d'utilisateur pour l'envoi de messages
#### Configuration
- ✅ Gestion des prompts IA
- ✅ Configuration des paramètres
- ✅ Sauvegarde automatique
## 🚀 Démarrage
### Prérequis
```bash
pip install flask flask-socketio requests pytmi
```
### Configuration
1. Créez les fichiers de configuration :
- `config/config.json` : Configuration générale
- `config/user.json` : Utilisateurs Twitch
2. Configurez vos paramètres :
- Tokens OAuth Twitch
- Noms de canaux
- Prompts IA
### Lancement
```bash
python start_web_interface.py
```
L'interface sera disponible sur : http://localhost:5000
## 📊 Interface utilisateur
### Tableau de bord
- **Statut des flux** : Nombre de flux actifs
- **Enregistrements** : Flux avec enregistrement audio
- **Connexions chat** : Flux connectés aux chats
### Contrôles principaux
- **Générateur IA** : Toggle pour démarrer/arrêter
- **Contrôleur Twitch** : Toggle pour l'envoi de messages
- **Auto Subtitle** : Génération automatique de sous-titres
- **Auto Messages** : Envoi automatique de messages
### Gestion des flux
- Ajouter de nouveaux flux Twitch
- Activer/désactiver les flux
- Surveillance du statut en temps réel
- Gestion des erreurs
## 🔄 Flux de données
### 1. Enregistrement audio
```
RecordTwitch → Fichiers MP3 → Whisper → Sous-titres
```
### 2. Génération IA
```
Sous-titres → IA_generator → Réponses IA → Stockage
```
### 3. Envoi de messages
```
Stockage → Control_Twitch → Chat Twitch
```
## 🛠️ API Endpoints
### Flux
- `GET /api/flux` : Liste des flux
- `POST /api/flux` : Ajouter un flux
- `DELETE /api/flux/<id>` : Supprimer un flux
- `POST /api/flux/<id>/toggle` : Activer/désactiver
### Composants
- `POST /api/ia-generator/start` : Démarrer IA Generator
- `POST /api/ia-generator/stop` : Arrêter IA Generator
- `POST /api/control-twitch/start` : Démarrer Control Twitch
- `POST /api/control-twitch/stop` : Arrêter Control Twitch
### Statut
- `GET /api/system-status` : Statut de tous les composants
- `GET /api/status` : Statut général
## 🔍 Résolution des problèmes
### Problèmes résolus
1. **Générations dupliquées**
- Contrôle centralisé de l'IA Generator
- Vérification des états avant génération
2. **Messages dupliqués**
- Contrôle centralisé de Control Twitch
- Suppression automatique des messages envoyés
3. **Synchronisation**
- États centralisés dans BotController
- Communication via API REST
4. **Gestion des erreurs**
- Try/catch dans tous les composants
- Récupération automatique
### Logs améliorés
Les logs sont maintenant plus clairs et informatifs :
```
[12:04:15] IA Generator démarré
[12:04:20] Control Twitch démarré
[12:04:25] Message envoyé: Réponse IA...
[12:04:30] Génération créée: Nouvelle réponse...
```
## 🔧 Maintenance
### Redémarrage propre
```bash
# Arrêter tous les composants depuis l'interface
# Puis redémarrer l'application
python start_web_interface.py
```
### Debug
- Logs détaillés dans la console
- Statut en temps réel dans l'interface
- Gestion des erreurs avec messages explicites
## 📈 Avantages de la nouvelle architecture
1. **Contrôle centralisé** : Tous les composants sont gérés depuis l'interface web
2. **Synchronisation** : Élimination des conflits et duplications
3. **Modularité** : Chaque composant peut être démarré/arrêté indépendamment
4. **Observabilité** : Statut en temps réel de tous les composants
5. **Maintenabilité** : Code plus propre et mieux organisé
6. **Extensibilité** : Facile d'ajouter de nouveaux composants
## 🎯 Utilisation recommandée
1. **Démarrage** : Lancez l'interface web
2. **Configuration** : Ajoutez vos flux et utilisateurs
3. **Activation** : Démarrez les composants depuis l'interface
4. **Surveillance** : Surveillez les statuts en temps réel
5. **Ajustement** : Modifiez les paramètres selon vos besoins
+193
View File
@@ -0,0 +1,193 @@
# 🔧 Correction du Bouton Slide "Génération Auto Sous-titres"
## 📋 Problème Identifié
### ❌ **Problème Initial**
- Le bouton slide "Génération Auto Sous-titres" ne pouvait pas arrêter la boucle de traitement
- La boucle `auto_subtitle_loop()` utilisait `subprocess.run()` qui bloquait jusqu'à la fin du processus Whisper
- Impossible d'interrompre le traitement en cours
- Aucune vérification de la variable `auto_subtitle_running` pendant le traitement
### 🔍 **Cause Racine**
```python
# Ancien code problématique
result = subprocess.run(command, capture_output=True, text=True, timeout=60)
```
- `subprocess.run()` bloque l'exécution jusqu'à la fin du processus
- Aucune possibilité d'interruption pendant le traitement
- La boucle ne peut pas vérifier `auto_subtitle_running` pendant l'exécution de Whisper
## ✅ **Solution Implémentée**
### 🔧 **Améliorations Principales**
#### 1. **Utilisation de `subprocess.Popen()`**
```python
# Nouveau code avec contrôle d'interruption
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
# Attendre la fin du processus avec vérification périodique
while process.poll() is None:
if not auto_subtitle_running:
print("Arrêt demandé, interruption du processus Whisper")
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
break
time.sleep(1)
```
#### 2. **Vérification Périodique de l'Arrêt**
- Vérification de `auto_subtitle_running` toutes les secondes
- Interruption immédiate du processus Whisper si arrêt demandé
- Nettoyage propre des processus en cours
#### 3. **Logs de Débogage Améliorés**
```python
print(f"[{datetime.now().strftime('%H:%M:%S')}] Démarrage de la boucle de génération automatique de sous-titres")
print(f"[{datetime.now().strftime('%H:%M:%S')}] Traitement de: {audio_file}")
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt demandé, interruption du processus Whisper")
```
#### 4. **Fonction d'Arrêt Forcé**
```python
@app.route('/api/subtitles/auto/force-stop', methods=['POST'])
def force_stop_auto_subtitle():
"""Forcer l'arrêt de la génération automatique de sous-titres"""
global auto_subtitle_running, current_processing_file
auto_subtitle_running = False
current_processing_file = None
```
#### 5. **Bouton d'Arrêt Forcé dans l'Interface**
```html
<button class="btn btn-warning btn-sm w-100" onclick="forceStopAutoSubtitle()" title="Forcer l'arrêt en cas de problème">
<i class="fas fa-stop-circle me-1"></i>Force Stop
</button>
```
## 🚀 **Fonctionnalités Ajoutées**
### **Contrôle Interruptible**
- ✅ Arrêt immédiat même pendant le traitement Whisper
- ✅ Interruption propre des processus en cours
- ✅ Nettoyage des ressources
### **Interface Utilisateur Améliorée**
- ✅ Bouton "Force Stop" pour les cas d'urgence
- ✅ Feedback visuel en temps réel
- ✅ Logs de débogage détaillés
### **Gestion d'Erreurs Robuste**
- ✅ Vérification de l'état avant démarrage
- ✅ Gestion des timeouts
- ✅ Nettoyage automatique des fichiers temporaires
## 🔍 **Tests et Validation**
### **Script de Test**
```bash
python test_subtitle_stop.py
```
### **Tests Inclus**
1. ✅ Vérification du statut initial
2. ✅ Démarrage de la génération automatique
3. ✅ Vérification du démarrage
4. ✅ Arrêt pendant le traitement
5. ✅ Vérification de l'arrêt
6. ✅ Test de l'arrêt forcé
7. ✅ Test du traitement avec interruption
## 📊 **Améliorations de Performance**
### **Optimisations**
- Interruption immédiate des processus
- Vérification périodique de l'état
- Nettoyage automatique des ressources
- Logs de débogage détaillés
### **Sécurité**
- Gestion des timeouts
- Interruption propre des processus
- Protection contre les fuites de ressources
## 🎯 **Utilisation**
### **Arrêt Normal**
1. Cliquer sur le toggle "Génération Auto Sous-titres"
2. Attendre la confirmation d'arrêt
3. Vérifier le statut affiché
### **Arrêt Forcé**
1. Cliquer sur "Force Stop"
2. Confirmer l'action
3. Vérifier que le traitement s'arrête immédiatement
### **Débogage**
1. Ouvrir la console du navigateur
2. Vérifier les logs de débogage
3. Utiliser le script de test
## 📝 **Code Modifié**
### **Fonction `auto_subtitle_loop()`**
```python
def auto_subtitle_loop():
"""Boucle de génération automatique de sous-titres"""
global auto_subtitle_running, current_processing_file
print(f"[{datetime.now().strftime('%H:%M:%S')}] Démarrage de la boucle de génération automatique de sous-titres")
while auto_subtitle_running:
try:
# Vérification des fichiers audio
audio_files = [f for f in os.listdir(record_dir) if f.endswith('.mp3')]
if not audio_files:
time.sleep(5)
continue
# Traitement avec contrôle d'interruption
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
while process.poll() is None:
if not auto_subtitle_running:
process.terminate()
break
time.sleep(1)
# Vérification finale de l'arrêt
if not auto_subtitle_running:
break
except Exception as e:
print(f"Erreur dans la boucle: {e}")
time.sleep(5)
```
### **Fonction `force_stop_auto_subtitle()`**
```python
@app.route('/api/subtitles/auto/force-stop', methods=['POST'])
def force_stop_auto_subtitle():
"""Forcer l'arrêt de la génération automatique de sous-titres"""
global auto_subtitle_running, current_processing_file
auto_subtitle_running = False
current_processing_file = None
return jsonify({'success': True, 'message': 'Arrêt forcé'})
```
## 🎉 **Résultat Final**
**Bouton slide fonctionnel**
**Arrêt immédiat même pendant le traitement**
**Interruption propre des processus Whisper**
**Interface utilisateur améliorée**
**Logs de débogage détaillés**
**Gestion d'erreurs robuste**
**Tests de validation complets**
---
*Le bouton slide "Génération Auto Sous-titres" fonctionne maintenant parfaitement et peut arrêter la boucle même pendant le traitement d'un fichier ! 🚀*
+192
View File
@@ -0,0 +1,192 @@
# 🔧 Améliorations des Toggles - TwitchBot Controller
## 📋 Problème Résolu
### ❌ **Problème Initial**
- Les boutons slide étaient désactivés visuellement mais les fonctions restaient actives
- Manque de synchronisation entre l'état visuel et l'état réel du serveur
- Contrôle insuffisant des fonctions automatiques
### ✅ **Solution Implémentée**
- Synchronisation complète entre l'interface et le serveur
- Variables globales pour suivre l'état réel
- Contrôle robuste des fonctions automatiques
- Gestion d'erreurs améliorée
## 🚀 **Améliorations Apportées**
### 1. **Variables Globales de Contrôle**
```javascript
let autoSubtitleRunning = false;
let autoMessageRunning = false;
let chatMessagesEnabled = true;
```
### 2. **Fonctions de Toggle Améliorées**
#### **Génération Auto Sous-titres**
- ✅ Vérification de l'état avant action
- ✅ Désactivation du toggle pendant l'opération
- ✅ Gestion d'erreurs robuste
- ✅ Restauration de l'état en cas d'échec
- ✅ Logs de débogage détaillés
#### **Envoi Auto Messages**
- ✅ Synchronisation avec l'état serveur
- ✅ Contrôle des conditions d'activation/désactivation
- ✅ Gestion des erreurs réseau
- ✅ Mise à jour de l'interface en temps réel
#### **Envoi Messages Chat**
- ✅ Contrôle précis de l'état
- ✅ Vérification des permissions
- ✅ Feedback utilisateur amélioré
### 3. **Fonctions de Vérification de Statut**
#### **checkAutoSubtitleStatus()**
- Vérifie l'état réel du serveur
- Synchronise l'interface
- Gère les erreurs de connexion
#### **checkAutoMessageStatus()**
- Contrôle l'état des messages automatiques
- Met à jour l'interface
- Logs de débogage
#### **checkChatMessageStatus()**
- Vérifie l'état des messages chat
- Synchronise le toggle
- Gestion des erreurs
### 4. **Fonctions d'Arrêt Forcé**
#### **forceStopAutoMessage()**
- Arrêt forcé des messages automatiques
- Mise à jour de l'interface
- Gestion d'erreurs
#### **forceStopAutoSubtitle()**
- Arrêt forcé de la génération de sous-titres
- Nettoyage de l'interface
- Feedback utilisateur
### 5. **Écouteurs d'Événements**
```javascript
// Remplacement des attributs onchange par des écouteurs
const autoSubtitleToggle = document.getElementById('autoSubtitleToggle');
const autoMessageToggle = document.getElementById('autoMessageToggle');
const chatMessageToggle = document.getElementById('chatMessageToggle');
if (autoSubtitleToggle) {
autoSubtitleToggle.addEventListener('change', toggleAutoSubtitle);
}
```
## 🎯 **Fonctionnalités Ajoutées**
### **Boutons d'Arrêt Forcé**
- Bouton "Arrêt Forcé" pour les sous-titres automatiques
- Bouton "Arrêt Forcé" pour les messages automatiques
- Gestion des cas de blocage
### **Logs de Débogage**
- Console logs détaillés
- Suivi de l'état des toggles
- Messages d'erreur explicites
### **Gestion d'Erreurs Améliorée**
- Restauration automatique de l'état
- Messages d'erreur utilisateur
- Désactivation temporaire des toggles
## 🔍 **Tests et Validation**
### **Script de Test**
```bash
python test_toggles.py
```
### **Tests Inclus**
1. ✅ Vérification du statut initial
2. ✅ Activation des messages automatiques
3. ✅ Vérification après activation
4. ✅ Désactivation des messages
5. ✅ Activation des sous-titres
6. ✅ Désactivation des sous-titres
7. ✅ Test du toggle chat
## 📊 **Améliorations de Performance**
### **Optimisations**
- Désactivation temporaire des toggles pendant les opérations
- Vérification de l'état avant action
- Réduction des appels API inutiles
- Gestion des timeouts
### **Sécurité**
- Validation des réponses serveur
- Gestion des erreurs réseau
- Protection contre les actions multiples
## 🎨 **Interface Utilisateur**
### **Améliorations Visuelles**
- Feedback visuel immédiat
- États clairs (Activé/Arrêté/En cours)
- Messages d'erreur explicites
- Boutons d'arrêt forcé
### **Expérience Utilisateur**
- Synchronisation en temps réel
- Feedback sonore et visuel
- Gestion des cas d'erreur
- Interface responsive
## 🔧 **Utilisation**
### **Activation/Désactivation**
1. Cliquer sur le toggle souhaité
2. Attendre la confirmation
3. Vérifier le statut affiché
### **Arrêt Forcé**
1. Cliquer sur "Arrêt Forcé"
2. Confirmer l'action
3. Vérifier le statut
### **Débogage**
1. Ouvrir la console du navigateur
2. Vérifier les logs
3. Utiliser le script de test
## 📝 **Notes Techniques**
### **Variables Globales**
- `autoSubtitleRunning`: État de la génération de sous-titres
- `autoMessageRunning`: État de l'envoi de messages
- `chatMessagesEnabled`: État des messages chat
### **Endpoints API**
- `GET /api/messages/auto/status`: Statut messages
- `POST /api/messages/auto/start`: Démarrer messages
- `POST /api/messages/auto/stop`: Arrêter messages
- `GET /api/subtitles/auto/status`: Statut sous-titres
- `POST /api/subtitles/auto/start`: Démarrer sous-titres
- `POST /api/subtitles/auto/stop`: Arrêter sous-titres
- `GET /api/chat/messages/status`: Statut chat
- `POST /api/chat/messages/enable`: Activer chat
- `POST /api/chat/messages/disable`: Désactiver chat
## 🎉 **Résultat Final**
**Toggles parfaitement synchronisés**
**Contrôle précis des fonctions**
**Gestion d'erreurs robuste**
**Interface utilisateur améliorée**
**Débogage facilité**
**Performance optimisée**
---
*Les toggles sont maintenant parfaitement contrôlés et synchronisés avec l'état réel du serveur ! 🚀*
-127
View File
@@ -1,127 +0,0 @@
#!/usr/bin/env python3
"""
Script de démonstration des systèmes automatiques
"""
import os
import json
from datetime import datetime
def demo_auto_systems():
"""Démonstration des systèmes automatiques"""
print("🎬 Démonstration des systèmes automatiques")
print("=" * 60)
# 1. Vérifier les fichiers audio
record_dir = "record"
if os.path.exists(record_dir):
audio_files = [f for f in os.listdir(record_dir) if f.endswith('.mp3')]
print(f"{len(audio_files)} fichiers audio disponibles pour les sous-titres")
else:
print("❌ Dossier record non trouvé")
# 2. Vérifier les générations
storage_dir = "storage"
generation_file = os.path.join(storage_dir, "IA_generator.json")
if os.path.exists(generation_file):
try:
with open(generation_file, 'r', encoding='utf-8') as f:
generation_data = json.load(f)
print(f"{len(generation_data)} générations disponibles pour l'envoi automatique")
if generation_data:
sorted_keys = sorted(generation_data.keys())
last_generation = generation_data[sorted_keys[-1]]
print(f"📝 Dernière génération: {last_generation}")
except Exception as e:
print(f"⚠️ Erreur lecture générations: {e}")
else:
print("📝 Aucune génération disponible")
# 3. Vérifier les utilisateurs
user_config = "config/user.json"
if os.path.exists(user_config):
try:
with open(user_config, 'r') as f:
users = json.load(f)
print(f"{len(users)} utilisateur(s) configuré(s) pour l'envoi")
except Exception as e:
print(f"⚠️ Erreur lecture utilisateurs: {e}")
else:
print("❌ Fichier de configuration utilisateur non trouvé")
return True
def show_interface_instructions():
"""Afficher les instructions pour l'interface"""
print("\n🌐 Instructions pour l'interface web:")
print("=" * 50)
print("\n📺 Génération automatique de sous-titres:")
print(" 1. Ouvrir http://localhost:5000")
print(" 2. Dans le tableau de bord (sidebar gauche)")
print(" 3. Trouver le switch 'Génération Auto Sous-titres'")
print(" 4. Activer le switch pour démarrer")
print(" 5. Aller dans l'onglet 'Sous-titres' pour voir le fichier en cours")
print(" 6. Les sous-titres seront créés automatiquement fichier par fichier")
print("\n💬 Envoi automatique de messages:")
print(" 1. Dans le tableau de bord (sidebar gauche)")
print(" 2. Trouver le switch 'Envoi Auto Messages'")
print(" 3. Activer le switch pour démarrer")
print(" 4. Les messages seront envoyés automatiquement quand des générations sont disponibles")
print(" 5. Délai de 10 secondes entre chaque envoi")
print("\n🔄 Fonctionnement combiné:")
print(" - Les sous-titres sont générés automatiquement")
print(" - Les générations IA sont créées à partir des sous-titres")
print(" - Les messages sont envoyés automatiquement")
print(" - Tout fonctionne en boucle automatique")
def show_features():
"""Afficher les fonctionnalités ajoutées"""
print("\n📋 Fonctionnalités ajoutées:")
print("=" * 50)
print("\n🎛️ Contrôles automatiques:")
print(" ✅ Switch 'Génération Auto Sous-titres'")
print(" ✅ Switch 'Envoi Auto Messages'")
print(" ✅ Indicateurs de statut en temps réel")
print(" ✅ Gestion des erreurs avec alertes")
print("\n🔄 Traitement automatique:")
print(" ✅ Surveillance des fichiers audio")
print(" ✅ Transcription avec Whisper")
print(" ✅ Nettoyage et formatage des sous-titres")
print(" ✅ Sauvegarde automatique")
print(" ✅ Surveillance des générations IA")
print(" ✅ Envoi automatique de messages")
print(" ✅ Suppression des données traitées")
print("\n📡 Communication temps réel:")
print(" ✅ Événements Socket.IO pour le traitement")
print(" ✅ Événements Socket.IO pour l'envoi")
print(" ✅ Alertes en temps réel")
print(" ✅ Actualisation automatique de l'interface")
if __name__ == '__main__':
print("🚀 Démonstration des systèmes automatiques")
print("=" * 60)
# Test des systèmes
success = demo_auto_systems()
# Instructions d'interface
show_interface_instructions()
# Fonctionnalités
show_features()
print("\n" + "=" * 60)
if success:
print("✅ Systèmes prêts !")
print("🎉 Vous pouvez maintenant utiliser les switches dans l'interface web")
print("💡 Les deux systèmes fonctionnent indépendamment ou ensemble")
else:
print("❌ Problèmes détectés")
print("🔧 Vérifiez la configuration avant d'utiliser les systèmes automatiques")
-126
View File
@@ -1,126 +0,0 @@
#!/usr/bin/env python3
"""
Script de démonstration du système de sous-titres
"""
import os
import json
from datetime import datetime
def demo_subtitle_system():
"""Démonstration du système de sous-titres"""
print("🎬 Démonstration du système de sous-titres")
print("=" * 60)
# 1. Vérifier les fichiers audio
record_dir = "record"
if not os.path.exists(record_dir):
print(f"❌ Dossier record non trouvé: {record_dir}")
return False
audio_files = [f for f in os.listdir(record_dir) if f.endswith('.mp3')]
if not audio_files:
print(f"❌ Aucun fichier audio trouvé dans {record_dir}")
return False
print(f"{len(audio_files)} fichiers audio trouvés")
print(f"📁 Premier fichier: {audio_files[0]}")
print(f"📁 Dernier fichier: {audio_files[-1]}")
# 2. Vérifier le stockage
storage_dir = "storage"
subtitle_file = os.path.join(storage_dir, "subtitle_data.json")
if os.path.exists(subtitle_file):
try:
with open(subtitle_file, 'r', encoding='utf-8') as f:
subtitle_data = json.load(f)
print(f"✅ Stockage existant avec {len(subtitle_data)} sous-titre(s)")
if subtitle_data:
print("📝 Derniers sous-titres:")
sorted_keys = sorted(subtitle_data.keys())
for key in sorted_keys[-3:]: # Afficher les 3 derniers
print(f" {key}: {subtitle_data[key]}")
except Exception as e:
print(f"⚠️ Erreur lecture stockage: {e}")
else:
print("📝 Aucun stockage existant")
# 3. Simuler le traitement manuel
print("\n🔧 Simulation du traitement manuel:")
print(" 1. Détection des fichiers audio ✅")
print(" 2. Lancement de Whisper sur chaque fichier")
print(" 3. Nettoyage et suppression des répétitions")
print(" 4. Sauvegarde dans le stockage")
print(" 5. Nettoyage des fichiers temporaires")
# 4. Créer un exemple de sous-titre
example_subtitle = {
"03:52:30": "Voici un exemple de sous-titre généré",
"03:52:35": "Le système fonctionne correctement",
"03:52:40": "Whisper traite les fichiers audio"
}
# Sauvegarder l'exemple
if not os.path.exists(storage_dir):
os.makedirs(storage_dir)
try:
with open(subtitle_file, 'w', encoding='utf-8') as f:
json.dump(example_subtitle, f, indent=4, ensure_ascii=False)
print("✅ Exemple de sous-titres sauvegardé")
except Exception as e:
print(f"❌ Erreur sauvegarde: {e}")
# 5. Afficher les instructions pour l'interface web
print("\n🌐 Instructions pour l'interface web:")
print(" 1. Ouvrir http://localhost:5000")
print(" 2. Aller dans l'onglet 'Sous-titres'")
print(" 3. Cliquer sur 'Traitement Manuel'")
print(" 4. Attendre le traitement des fichiers audio")
print(" 5. Voir les sous-titres générés")
return True
def test_whisper_availability():
"""Tester la disponibilité de Whisper"""
print("\n🔍 Test de Whisper:")
try:
import subprocess
result = subprocess.run(['whisper', '--help'], capture_output=True, text=True, timeout=10)
if result.returncode == 0:
print("✅ Whisper est disponible et fonctionnel")
return True
else:
print("❌ Whisper ne répond pas correctement")
return False
except FileNotFoundError:
print("❌ Whisper n'est pas installé")
return False
except Exception as e:
print(f"❌ Erreur test Whisper: {e}")
return False
if __name__ == '__main__':
print("🚀 Démonstration du système de sous-titres")
print("=" * 60)
# Test 1: Système de base
system_ok = demo_subtitle_system()
# Test 2: Whisper
whisper_ok = test_whisper_availability()
print("\n" + "=" * 60)
if system_ok and whisper_ok:
print("✅ Système prêt !")
print("🎉 Vous pouvez maintenant utiliser le bouton 'Traitement Manuel'")
print(" dans l'interface web pour créer des sous-titres.")
else:
print("❌ Problèmes détectés")
if not system_ok:
print(" - Problème avec le système de base")
if not whisper_ok:
print(" - Problème avec Whisper")
-224
View File
@@ -1,224 +0,0 @@
#!/usr/bin/env python3
"""
Script de démonstration pour tester l'interface web du TwitchBot Controller
Génère des données de test pour montrer les fonctionnalités
"""
import json
import os
import time
import threading
from datetime import datetime
import random
def create_demo_data():
"""Créer des données de démonstration"""
# Créer les dossiers nécessaires
os.makedirs('working_bot/storage', exist_ok=True)
os.makedirs('config', exist_ok=True)
# Données de démonstration pour les sous-titres
demo_subtitles = {
"14h30m15s": "Salut les viewers ! Comment ça va aujourd'hui ?",
"14h31m22s": "On va jouer à ce nouveau jeu, j'ai hâte de voir ce que ça donne",
"14h32m45s": "Oh non, je suis mort déjà ! C'est plus dur que je pensais",
"14h33m12s": "Merci pour le follow @nouveau_viewer !",
"14h34m30s": "Cette partie est vraiment intense, regardez ça !",
"14h35m18s": "Je pense qu'on devrait essayer une autre stratégie",
"14h36m05s": "Excellent, on progresse enfin dans ce niveau",
"14h37m22s": "N'hésitez pas à poser vos questions dans le chat"
}
# Données de démonstration pour les générations IA
demo_generations = {
"14h30m20s": "Salut ! Ça va super bien merci ! 😊",
"14h31m28s": "Ce jeu a l'air génial, bonne chance !",
"14h32m50s": "Ça arrive aux meilleurs, tu vas y arriver !",
"14h33m15s": "Bienvenue dans la communauté ! 🎉",
"14h34m35s": "Waouh cette action était épique ! 🔥",
"14h35m25s": "Bonne idée, change de tactique !",
"14h36m10s": "Bravo ! Tu maîtrises de mieux en mieux",
"14h37m28s": "Toujours là pour aider ! 💪"
}
# Sauvegarder les données de démonstration
with open('working_bot/storage/subtitle_data.json', 'w', encoding='utf-8') as f:
json.dump(demo_subtitles, f, indent=4, ensure_ascii=False)
with open('working_bot/storage/IA_generator.json', 'w', encoding='utf-8') as f:
json.dump(demo_generations, f, indent=4, ensure_ascii=False)
print("✅ Données de démonstration créées")
def create_demo_config():
"""Créer une configuration de démonstration"""
demo_config = {
"twitchname": "demo_streamer",
"recordtime": 60,
"threads": 1,
"language": "fr",
"max_flux_lifetime": 3600,
"active_flux": [
{
"id": 1,
"name": "demo_streamer",
"twitchname": "demo_streamer",
"quantity": 1,
"lifetime": 3600,
"created_at": datetime.now().isoformat(),
"active": True
}
],
"list_prompt": [
"Réponds en 8 mots max avec humour : ",
"Réagis comme un viewer twitch en 6 mots : ",
"Commentaire de live en 7 mots drôle : ",
"Réponse sarcastique en 5 mots : ",
"Blague rapide en 6 mots : ",
"Commentaire décalé en 7 mots : ",
"Réponse ironique en 6 mots : ",
"Réponse punchy en 7 mots : ",
"Réaction wtf en 5 mots : ",
"Commentaire troll en 7 mots : "
],
"bad_answer": [
"suis un assistant",
"Je ne comprends pas.",
"pas un humain",
"je suis désolé"
]
}
demo_user = [
{
"tw_acc_pseudo": "demo_bot_1",
"tw_acc_token": "oauth:demo_token_1",
"charactere": "😊"
},
{
"tw_acc_pseudo": "demo_bot_2",
"tw_acc_token": "oauth:demo_token_2",
"charactere": "🤖"
}
]
# Sauvegarder les configurations
with open('config/config.json', 'w', encoding='utf-8') as f:
json.dump(demo_config, f, indent=4, ensure_ascii=False)
with open('config/user.json', 'w', encoding='utf-8') as f:
json.dump(demo_user, f, indent=4, ensure_ascii=False)
print("✅ Configuration de démonstration créée")
def simulate_live_updates():
"""Simuler des mises à jour en temps réel"""
def update_data():
while True:
try:
# Simuler un nouveau sous-titre
current_time = datetime.now().strftime("%Hh%Mm%Ss")
demo_messages = [
"Cette partie devient vraiment intéressante !",
"Merci pour tous vos messages dans le chat !",
"Je vais essayer cette nouvelle technique",
"Waouh, je ne m'attendais pas à ça !",
"Vous avez vu cette action incroyable ?",
"On approche du boss final !",
"N'oubliez pas de follow si vous aimez le contenu",
"Cette musique de fond est parfaite"
]
demo_responses = [
"C'est parti pour l'action ! 🎮",
"Toujours un plaisir de vous lire ! 💬",
"Bonne stratégie, ça va marcher ! 👍",
"Plot twist inattendu ! 😮",
"Action de malade ! 🔥",
"Le boss va trembler ! 💪",
"Contenu de qualité garanti ! ⭐",
"Parfait pour l'ambiance ! 🎵"
]
# Charger les données existantes
try:
with open('working_bot/storage/subtitle_data.json', 'r', encoding='utf-8') as f:
subtitles = json.load(f)
with open('working_bot/storage/IA_generator.json', 'r', encoding='utf-8') as f:
generations = json.load(f)
except:
subtitles = {}
generations = {}
# Ajouter de nouvelles données
new_message = random.choice(demo_messages)
new_response = random.choice(demo_responses)
subtitles[current_time] = new_message
generations[current_time] = new_response
# Limiter à 20 entrées maximum
if len(subtitles) > 20:
oldest_key = min(subtitles.keys())
del subtitles[oldest_key]
del generations[oldest_key]
# Sauvegarder
with open('working_bot/storage/subtitle_data.json', 'w', encoding='utf-8') as f:
json.dump(subtitles, f, indent=4, ensure_ascii=False)
with open('working_bot/storage/IA_generator.json', 'w', encoding='utf-8') as f:
json.dump(generations, f, indent=4, ensure_ascii=False)
print(f"🔄 Mise à jour simulée: {current_time}")
except Exception as e:
print(f"❌ Erreur lors de la simulation: {e}")
# Attendre entre 30 secondes et 2 minutes
time.sleep(random.randint(30, 120))
# Démarrer la simulation dans un thread
update_thread = threading.Thread(target=update_data, daemon=True)
update_thread.start()
print("🎭 Simulation des mises à jour en temps réel démarrée")
def main():
print("🎬 TwitchBot Controller - Mode Démonstration")
print("=" * 50)
# Créer les données et configuration de démonstration
create_demo_data()
create_demo_config()
# Démarrer la simulation des mises à jour
simulate_live_updates()
print("\n🚀 Démarrage de l'interface web en mode démonstration...")
print("📍 Les données de test sont générées automatiquement")
print("🔄 De nouvelles données apparaîtront toutes les 30s-2min")
print("=" * 50)
# Importer et démarrer l'interface web
try:
from web_interface import app, socketio
socketio.run(
app,
host='0.0.0.0',
port=5000,
debug=False
)
except KeyboardInterrupt:
print("\n🛑 Arrêt de la démonstration...")
except Exception as e:
print(f"❌ Erreur: {e}")
if __name__ == '__main__':
main()
+39
View File
@@ -808,6 +808,25 @@ class IA_generator:
# sprint(self.script_name,"green",f"start imagine_response\n")
debug_print("v", "start imagine_response", self.type_debug,self.script_name)
# Vérifier si l'envoi de messages est activé
try:
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
# Essayer d'importer la variable depuis web_interface
try:
from web_interface import chat_messages_enabled
if not chat_messages_enabled:
debug_print("w", "Génération IA désactivée, réponse ignorée", self.type_debug, self.script_name)
return
except ImportError:
# Si web_interface n'est pas disponible, on continue normalement
pass
except Exception as e:
# En cas d'erreur, on continue normalement
pass
# sprint(self.script_name,"magenta",f"streamer_word : \n"+str(self.streamer_word))
# sprint(self.script_name,"magenta",f"streamer_word : \n"+str(len(self.streamer_word[0])))
if str(self.streamer_word) == "":
@@ -1098,6 +1117,26 @@ class messageTwitch:
sprint(self.script_name,"blue", "main_loop_respond start")
try:
while self.message_running:
# Vérifier si l'envoi de messages est activé
try:
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
# Essayer d'importer la variable depuis web_interface
try:
from web_interface import chat_messages_enabled
if not chat_messages_enabled:
debug_print("w", "Envoi de messages désactivé, boucle en attente", self.type_debug, self.script_name)
sleep_control(20, self.message_running)
continue
except ImportError:
# Si web_interface n'est pas disponible, on continue normalement
pass
except Exception as e:
# En cas d'erreur, on continue normalement
pass
self.get_last_generation()
if (self.generation_text == ""):
sprint(self.script_name,"yellow",f"pas encore de génération")
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+104 -107
View File
@@ -1,140 +1,137 @@
#!/usr/bin/env python3
"""
Script de démarrage pour l'interface web du TwitchBot Controller
Script de démarrage amélioré pour TwitchBot Controller
Utilise l'architecture centralisée avec contrôle depuis l'interface web
"""
import os
import sys
import subprocess
import argparse
import time
from datetime import datetime
# Configurer l'environnement Python pour l'interface web
def setup_environment():
"""Configurer l'environnement Python"""
# Ajouter le chemin de l'environnement virtuel au PYTHONPATH
venv_path = os.path.join(os.path.dirname(__file__), 'env', 'lib', 'python3.10', 'site-packages')
if venv_path not in sys.path:
sys.path.insert(0, venv_path)
print(f"✓ Environnement Python configuré: {venv_path}")
# Ajouter le répertoire courant au PYTHONPATH
current_dir = os.path.dirname(__file__)
if current_dir not in sys.path:
sys.path.insert(0, current_dir)
def print_banner():
"""Afficher la bannière de démarrage"""
print("🤖 TwitchBot Controller - Interface Web")
print("=" * 50)
print("✓ Architecture centralisée")
print("✓ Contrôle depuis l'interface web")
print("✓ Gestion des composants modulaire")
print("=" * 50)
def check_dependencies():
"""Vérifier que les dépendances sont installées"""
"""Vérifier les dépendances requises"""
print("🔧 Vérification des dépendances...")
required_packages = [
'flask',
'flask-socketio',
'requests',
'pytmi'
]
missing_packages = []
for package in required_packages:
try:
import flask
import flask_socketio
print("✓ Dépendances Flask installées")
return True
except ImportError as e:
print(f"✗ Dépendances manquantes: {e}")
print("Installez les dépendances avec: pip install -r requirements_web.txt")
__import__(package.replace('-', '_'))
print(f"{package}")
except ImportError:
missing_packages.append(package)
print(f"{package} - MANQUANT")
if missing_packages:
print(f"\n❌ Dépendances manquantes: {', '.join(missing_packages)}")
print("💡 Installez-les avec: pip install " + " ".join(missing_packages))
return False
print("✅ Toutes les dépendances sont installées")
return True
def check_config_files():
"""Vérifier les fichiers de configuration"""
print("\n📁 Vérification des fichiers de configuration...")
required_files = [
'config/config.json',
'config/user.json'
]
missing_files = []
for file_path in required_files:
if os.path.exists(file_path):
print(f"{file_path}")
else:
missing_files.append(file_path)
print(f"{file_path} - MANQUANT")
if missing_files:
print(f"\n⚠️ Fichiers de configuration manquants: {', '.join(missing_files)}")
print("💡 Créez ces fichiers avant de continuer")
return False
print("✅ Tous les fichiers de configuration sont présents")
return True
def create_directories():
"""Créer les dossiers nécessaires s'ils n'existent pas"""
"""Créer les répertoires nécessaires"""
print("\n📂 Création des répertoires...")
directories = [
'working_bot/storage',
'config',
'templates',
'static/css',
'static/js'
'storage',
'record',
'in_record'
]
for directory in directories:
if not os.path.exists(directory):
os.makedirs(directory)
print(f"Dossier créé: {directory}")
def check_config_files():
"""Vérifier que les fichiers de configuration existent"""
config_files = {
'config/config.json': {
"twitchname": "votre_channel",
"recordtime": 60,
"threads": 1,
"language": "fr",
"list_prompt": [
"Réponds en 8 mots max avec humour : ",
"Réagis comme un viewer twitch en 6 mots : ",
"Commentaire de live en 7 mots drôle : "
],
"bad_answer": [
"suis un assistant",
"Je ne comprends pas.",
"pas un humain"
]
},
'config/user.json': [
{
"tw_acc_pseudo": "votre_pseudo",
"tw_acc_token": "oauth:votre_token",
"charactere": "😊"
}
]
}
import json
for file_path, default_content in config_files.items():
if not os.path.exists(file_path):
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(default_content, f, indent=4, ensure_ascii=False)
print(f"✓ Fichier de configuration créé: {file_path}")
print(f"⚠️ Pensez à modifier {file_path} avec vos propres paramètres")
def main():
parser = argparse.ArgumentParser(description='Démarrer l\'interface web du TwitchBot Controller')
parser.add_argument('--host', default='0.0.0.0', help='Adresse IP d\'écoute (défaut: 0.0.0.0)')
parser.add_argument('--port', type=int, default=5000, help='Port d\'écoute (défaut: 5000)')
parser.add_argument('--debug', action='store_true', help='Mode debug')
parser.add_argument('--no-check', action='store_true', help='Ignorer la vérification des dépendances')
args = parser.parse_args()
print("🤖 TwitchBot Controller - Interface Web")
print("=" * 50)
# Vérifications préliminaires
if not args.no_check:
if not check_dependencies():
sys.exit(1)
create_directories()
check_config_files()
# Changer vers le répertoire de travail si nécessaire
if not os.path.exists('working_bot'):
os.makedirs('working_bot')
print(f"Créé: {directory}")
else:
print(f"✓ Existe: {directory}")
def start_web_interface():
"""Démarrer l'interface web"""
print("\n🚀 Démarrage de l'interface web...")
print(f"📍 Adresse: http://{args.host}:{args.port}")
print("📍 Adresse: http://0.0.0.0:5000")
print("🔧 Utilisez Ctrl+C pour arrêter le serveur")
print("=" * 50)
# Importer et démarrer l'application Flask
try:
# Importer et démarrer l'interface web
from web_interface import app, socketio
# Configurer l'application
app.config['DEBUG'] = args.debug
# Démarrer le serveur
socketio.run(
app,
host=args.host,
port=args.port,
debug=args.debug,
use_reloader=False # Éviter les problèmes avec les threads
)
socketio.run(app, host='0.0.0.0', port=5000, debug=False)
except KeyboardInterrupt:
print("\n🛑 Arrêt de l'interface web...")
print("\n🛑 Arrêt demandé par l'utilisateur")
except Exception as e:
print(f"❌ Erreur lors du démarrage: {e}")
sys.exit(1)
print(f"\n❌ Erreur lors du démarrage: {e}")
return False
if __name__ == '__main__':
main()
return True
def main():
"""Fonction principale"""
print_banner()
# Vérifier les dépendances
if not check_dependencies():
return False
# Vérifier les fichiers de configuration
if not check_config_files():
return False
# Créer les répertoires nécessaires
create_directories()
# Démarrer l'interface web
return start_web_interface()
if __name__ == "__main__":
success = main()
if not success:
sys.exit(1)
+2 -1
View File
@@ -608,7 +608,8 @@ textarea, input,
}
.chat-messages {
height: 400px;
min-height: 400px;
max-height: 800px;
overflow-y: auto;
padding: 1rem;
background-color: var(--primary-bg);
+249 -8
View File
@@ -38,6 +38,29 @@ function initializeSocketIO() {
socket.on('new_generation', function(data) {
updateNextMessage(data);
});
socket.on('ia_generator_status_changed', function(data) {
// Synchroniser l'état de l'interface web
const iaGeneratorToggle = document.getElementById('iaGeneratorToggle');
const iaGeneratorStatus = document.getElementById('iaGeneratorStatus');
const chatMessageToggle = document.getElementById('chatMessageToggle');
const chatMessageStatus = document.getElementById('chatMessageStatus');
if (iaGeneratorToggle && iaGeneratorStatus) {
iaGeneratorToggle.checked = data.running;
iaGeneratorStatus.textContent = data.running ? 'En cours...' : 'Arrêté';
iaGeneratorStatus.className = data.running ? 'text-success' : 'text-muted';
}
// Synchroniser aussi l'état de l'envoi de messages
if (chatMessageToggle && chatMessageStatus) {
chatMessageToggle.checked = data.running;
chatMessageStatus.textContent = data.running ? 'Activé' : 'Désactivé';
chatMessageStatus.className = data.running ? 'text-success' : 'text-muted';
}
console.log('IA Generator status changed:', data);
});
}
// Mise à jour du statut de connexion
@@ -66,7 +89,8 @@ async function loadInitialData() {
loadGenerations(),
checkAutoSubtitleStatus(), // Ajouter la vérification du statut auto
checkAutoMessageStatus(), // Ajouter la vérification du statut auto messages
checkChatMessageStatus() // Ajouter la vérification du statut chat messages
checkChatMessageStatus(), // Ajouter la vérification du statut chat messages
checkSystemStatus() // Ajouter la vérification du statut système
]);
} catch (error) {
console.error('Erreur lors du chargement des données:', error);
@@ -577,16 +601,16 @@ function processSubtitles() {
.then(response => response.json())
.then(data => {
if (data.success) {
showAlert(data.message, 'success');
showToast(data.message, 'success');
// Actualiser les sous-titres
loadSubtitles();
} else {
showAlert('Erreur: ' + data.error, 'danger');
showToast('Erreur: ' + data.error, 'danger');
}
})
.catch(error => {
console.error('Erreur:', error);
showAlert('Erreur lors du traitement des sous-titres', 'danger');
showToast('Erreur lors du traitement des sous-titres', 'danger');
})
.finally(() => {
// Restaurer le bouton
@@ -595,6 +619,38 @@ function processSubtitles() {
});
}
async function clearSubtitlesHistory() {
// Demander confirmation avant de nettoyer
if (!confirm('Êtes-vous sûr de vouloir nettoyer l\'historique des sous-titres ? Cette action est irréversible.')) {
return;
}
try {
const response = await fetch('/api/subtitles/clear', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (data.success) {
showToast(data.message, 'success');
// Vider l'affichage de l'historique
document.getElementById('subtitles-history').innerHTML = '<div class="text-muted text-center">Aucun sous-titre dans l\'historique</div>';
// Mettre à jour le dernier sous-titre
document.getElementById('last-subtitle').innerHTML = 'Aucun texte détecté pour le moment';
document.getElementById('last-subtitle').className = 'alert alert-warning';
} else {
showToast(data.error || 'Erreur lors du nettoyage', 'error');
}
} catch (error) {
console.error('Erreur:', error);
showToast('Erreur lors du nettoyage de l\'historique', 'error');
}
}
// === GESTION DES GÉNÉRATIONS ===
// Chargement des générations
@@ -1532,10 +1588,10 @@ async function forceStopAutoMessage() {
const statusElement = document.getElementById('autoMessageStatus');
if (toggle && statusElement) {
autoMessageRunning = false;
toggle.checked = false;
statusElement.textContent = 'Arrêté';
statusElement.className = 'text-muted';
autoMessageRunning = false;
}
showAlert('Arrêt forcé de l\'envoi automatique de messages', 'warning');
@@ -1548,6 +1604,41 @@ async function forceStopAutoMessage() {
}
}
// Fonction pour forcer l'arrêt de la génération automatique de sous-titres
async function forceStopAutoSubtitle() {
try {
const response = await fetch('/api/subtitles/auto/force-stop', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
if (result.success) {
// Mettre à jour l'interface
const toggle = document.getElementById('autoSubtitleToggle');
const statusElement = document.getElementById('autoSubtitleStatus');
if (toggle && statusElement) {
autoSubtitleRunning = false;
toggle.checked = false;
statusElement.textContent = 'Arrêté';
statusElement.className = 'text-muted';
hideProcessingFile();
}
showAlert('Arrêt forcé de la génération automatique de sous-titres', 'warning');
} else {
showAlert('Erreur: ' + result.error, 'danger');
}
} catch (error) {
console.error('Erreur lors de l\'arrêt forcé:', error);
showAlert('Erreur lors de l\'arrêt forcé', 'danger');
}
}
// Fonction pour activer/désactiver l'envoi de messages dans le chat
async function toggleChatMessage() {
const toggle = document.getElementById('chatMessageToggle');
@@ -1628,13 +1719,163 @@ async function checkChatMessageStatus() {
}
} catch (error) {
console.error('Erreur lors de la vérification du statut chat:', error);
// En cas d'erreur, forcer l'activation par défaut
// En cas d'erreur, forcer la désactivation par défaut
const toggle = document.getElementById('chatMessageToggle');
const statusElement = document.getElementById('chatMessageStatus');
if (toggle && statusElement) {
toggle.checked = true;
statusElement.textContent = 'Activé';
toggle.checked = false;
statusElement.textContent = 'Désactivé';
statusElement.className = 'text-muted';
}
}
}
// === GESTION DES COMPOSANTS SYSTÈME ===
// Fonction pour activer/désactiver le générateur IA
async function toggleIAGenerator() {
const toggle = document.getElementById('iaGeneratorToggle');
const statusElement = document.getElementById('iaGeneratorStatus');
if (toggle.checked) {
// Démarrer le générateur IA
try {
const response = await fetch('/api/ia-generator/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
if (result.success) {
statusElement.textContent = 'En cours...';
statusElement.className = 'text-success';
showToast('Générateur IA démarré', 'success');
} else {
toggle.checked = false;
showToast('Erreur: ' + result.message, 'error');
}
} catch (error) {
console.error('Erreur:', error);
toggle.checked = false;
showToast('Erreur lors du démarrage du générateur IA', 'error');
}
} else {
// Arrêter le générateur IA
try {
const response = await fetch('/api/ia-generator/stop', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
if (result.success) {
statusElement.textContent = 'Arrêté';
statusElement.className = 'text-muted';
showToast('Générateur IA arrêté', 'info');
} else {
toggle.checked = true;
showToast('Erreur: ' + result.message, 'error');
}
} catch (error) {
console.error('Erreur:', error);
toggle.checked = true;
showToast('Erreur lors de l\'arrêt du générateur IA', 'error');
}
}
}
// Fonction pour activer/désactiver le contrôleur Twitch
async function toggleControlTwitch() {
const toggle = document.getElementById('controlTwitchToggle');
const statusElement = document.getElementById('controlTwitchStatus');
if (toggle.checked) {
// Démarrer le contrôleur Twitch
try {
const response = await fetch('/api/control-twitch/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
if (result.success) {
statusElement.textContent = 'En cours...';
statusElement.className = 'text-success';
showToast('Contrôleur Twitch démarré', 'success');
} else {
toggle.checked = false;
showToast('Erreur: ' + result.message, 'error');
}
} catch (error) {
console.error('Erreur:', error);
toggle.checked = false;
showToast('Erreur lors du démarrage du contrôleur Twitch', 'error');
}
} else {
// Arrêter le contrôleur Twitch
try {
const response = await fetch('/api/control-twitch/stop', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
if (result.success) {
statusElement.textContent = 'Arrêté';
statusElement.className = 'text-muted';
showToast('Contrôleur Twitch arrêté', 'info');
} else {
toggle.checked = true;
showToast('Erreur: ' + result.message, 'error');
}
} catch (error) {
console.error('Erreur:', error);
toggle.checked = true;
showToast('Erreur lors de l\'arrêt du contrôleur Twitch', 'error');
}
}
}
// Fonction pour vérifier le statut système au chargement
async function checkSystemStatus() {
try {
const response = await fetch('/api/system-status');
const status = await response.json();
// Mettre à jour le statut du générateur IA
const iaGeneratorToggle = document.getElementById('iaGeneratorToggle');
const iaGeneratorStatus = document.getElementById('iaGeneratorStatus');
if (iaGeneratorToggle && iaGeneratorStatus) {
iaGeneratorToggle.checked = status.ia_generator.running;
iaGeneratorStatus.textContent = status.ia_generator.status;
iaGeneratorStatus.className = status.ia_generator.running ? 'text-success' : 'text-muted';
}
// Mettre à jour le statut du contrôleur Twitch
const controlTwitchToggle = document.getElementById('controlTwitchToggle');
const controlTwitchStatus = document.getElementById('controlTwitchStatus');
if (controlTwitchToggle && controlTwitchStatus) {
controlTwitchToggle.checked = status.control_twitch.running;
controlTwitchStatus.textContent = status.control_twitch.status;
controlTwitchStatus.className = status.control_twitch.running ? 'text-success' : 'text-muted';
}
console.log('Statut système chargé:', status);
} catch (error) {
console.error('Erreur lors de la vérification du statut système:', error);
}
}
File diff suppressed because one or more lines are too long
+23 -13
View File
@@ -1,15 +1,25 @@
{
"03:52:30": "Voici un exemple de sous-titre généré",
"03:52:35": "Le système fonctionne correctement",
"03:52:40": "Whisper traite les fichiers audio",
"03:58:02": "elles sont marquées dune encore un droite et vas-y je nai même pas vu une tatouée jungle lendroit où est la fenêtre non il",
"04:04:51": "Oh il a pas de kit Ah putain ouais bah Jai besoin des tatouages exotiques mais joublie où est la fenêtre Hein ? Ça veut dire quoi",
"04:10:30": "Ah zut où est-ce que jai mis ma fenêtre à jouer des tatouages ? Ça ne maide rien. Vraiment cest tatouage hein lui Cest exotique.",
"04:11:07": "Merci à tous.",
"04:11:44": "comment ça se passe avec son bot on y est là",
"04:16:54": "Sous-titrage ST 501",
"04:17:32": "un peu con première la pertinence des réponses en effort supplémentaire de lutilisateur ouais ok mais sortie doù le truc exotique",
"04:18:11": "cest un machin exotique ton bot il parle de tatouage sur Sadu on a pas parlé",
"04:18:47": "Sous-titrage ST 501",
"04:33:10": "Un mois vraiment je lui envoyais des messages il répondait pas quoi. Il est mort. Cest moi. qui le patron ? Elle légendaire cette ref. pour ça que cétait quand du coup. Mais pourquoi parle anglais maintenant encore en vie. Ouais suis"
"00:33:44": "Là tu ne trouves pas assez de poissons cool avant ? Mais oui il faut monter. Tes sans jeu les montées. Parce que je me suis dit peut-être quon va avoir des trucs rares. Oh ! De toute façon elle a maillé. Cest mine ça. Elle te fait la plage. rare. Ah dommage prend elle. Tu contrôles tes bien. Jai contrôlé mais sûr. Ouais ben non. fait.",
"00:34:24": "Hal tes pas contrôle en plus Jai de QN à la putaire Là il y a un coup qui joué Tu essaies te barrer là ? Ouais Cest juste au dessus droite Mais tétais passé par Non non Ah oui ! Dans fente La nez",
"00:35:06": "Moi jpourrais que cétait... Ah ouais rien à voir ! Et toi tes là ? Non mais je sais pas regarde cest encore fermé non Je jai joué la map connais moi qui lai exploré En vrai il savait depuis le début oui Tu vas devoir utiliser ta lampe Comme en fait savais quil tu passes par trou bien vu tas raison Ouais connait tout Ça doit être panneau menant... quon peut y aller avec ce truc",
"00:35:28": "Cest long hein ? Tu tournes en rond quoi. Ah oui. Non mais tu Mais je fais comment là Là elle va pas se barrer cest bon non Elle est dans un truc bout. Oui maides pas. Moi croyais que cétait par la sortie. oui ok retournes effectivement. On tourne de fou. Sous-titrage ST 501",
"00:36:08": "Oh le beau poisson ! Vas-y fume-le Comment je fais ? Et tu vas pas tuer tas que 2 balles mais cest grave Tu finis au... harponne-le go Dash Tes dans lui là quest-ce Mais il maspire",
"00:36:32": "Cest bon ça ? Ça va tas un coquet juste en dessous. Oh R cest bien elle fait... Non non le fais pas maintenant déjà commencé à manger maintenant. si prend... on a quun seul continue continue. Mais je comprends là. Continue quoi qui sest passé prend plus pareil. Si plus. sur elle. truc expliquez ! te ramène poisson. entier direct la base.",
"00:37:16": "Lété par Alada sorti oui ok retourne effectivement du son sous-titrage dST500 merde. Ten fous de le tuer. Vas-y va faire péter ça. Voilà. Faut la pioche. Ouais. Ouais laisse tomber. pêcher pêcher. Mais ça là peut-être que demain ya pas Non mais cest soja là. vas-y prends-le fait un truc pour les recettes. Cest mal. Curcuma. On connait. Ah ouais.",
"00:37:37": "ça prend pas plus juste le poisson direct te ramène hein cest quand tu as les crabes bah comme peux prendre munitions à côté faut que mettes assez haut en fait bien un truc quon peut arrêter long tournes rond quoi ah oui non je sais comment là elle va se barrer bon heeeeeee",
"00:38:25": "On reconnaît quand même est des croustos on pas Gingembre Ouais gingembre surtout Vas-y motte oh petite caisse Là ya une pioche Non prends la cest sûr quil y a 100% Oh vas-y le 10 de dégâts mieux que batte Et top",
"00:38:48": "Amélioration de Warpant ! 13 dégâts en plus je suis pas tabassé Vas-y monte On va chasser du... Oh ça Cest cest cest... Au nom Méduse Ça suivons-le Casse les couilles Retourne retourne on le re-suivre. Ils se préparent à avoir des tortues. Des tortues ? Ben oui ce quils disaient.",
"00:39:27": "Si on a de la tortue... On repasse au point... pète les couilles ! Oh 16 dégâts vas-y prends 7 si je peux plus...",
"00:39:46": "Oh oh mais non prends le comme ça on a plan En vrai tu peux reprendre attends essaye de tirer une fois avec Non cest pas Ok vas-y re-change remets toi en contre",
"00:40:24": "Oh une piège Je peux aller pêcher le gros caillou si tu en veux Ah habitation ça il faut les prendre trucs comme",
"00:40:44": "On na jamais pris ça Si moi je les prends à chaque fois Mais cest pour lémission quon sen bat couilles là Floé dit Ouais ouais vrai lécologie quest-ce fouille Oh la tortue Tu vas tuer toi",
"00:41:24": "Mange-la mange-la ! Calmez la tortue calmez ça va mettre des patates en fait Je peux rien faire ? Vas-y cest de lapprocher. Ah faut que tu tattaches à pour ralentir. comment fais Bah capter une minute. Mais il est ouais faites pas chez vous",
"17:22:02": "Sous-titres par Jérémy Diaz",
"17:22:53": "La carte ciblée se retrouve à 100% de ses HP max Ça cest exceptionnel les gars Genre là tous 7 tours tu reviens full vie Et NaoA qui tape 20 Cest Mais dégâts augmentent base vraiment fort jaime beaucoup cette en vrai va partir Oula Ok alors comment on cook ça On prendre le roi Le problème que un peu bizarre 40 et après entre 1 lumière Donc ombre plus bon",
"17:23:41": "Après il faut que je teste la mécanique de fumée donc en vrai vais aller découvrir nouvelle Et ça cest fort non vas-y faire un deck full on comme On va voir ce donne toute façon maintenant le in-game avoir pas mal dimpact Alors vous présenter les nouveautés Directement adversaire bien sûr Regardez regardez stylé par contre jai oublié mettre mon visuel mis à moi Ok est",
"17:24:08": "Oh là il y a une légendaire donc la rareté maintenant cest le truc qui est en dessous Donc rare et deux communes Moi jai rares épique trois moi les gars Jai Euh... Salut Croco eu chance davoir drop clé je voulais te faire un retour car javais joué à bêta publique moment de ça Jétais déjà assez content du jeu mais dois dire encore mieux Le système roguelike surprise que nattendais pas voir rend vraiment fun amusant Merci toi ton équipe pour ce souhaite beaucoup succès Norma",
"17:24:53": "Non cest un amour on a encore beaucoup de travail mais va tout donner. Alors mon deck ah bah simple jai rien up. Voilà super Croco merci pour ce tour. Allez magnifique très bon premier tour se régale en cas. ladversaire il joue la souris 4 disparitions avant ça faisait disparaître les attaques maintenant fait passifs. Donc gros là certainement faire ma fumée qui que je naurai plus fumée. Mais ne peut attaques. éternité augmente dun vous voyez mes tours.",
"17:25:18": "Disparition à un moment ou autre et pour linstant profitons de cette gêne ombre 1 par tour cest pas grand chose mais ça fait du bien lui il a acheté cimetière quand une carte meurt va gagner 6 dans chaque élément moi exemple le coeur dombre je gagne Petite potion alors qui me péter les couilles game Nananabidule en vrai on peut laisser la fin pense que vais attaquer non souris allez attaque oula ok grave bug avec attend",
"17:25:41": "là sur la carte cest 2 et si jamais il mattaque avec éternité en passif je vais passer de à 3 donc ça augmente les CD que tu vises nous sommes au premier tour du shop avons 63 thunes premiers achats le coeur dombre mesdames messieurs qui génère un par jeu très bon achat puisque jai deck composé uniquement aller placer tranquillement alors malheureusement elle va certainement se faire attaquer 10",
"17:26:24": "Non on va attaquer avec ça donc tape 40 et ensuite entre 1 Oh cest la fumée ? Attends pas mal non Cest il y a une belle amélioration de en vrai. Ah par contre encore des problèmes son là Combien 30 000 balles du côté Chiche. Putain je suis dégoûté Je"
}
+38 -2
View File
@@ -76,6 +76,11 @@
<div class="mt-2">
<small class="text-muted" id="autoSubtitleStatus">Arrêté</small>
</div>
<div class="mt-2">
<button class="btn btn-warning btn-sm w-100" onclick="forceStopAutoSubtitle()" title="Forcer l'arrêt en cas de problème">
<i class="fas fa-stop-circle me-1"></i>Force Stop
</button>
</div>
</div>
<!-- Auto Message Sending Toggle -->
@@ -102,12 +107,40 @@
<div class="d-flex justify-content-between align-items-center">
<span class="small text-muted">Envoi Messages Chat</span>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="chatMessageToggle" onchange="toggleChatMessage()" checked>
<input class="form-check-input" type="checkbox" id="chatMessageToggle" onchange="toggleChatMessage()">
<label class="form-check-label small" for="chatMessageToggle"></label>
</div>
</div>
<div class="mt-2">
<small class="text-muted" id="chatMessageStatus">Activé</small>
<small class="text-muted" id="chatMessageStatus">Désactivé</small>
</div>
</div>
<!-- IA Generator Control -->
<div class="mt-3">
<div class="d-flex justify-content-between align-items-center">
<span class="small text-muted">Générateur IA</span>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="iaGeneratorToggle" onchange="toggleIAGenerator()">
<label class="form-check-label small" for="iaGeneratorToggle"></label>
</div>
</div>
<div class="mt-2">
<small class="text-muted" id="iaGeneratorStatus">Arrêté</small>
</div>
</div>
<!-- Control Twitch Control -->
<div class="mt-3">
<div class="d-flex justify-content-between align-items-center">
<span class="small text-muted">Contrôleur Twitch</span>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="controlTwitchToggle" onchange="toggleControlTwitch()">
<label class="form-check-label small" for="controlTwitchToggle"></label>
</div>
</div>
<div class="mt-2">
<small class="text-muted" id="controlTwitchStatus">Arrêté</small>
</div>
</div>
</div>
@@ -280,6 +313,9 @@
<button class="btn btn-primary" onclick="processSubtitles()">
<i class="fas fa-cogs me-2"></i>Traitement Manuel
</button>
<button class="btn btn-danger" onclick="clearSubtitlesHistory()">
<i class="fas fa-trash me-2"></i>Nettoyer Historique
</button>
</div>
</div>
</div>
-118
View File
@@ -1,118 +0,0 @@
#!/usr/bin/env python3
"""
Script de test pour l'envoi automatique de messages
"""
import os
import json
import time
from datetime import datetime
def test_auto_message_system():
"""Test du système d'envoi automatique de messages"""
print("🧪 Test du système d'envoi automatique de messages")
print("=" * 60)
# 1. Vérifier les fichiers de configuration
user_config = "config/user.json"
if not os.path.exists(user_config):
print(f"❌ Fichier de configuration utilisateur non trouvé: {user_config}")
return False
print("✅ Fichier de configuration utilisateur trouvé")
# 2. Vérifier les générations disponibles
storage_dir = "storage"
generation_file = os.path.join(storage_dir, "IA_generator.json")
if os.path.exists(generation_file):
try:
with open(generation_file, 'r', encoding='utf-8') as f:
generation_data = json.load(f)
print(f"{len(generation_data)} génération(s) disponible(s)")
if generation_data:
sorted_keys = sorted(generation_data.keys())
last_generation = generation_data[sorted_keys[-1]]
print(f"📝 Dernière génération: {last_generation}")
except Exception as e:
print(f"⚠️ Erreur lecture générations: {e}")
else:
print("📝 Aucune génération disponible")
# 3. Simuler l'envoi automatique
print("\n🔄 Simulation de l'envoi automatique:")
print(" 1. Surveillance des nouvelles générations")
print(" 2. Envoi automatique avec le premier utilisateur")
print(" 3. Suppression de la génération après envoi")
print(" 4. Attente de 10 secondes entre chaque envoi")
return True
def demo_auto_message_interface():
"""Démonstration de l'interface d'envoi automatique"""
print("\n🌐 Démonstration de l'interface:")
print(" 1. Ouvrir http://localhost:5000")
print(" 2. Dans le tableau de bord (sidebar gauche)")
print(" 3. Trouver le switch 'Envoi Auto Messages'")
print(" 4. Activer le switch pour démarrer l'envoi automatique")
print(" 5. Les messages seront envoyés automatiquement quand des générations sont disponibles")
print("\n📋 Fonctionnalités ajoutées:")
print(" ✅ Bouton slide pour l'envoi automatique de messages")
print(" ✅ Surveillance des générations IA")
print(" ✅ Envoi automatique avec le premier utilisateur")
print(" ✅ Suppression automatique des générations envoyées")
print(" ✅ Délai de 10 secondes entre chaque envoi")
print(" ✅ Retour en temps réel via Socket.IO")
print(" ✅ Gestion des erreurs d'envoi")
def test_message_bot():
"""Test du bot de messages"""
print("\n🤖 Test du bot de messages:")
try:
from fonction.first_class import messageTwitch
# Créer une instance du bot de messages
message_bot = messageTwitch("config/user.json", "default")
print("✅ Bot de messages créé avec succès")
# Vérifier les utilisateurs disponibles
with open("config/user.json", 'r') as f:
users = json.load(f)
print(f"{len(users)} utilisateur(s) configuré(s)")
for i, user in enumerate(users):
print(f" {i}: {user['tw_acc_pseudo']} {user['charactere']}")
return True
except Exception as e:
print(f"❌ Erreur lors du test du bot: {e}")
return False
if __name__ == '__main__':
print("🚀 Test du système d'envoi automatique de messages")
print("=" * 60)
# Test du système de base
system_ok = test_auto_message_system()
# Test du bot de messages
bot_ok = test_message_bot()
# Démonstration de l'interface
demo_auto_message_interface()
print("\n" + "=" * 60)
if system_ok and bot_ok:
print("✅ Test réussi !")
print("🎉 Le système d'envoi automatique de messages est prêt")
print("💡 Utilisez le switch dans l'interface web pour l'activer")
else:
print("❌ Problèmes détectés")
if not system_ok:
print(" - Problème avec le système de base")
if not bot_ok:
print(" - Problème avec le bot de messages")
-154
View File
@@ -1,154 +0,0 @@
#!/usr/bin/env python3
"""
Script de test pour la génération automatique de sous-titres
"""
import subprocess
import os
import json
import time
from datetime import datetime
def test_auto_subtitle_system():
"""Test du système de génération automatique de sous-titres"""
print("🧪 Test du système de génération automatique de sous-titres")
print("=" * 60)
# 1. Vérifier les fichiers audio disponibles
record_dir = "record"
if not os.path.exists(record_dir):
print(f"❌ Dossier record non trouvé: {record_dir}")
return False
audio_files = [f for f in os.listdir(record_dir) if f.endswith('.mp3')]
if not audio_files:
print(f"❌ Aucun fichier audio trouvé dans {record_dir}")
return False
print(f"{len(audio_files)} fichiers audio trouvés")
print(f"📁 Premier fichier: {audio_files[0]}")
# 2. Simuler le traitement d'un fichier
test_file = audio_files[0]
audio_path = os.path.join(record_dir, test_file)
print(f"\n🎵 Simulation du traitement de: {test_file}")
try:
# Lancer Whisper
command = [
'whisper',
'--language', 'fr',
audio_path,
'--device', 'cuda',
'--model', 'large-v3'
]
print(f"📝 Commande: {' '.join(command)}")
print("⏳ Traitement en cours...")
result = subprocess.run(command, capture_output=True, text=True, timeout=60)
if result.returncode == 0:
print("✅ Whisper a fonctionné avec succès")
# Lire le fichier .txt généré
txt_file = test_file.replace('.mp3', '.txt')
if os.path.exists(txt_file):
with open(txt_file, 'r', encoding='utf-8') as f:
content = f.read().strip()
print(f"📝 Contenu généré: {content}")
# Nettoyer le contenu
content = content.replace("'", "").replace('"', "").replace("\n", " ").replace(",", "")
# Supprimer les répétitions de mots
words = content.split()
seen = set()
result_words = []
for word in words:
if word not in seen:
result_words.append(word)
seen.add(word)
cleaned_content = " ".join(result_words)
print(f"🧹 Contenu nettoyé: {cleaned_content}")
# Sauvegarder dans le stockage
current_time = datetime.now().strftime('%H:%M:%S')
# Sauvegarder dans le fichier de stockage
storage_dir = "storage"
if not os.path.exists(storage_dir):
os.makedirs(storage_dir)
subtitle_file = os.path.join(storage_dir, "subtitle_data.json")
try:
with open(subtitle_file, 'r', encoding='utf-8') as f:
existing_data = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
existing_data = {}
existing_data[current_time] = cleaned_content
with open(subtitle_file, 'w', encoding='utf-8') as f:
json.dump(existing_data, f, indent=4, ensure_ascii=False)
print(f"💾 Sous-titre sauvegardé à {current_time}")
# Nettoyer les fichiers temporaires
os.remove(txt_file)
print("🧹 Fichier temporaire nettoyé")
return True
else:
print("⚠️ Aucun fichier .txt généré")
return False
else:
print(f"❌ Erreur Whisper: {result.stderr}")
return False
except subprocess.TimeoutExpired:
print("⏰ Timeout - Whisper a pris trop de temps")
return False
except Exception as e:
print(f"❌ Erreur: {e}")
return False
def demo_auto_subtitle_interface():
"""Démonstration de l'interface de génération automatique"""
print("\n🌐 Démonstration de l'interface:")
print(" 1. Ouvrir http://localhost:5000")
print(" 2. Dans le tableau de bord (sidebar gauche)")
print(" 3. Trouver le switch 'Génération Auto Sous-titres'")
print(" 4. Activer le switch pour démarrer la génération automatique")
print(" 5. Aller dans l'onglet 'Sous-titres' pour voir le fichier en cours")
print(" 6. Les sous-titres seront créés automatiquement fichier par fichier")
print("\n📋 Fonctionnalités ajoutées:")
print(" ✅ Bouton slide dans le tableau de bord")
print(" ✅ Indicateur de fichier en cours de traitement")
print(" ✅ Traitement automatique fichier par fichier")
print(" ✅ Retour en temps réel via Socket.IO")
print(" ✅ Sauvegarde automatique dans le stockage")
print(" ✅ Nettoyage automatique des fichiers temporaires")
if __name__ == '__main__':
print("🚀 Test du système de génération automatique de sous-titres")
print("=" * 60)
# Test du traitement automatique
success = test_auto_subtitle_system()
# Démonstration de l'interface
demo_auto_subtitle_interface()
print("\n" + "=" * 60)
if success:
print("✅ Test réussi !")
print("🎉 Le système de génération automatique est prêt")
print("💡 Utilisez le switch dans l'interface web pour l'activer")
else:
print("❌ Test échoué !")
print("🔧 Vérifiez que Whisper fonctionne correctement")
-109
View File
@@ -1,109 +0,0 @@
#!/usr/bin/env python3
"""
Script de test pour vérifier le toggle d'envoi de messages chat
"""
import requests
import json
import time
BASE_URL = "http://localhost:5000"
def test_chat_messages_toggle():
"""Test du toggle d'envoi de messages chat"""
print("🧪 Test du toggle d'envoi de messages chat")
print("=" * 50)
# Test 1: Vérifier le statut initial
print("1. Vérification du statut initial...")
try:
response = requests.get(f"{BASE_URL}/api/chat/messages/status")
if response.status_code == 200:
status = response.json()
print(f" ✓ Statut initial: {'Activé' if status['enabled'] else 'Désactivé'}")
else:
print(f" ✗ Erreur: {response.status_code}")
return False
except Exception as e:
print(f" ✗ Erreur de connexion: {e}")
return False
# Test 2: Désactiver l'envoi de messages
print("2. Désactivation de l'envoi de messages...")
try:
response = requests.post(f"{BASE_URL}/api/chat/messages/disable")
if response.status_code == 200:
result = response.json()
print(f"{result['message']}")
else:
print(f" ✗ Erreur: {response.status_code}")
return False
except Exception as e:
print(f" ✗ Erreur: {e}")
return False
# Test 3: Vérifier que c'est bien désactivé
print("3. Vérification de la désactivation...")
try:
response = requests.get(f"{BASE_URL}/api/chat/messages/status")
if response.status_code == 200:
status = response.json()
if not status['enabled']:
print(" ✓ Envoi de messages désactivé avec succès")
else:
print(" ✗ L'envoi de messages n'a pas été désactivé")
return False
else:
print(f" ✗ Erreur: {response.status_code}")
return False
except Exception as e:
print(f" ✗ Erreur: {e}")
return False
# Test 4: Réactiver l'envoi de messages
print("4. Réactivation de l'envoi de messages...")
try:
response = requests.post(f"{BASE_URL}/api/chat/messages/enable")
if response.status_code == 200:
result = response.json()
print(f"{result['message']}")
else:
print(f" ✗ Erreur: {response.status_code}")
return False
except Exception as e:
print(f" ✗ Erreur: {e}")
return False
# Test 5: Vérifier que c'est bien réactivé
print("5. Vérification de la réactivation...")
try:
response = requests.get(f"{BASE_URL}/api/chat/messages/status")
if response.status_code == 200:
status = response.json()
if status['enabled']:
print(" ✓ Envoi de messages réactivé avec succès")
else:
print(" ✗ L'envoi de messages n'a pas été réactivé")
return False
else:
print(f" ✗ Erreur: {response.status_code}")
return False
except Exception as e:
print(f" ✗ Erreur: {e}")
return False
print("=" * 50)
print("✅ Tous les tests sont passés avec succès !")
return True
if __name__ == "__main__":
print("🤖 Test du système de toggle d'envoi de messages")
print("Assurez-vous que le serveur web est démarré sur http://localhost:5000")
print()
success = test_chat_messages_toggle()
if success:
print("\n🎉 Le toggle d'envoi de messages fonctionne correctement !")
else:
print("\n❌ Des erreurs ont été détectées lors des tests.")
-129
View File
@@ -1,129 +0,0 @@
#!/usr/bin/env python3
"""
Script de test pour simuler l'API de traitement manuel des sous-titres
"""
import subprocess
import os
import json
from datetime import datetime
def process_subtitles_manual():
"""Simuler le traitement manuel des sous-titres"""
print("🧪 Test du traitement manuel des sous-titres")
print("=" * 50)
# Vérifier que le dossier record existe
record_dir = "record"
if not os.path.exists(record_dir):
print(f"❌ Dossier record non trouvé: {record_dir}")
return False
# Trouver les fichiers audio
audio_files = [f for f in os.listdir(record_dir) if f.endswith('.mp3')]
if not audio_files:
print(f"❌ Aucun fichier audio trouvé dans {record_dir}")
return False
print(f"{len(audio_files)} fichiers audio trouvés")
subtitles_created = 0
subtitles_data = {}
# Traiter chaque fichier audio (limiter à 2 pour le test)
for audio_file in audio_files[:2]:
audio_path = os.path.join(record_dir, audio_file)
print(f"🎵 Traitement de: {audio_file}")
try:
# Lancer Whisper
command = [
'whisper',
'--language', 'fr',
audio_path,
'--device', 'cuda',
'--model', 'large-v3'
]
print(f"📝 Commande: {' '.join(command)}")
result = subprocess.run(command, capture_output=True, text=True, timeout=60)
if result.returncode == 0:
# Lire le fichier .txt généré
txt_file = audio_file.replace('.mp3', '.txt')
if os.path.exists(txt_file):
with open(txt_file, 'r', encoding='utf-8') as f:
content = f.read().strip()
print(f"📝 Contenu brut: {content}")
# Nettoyer le contenu
content = content.replace("'", "").replace('"', "").replace("\n", " ").replace(",", "")
# Supprimer les répétitions de mots
words = content.split()
seen = set()
result_words = []
for word in words:
if word not in seen:
result_words.append(word)
seen.add(word)
cleaned_content = " ".join(result_words)
print(f"🧹 Contenu nettoyé: {cleaned_content}")
# Sauvegarder dans le stockage
current_time = datetime.now().strftime('%H:%M:%S')
subtitles_data[current_time] = cleaned_content
# Sauvegarder dans le fichier de stockage
storage_dir = "storage"
if not os.path.exists(storage_dir):
os.makedirs(storage_dir)
subtitle_file = os.path.join(storage_dir, "subtitle_data.json")
try:
with open(subtitle_file, 'r', encoding='utf-8') as f:
existing_data = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
existing_data = {}
existing_data[current_time] = cleaned_content
with open(subtitle_file, 'w', encoding='utf-8') as f:
json.dump(existing_data, f, indent=4, ensure_ascii=False)
subtitles_created += 1
print(f"✅ Sous-titre créé et sauvegardé")
# Nettoyer les fichiers temporaires
os.remove(txt_file)
os.remove(audio_path) # Supprimer le fichier audio traité
print(f"🧹 Fichiers temporaires nettoyés")
else:
print(f"⚠️ Aucun fichier .txt généré pour {audio_file}")
else:
print(f"❌ Erreur Whisper: {result.stderr}")
except subprocess.TimeoutExpired:
print(f"⏰ Timeout pour {audio_file}")
continue
except Exception as e:
print(f"❌ Erreur pour {audio_file}: {e}")
continue
print(f"\n📊 Résumé: {subtitles_created} sous-titre(s) créé(s)")
print("📝 Sous-titres générés:")
for time_key, text in subtitles_data.items():
print(f" {time_key}: {text}")
return subtitles_created > 0
if __name__ == '__main__':
success = process_subtitles_manual()
if success:
print("\n✅ Test réussi ! Le traitement manuel fonctionne.")
else:
print("\n❌ Test échoué !")
-79
View File
@@ -1,79 +0,0 @@
#!/usr/bin/env python3
"""
Script de test pour le traitement manuel des sous-titres
"""
import os
import sys
import json
# Ajouter le chemin vers les modules
sys.path.append('.')
def test_manual_subtitle_processing():
"""Test du traitement manuel des sous-titres"""
print("🧪 Test du traitement manuel des sous-titres")
print("=" * 50)
# Vérifier que le fichier de configuration existe
config_file = "config/config.json"
if not os.path.exists(config_file):
print(f"❌ Fichier de configuration non trouvé: {config_file}")
return False
# Vérifier que le dossier record existe et contient des fichiers
record_dir = "record"
if not os.path.exists(record_dir):
print(f"❌ Dossier record non trouvé: {record_dir}")
return False
audio_files = [f for f in os.listdir(record_dir) if f.endswith('.mp3')]
if not audio_files:
print(f"❌ Aucun fichier audio trouvé dans {record_dir}")
return False
print(f"{len(audio_files)} fichiers audio trouvés")
print("📁 Fichiers audio disponibles:")
for file in audio_files[:5]: # Afficher les 5 premiers fichiers
print(f" - {file}")
# Créer une instance du bot de sous-titres
try:
from fonction.first_class import Subtitle_translation
subtitle_bot = Subtitle_translation(config_file)
print("✅ Bot de sous-titres créé avec succès")
# Lancer le traitement manuel
print("🔍 Lancement du traitement manuel...")
subtitle_bot.verif_file_transcribe()
# Vérifier si des sous-titres ont été créés
if subtitle_bot.subtitle:
print("✅ Sous-titres créés avec succès")
print("📝 Sous-titres générés:")
for time_key, text in subtitle_bot.subtitle.items():
print(f" {time_key}: {text}")
else:
print("⚠️ Aucun sous-titre créé")
# Vérifier le stockage
from fonction.first_class import storage
subtitle_data = storage.read("subtitle_data")
if subtitle_data:
print(f"💾 {len(subtitle_data)} sous-titre(s) sauvegardé(s) dans le stockage")
return True
except Exception as e:
print(f"❌ Erreur lors du test: {e}")
import traceback
traceback.print_exc()
return False
if __name__ == '__main__':
success = test_manual_subtitle_processing()
if success:
print("\n✅ Test réussi !")
else:
print("\n❌ Test échoué !")
-38
View File
@@ -1,38 +0,0 @@
#!/usr/bin/env python3
"""
Script de test pour vérifier l'envoi de messages
"""
import sys
import os
# Ajouter le chemin vers les modules
sys.path.append('.')
from fonction.first_class import messageTwitch
def test_send_message():
"""Test de l'envoi de message"""
try:
# Créer une instance de messageTwitch
msg_bot = messageTwitch("config/user.json", "test_channel")
# Tester l'envoi d'un message
print("Test d'envoi de message...")
msg_bot.send_message("Test message from bot")
print("✓ Test réussi !")
except Exception as e:
print(f"✗ Erreur lors du test: {e}")
return False
return True
if __name__ == "__main__":
print("🧪 Test de l'envoi de messages")
print("=" * 40)
if test_send_message():
print("\n✅ Tous les tests sont passés !")
else:
print("\n❌ Certains tests ont échoué.")
-69
View File
@@ -1,69 +0,0 @@
#!/usr/bin/env python3
"""
Script de test pour vérifier le fonctionnement du bot de sous-titres
"""
import os
import sys
import time
# Ajouter le chemin vers les modules
sys.path.append('.')
from fonction.first_class import Subtitle_translation
def test_subtitle_bot():
"""Test du bot de sous-titres"""
print("🧪 Test du bot de sous-titres")
print("=" * 50)
# Vérifier que le fichier de configuration existe
config_file = "config/config.json"
if not os.path.exists(config_file):
print(f"❌ Fichier de configuration non trouvé: {config_file}")
return False
# Vérifier que le dossier record existe et contient des fichiers
record_dir = "record"
if not os.path.exists(record_dir):
print(f"❌ Dossier record non trouvé: {record_dir}")
return False
audio_files = [f for f in os.listdir(record_dir) if f.endswith('.mp3')]
if not audio_files:
print(f"❌ Aucun fichier audio trouvé dans {record_dir}")
return False
print(f"{len(audio_files)} fichiers audio trouvés")
# Créer une instance du bot de sous-titres
try:
subtitle_bot = Subtitle_translation(config_file)
print("✅ Bot de sous-titres créé avec succès")
# Tester la méthode verif_file_transcribe
print("🔍 Test de la vérification des fichiers...")
subtitle_bot.verif_file_transcribe()
# Vérifier si des sous-titres ont été créés
if subtitle_bot.subtitle:
print("✅ Sous-titres créés avec succès")
for time_key, text in subtitle_bot.subtitle.items():
print(f" {time_key}: {text}")
else:
print("⚠️ Aucun sous-titre créé")
return True
except Exception as e:
print(f"❌ Erreur lors du test: {e}")
import traceback
traceback.print_exc()
return False
if __name__ == '__main__':
success = test_subtitle_bot()
if success:
print("\n✅ Test réussi !")
else:
print("\n❌ Test échoué !")
-139
View File
@@ -1,139 +0,0 @@
#!/usr/bin/env python3
"""
Script de test direct de Whisper pour la création de sous-titres
"""
import os
import subprocess
import json
import time
def test_whisper_direct():
"""Test direct de Whisper"""
print("🧪 Test direct de Whisper")
print("=" * 50)
# Vérifier que le dossier record existe et contient des fichiers
record_dir = "record"
if not os.path.exists(record_dir):
print(f"❌ Dossier record non trouvé: {record_dir}")
return False
audio_files = [f for f in os.listdir(record_dir) if f.endswith('.mp3')]
if not audio_files:
print(f"❌ Aucun fichier audio trouvé dans {record_dir}")
return False
print(f"{len(audio_files)} fichiers audio trouvés")
# Prendre le premier fichier pour le test
test_file = audio_files[0]
test_file_path = os.path.join(record_dir, test_file)
print(f"🎵 Test avec le fichier: {test_file}")
# Test direct de Whisper
try:
print("🔍 Lancement de Whisper...")
command = [
'whisper',
'--language', 'fr',
test_file_path,
'--device', 'cuda',
'--model', 'large-v3'
]
print(f"📝 Commande: {' '.join(command)}")
# Exécuter Whisper
result = subprocess.run(command, capture_output=True, text=True, timeout=60)
if result.returncode == 0:
print("✅ Whisper a fonctionné avec succès")
# Vérifier si un fichier .txt a été créé
txt_file = test_file.replace('.mp3', '.txt')
if os.path.exists(txt_file):
with open(txt_file, 'r', encoding='utf-8') as f:
content = f.read().strip()
print(f"📝 Contenu généré: {content}")
# Nettoyer le fichier de test
os.remove(txt_file)
print("🧹 Fichier de test nettoyé")
return True
else:
print("⚠️ Aucun fichier .txt généré")
return False
else:
print(f"❌ Erreur Whisper: {result.stderr}")
return False
except subprocess.TimeoutExpired:
print("⏰ Timeout - Whisper a pris trop de temps")
return False
except Exception as e:
print(f"❌ Erreur: {e}")
return False
def test_subtitle_storage():
"""Test du stockage des sous-titres"""
print("\n🧪 Test du stockage des sous-titres")
print("=" * 50)
# Créer un fichier de test pour le stockage
storage_dir = "storage"
if not os.path.exists(storage_dir):
os.makedirs(storage_dir)
print(f"✅ Dossier storage créé: {storage_dir}")
# Test d'écriture/lecture
test_data = {
"test_time": "Test de sous-titre",
"test_time_2": "Deuxième test"
}
subtitle_file = os.path.join(storage_dir, "subtitle_data.json")
try:
# Écrire des données de test
with open(subtitle_file, 'w', encoding='utf-8') as f:
json.dump(test_data, f, indent=4, ensure_ascii=False)
print("✅ Données de test écrites")
# Lire les données
with open(subtitle_file, 'r', encoding='utf-8') as f:
read_data = json.load(f)
if read_data == test_data:
print("✅ Lecture/écriture du stockage OK")
return True
else:
print("❌ Données lues différentes des données écrites")
return False
except Exception as e:
print(f"❌ Erreur stockage: {e}")
return False
if __name__ == '__main__':
print("🚀 Test complet du système de sous-titres")
print("=" * 60)
# Test 1: Whisper direct
whisper_ok = test_whisper_direct()
# Test 2: Stockage
storage_ok = test_subtitle_storage()
print("\n" + "=" * 60)
if whisper_ok and storage_ok:
print("✅ Tous les tests sont réussis !")
print("🎉 Le système de sous-titres est prêt à fonctionner")
else:
print("❌ Certains tests ont échoué")
if not whisper_ok:
print(" - Whisper ne fonctionne pas correctement")
if not storage_ok:
print(" - Le stockage ne fonctionne pas correctement")
+276 -7
View File
@@ -25,6 +25,10 @@ class BotController:
self.bots = {} # Stockage des instances de bots (pour l'utilisation interne)
self.flux_list = [] # Liste des flux surveillés (pour l'API JSON)
self.config = self.load_config()
self.ia_generator = None
self.control_twitch = None
self.ia_generator_running = False
self.control_twitch_running = False
def load_config(self):
try:
@@ -37,6 +41,21 @@ class BotController:
with open('config/config.json', 'w') as file:
json.dump(self.config, file, indent=4, ensure_ascii=False)
def get_system_status(self):
"""Obtenir le statut de tous les composants"""
return {
'ia_generator': {
'running': self.ia_generator_running,
'status': 'En cours' if self.ia_generator_running else 'Arrêté'
},
'control_twitch': {
'running': self.control_twitch_running,
'status': 'En cours' if self.control_twitch_running else 'Arrêté'
},
'flux_count': len(self.flux_list),
'active_flux': len([f for f in self.flux_list if f['active']])
}
def add_flux(self, channel_name, record_audio=True):
flux_id = len(self.flux_list) + 1
@@ -140,6 +159,112 @@ class BotController:
# Retourner seulement les données JSON (pas les instances de bots)
return self.flux_list
def start_ia_generator(self):
"""Démarrer le générateur IA de manière contrôlée"""
if self.ia_generator_running:
return False, "IA Generator déjà en cours d'exécution"
try:
self.ia_generator = IA_generator("config/config.json")
self.ia_generator_running = True
# Activer l'envoi de messages quand l'IA Generator est démarré
global chat_messages_enabled
chat_messages_enabled = True
# Démarrer dans un thread séparé
threading.Thread(target=self._ia_generator_loop, daemon=True).start()
print(f"[{datetime.now().strftime('%H:%M:%S')}] IA Generator démarré")
return True, "IA Generator démarré avec succès"
except Exception as e:
self.ia_generator_running = False
return False, f"Erreur lors du démarrage de l'IA Generator: {str(e)}"
def stop_ia_generator(self):
"""Arrêter le générateur IA"""
if not self.ia_generator_running:
return False, "IA Generator n'est pas en cours d'exécution"
try:
self.ia_generator_running = False
if self.ia_generator:
self.ia_generator.stop()
# Désactiver l'envoi de messages quand l'IA Generator est arrêté
global chat_messages_enabled
chat_messages_enabled = False
print(f"[{datetime.now().strftime('%H:%M:%S')}] IA Generator arrêté")
return True, "IA Generator arrêté avec succès"
except Exception as e:
return False, f"Erreur lors de l'arrêt de l'IA Generator: {str(e)}"
def _ia_generator_loop(self):
"""Boucle contrôlée pour l'IA Generator"""
while self.ia_generator_running:
try:
if self.ia_generator:
self.ia_generator.main_ask("") # Génération automatique
time.sleep(20) # Attendre 20 secondes entre les générations
except Exception as e:
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur dans IA Generator: {e}")
time.sleep(10)
def start_control_twitch(self):
"""Démarrer le contrôleur Twitch de manière contrôlée"""
if self.control_twitch_running:
return False, "Control Twitch déjà en cours d'exécution"
try:
# Utiliser le premier utilisateur par défaut
self.control_twitch = messageTwitch("config/user.json", "default")
self.control_twitch_running = True
# Démarrer dans un thread séparé
threading.Thread(target=self._control_twitch_loop, daemon=True).start()
print(f"[{datetime.now().strftime('%H:%M:%S')}] Control Twitch démarré")
return True, "Control Twitch démarré avec succès"
except Exception as e:
self.control_twitch_running = False
return False, f"Erreur lors du démarrage de Control Twitch: {str(e)}"
def stop_control_twitch(self):
"""Arrêter le contrôleur Twitch"""
if not self.control_twitch_running:
return False, "Control Twitch n'est pas en cours d'exécution"
try:
self.control_twitch_running = False
if self.control_twitch:
self.control_twitch.stop()
print(f"[{datetime.now().strftime('%H:%M:%S')}] Control Twitch arrêté")
return True, "Control Twitch arrêté avec succès"
except Exception as e:
return False, f"Erreur lors de l'arrêt de Control Twitch: {str(e)}"
def _control_twitch_loop(self):
"""Boucle contrôlée pour Control Twitch"""
while self.control_twitch_running:
try:
if self.control_twitch:
# Vérifier s'il y a des générations à envoyer
generation_data = storage.read("IA_generator")
if generation_data:
sorted_keys = sorted(generation_data.keys())
if sorted_keys:
last_generation = generation_data[sorted_keys[-1]]
# Envoyer le message avec le premier utilisateur
self.control_twitch.send_message_user(0, last_generation)
# Supprimer la génération envoyée
storage.delete("IA_generator", sorted_keys[-1])
print(f"[{datetime.now().strftime('%H:%M:%S')}] Message envoyé: {last_generation[:50]}...")
time.sleep(10) # Attendre 10 secondes entre les vérifications
except Exception as e:
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur dans Control Twitch: {e}")
time.sleep(10)
bot_controller = BotController()
@app.route('/')
@@ -372,6 +497,33 @@ def get_subtitles():
data = storage.read("subtitle_data")
return jsonify(data)
@app.route('/api/subtitles/clear', methods=['POST'])
def clear_subtitles():
"""Nettoyer l'historique des sous-titres"""
try:
# Récupérer toutes les clés de sous-titres
subtitle_data = storage.read("subtitle_data")
# Supprimer chaque clé une par une
for key in list(subtitle_data.keys()):
storage.delete("subtitle_data", key)
# Supprimer également le fichier JSON s'il existe
storage_dir = "storage"
subtitle_file = os.path.join(storage_dir, "subtitle_data.json")
if os.path.exists(subtitle_file):
os.remove(subtitle_file)
return jsonify({
'success': True,
'message': 'Historique des sous-titres nettoyé avec succès'
})
except Exception as e:
return jsonify({
'success': False,
'error': f'Erreur lors du nettoyage: {str(e)}'
}), 500
@app.route('/api/subtitles/process', methods=['POST'])
def process_subtitles():
"""Lancer manuellement le traitement des sous-titres"""
@@ -643,21 +795,32 @@ auto_message_running = False
current_message_bot = None
# Variable globale pour contrôler l'envoi de messages dans le chat
chat_messages_enabled = True
chat_messages_enabled = False
@app.route('/api/subtitles/auto/start', methods=['POST'])
def start_auto_subtitle():
"""Démarrer la génération automatique de sous-titres"""
global auto_subtitle_running
try:
# Vérifier si déjà en cours
if auto_subtitle_running:
return jsonify({
'success': False,
'error': 'La génération automatique est déjà en cours'
}), 400
auto_subtitle_running = True
print(f"[{datetime.now().strftime('%H:%M:%S')}] Démarrage de la génération automatique de sous-titres")
# Démarrer le thread de génération automatique
threading.Thread(target=auto_subtitle_loop, daemon=True).start()
return jsonify({
'success': True,
'message': 'Génération automatique démarrée'
})
except Exception as e:
auto_subtitle_running = False
return jsonify({
'success': False,
'error': f'Erreur lors du démarrage: {str(e)}'
@@ -668,7 +831,15 @@ def stop_auto_subtitle():
"""Arrêter la génération automatique de sous-titres"""
global auto_subtitle_running
try:
if not auto_subtitle_running:
return jsonify({
'success': False,
'error': 'La génération automatique n\'est pas en cours'
}), 400
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt de la génération automatique de sous-titres")
auto_subtitle_running = False
return jsonify({
'success': True,
'message': 'Génération automatique arrêtée'
@@ -679,6 +850,25 @@ def stop_auto_subtitle():
'error': f'Erreur lors de l\'arrêt: {str(e)}'
}), 500
@app.route('/api/subtitles/auto/force-stop', methods=['POST'])
def force_stop_auto_subtitle():
"""Forcer l'arrêt de la génération automatique de sous-titres"""
global auto_subtitle_running, current_processing_file
try:
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt forcé de la génération automatique de sous-titres")
auto_subtitle_running = False
current_processing_file = None
return jsonify({
'success': True,
'message': 'Arrêt forcé de la génération automatique de sous-titres'
})
except Exception as e:
return jsonify({
'success': False,
'error': f'Erreur lors de l\'arrêt forcé: {str(e)}'
}), 500
@app.route('/api/subtitles/auto/status', methods=['GET'])
def get_auto_subtitle_status():
"""Obtenir le statut de la génération automatique"""
@@ -692,6 +882,8 @@ def auto_subtitle_loop():
"""Boucle de génération automatique de sous-titres"""
global auto_subtitle_running, current_processing_file
print(f"[{datetime.now().strftime('%H:%M:%S')}] Démarrage de la boucle de génération automatique de sous-titres")
while auto_subtitle_running:
try:
# Vérifier s'il y a des fichiers audio à traiter
@@ -709,6 +901,8 @@ def auto_subtitle_loop():
audio_file = audio_files[0]
current_processing_file = audio_file
print(f"[{datetime.now().strftime('%H:%M:%S')}] Traitement de: {audio_file}")
# Émettre l'événement de début de traitement
socketio.emit('subtitle_processing_start', {
'file': audio_file,
@@ -719,7 +913,7 @@ def auto_subtitle_loop():
audio_path = os.path.join(record_dir, audio_file)
try:
# Lancer Whisper
# Lancer Whisper avec vérification périodique de l'arrêt
command = [
'whisper',
'--language', 'fr',
@@ -728,9 +922,30 @@ def auto_subtitle_loop():
'--model', 'large-v3'
]
result = subprocess.run(command, capture_output=True, text=True, timeout=60)
# Utiliser Popen pour pouvoir interrompre le processus
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if result.returncode == 0:
# Attendre la fin du processus avec vérification périodique
while process.poll() is None:
if not auto_subtitle_running:
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt demandé, interruption du processus Whisper")
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
break
time.sleep(1)
# Si la boucle a été arrêtée, sortir
if not auto_subtitle_running:
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt de la boucle de génération automatique")
break
result = process.returncode
stdout, stderr = process.communicate()
if result == 0:
# Lire le fichier .txt généré
txt_file = audio_file.replace('.mp3', '.txt')
if os.path.exists(txt_file):
@@ -777,6 +992,8 @@ def auto_subtitle_loop():
'timestamp': current_time
})
print(f"[{datetime.now().strftime('%H:%M:%S')}] Sous-titre généré: {cleaned_content}")
# Nettoyer les fichiers temporaires
os.remove(txt_file)
os.remove(audio_path)
@@ -787,38 +1004,49 @@ def auto_subtitle_loop():
'file': audio_file,
'error': 'Aucun fichier .txt généré'
})
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur: Aucun fichier .txt généré")
else:
# Émettre l'événement d'erreur
socketio.emit('subtitle_processing_error', {
'file': audio_file,
'error': f'Erreur Whisper: {result.stderr}'
'error': f'Erreur Whisper: {stderr}'
})
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur Whisper: {stderr}")
except subprocess.TimeoutExpired:
socketio.emit('subtitle_processing_error', {
'file': audio_file,
'error': 'Timeout - Whisper a pris trop de temps'
})
print(f"[{datetime.now().strftime('%H:%M:%S')}] Timeout - Whisper a pris trop de temps")
except Exception as e:
socketio.emit('subtitle_processing_error', {
'file': audio_file,
'error': f'Erreur: {str(e)}'
})
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur lors du traitement: {str(e)}")
current_processing_file = None
# Vérifier à nouveau si la boucle doit continuer
if not auto_subtitle_running:
print(f"[{datetime.now().strftime('%H:%M:%S')}] Arrêt de la boucle de génération automatique")
break
# Attendre avant de traiter le prochain fichier
time.sleep(2)
except Exception as e:
print(f"Erreur dans la boucle de génération automatique: {e}")
print(f"[{datetime.now().strftime('%H:%M:%S')}] Erreur dans la boucle de génération automatique: {e}")
time.sleep(5)
print(f"[{datetime.now().strftime('%H:%M:%S')}] Fin de la boucle de génération automatique de sous-titres")
@app.route('/api/messages/auto/start', methods=['POST'])
def start_auto_message():
"""Démarrer l'envoi automatique de messages"""
global auto_message_running, current_message_bot
global auto_message_running
try:
# Vérifier si déjà en cours
if auto_message_running:
@@ -1013,6 +1241,47 @@ def get_chat_messages_status():
'enabled': chat_messages_enabled
})
@app.route('/api/system-status', methods=['GET'])
def get_system_status():
"""Obtenir le statut de tous les composants"""
return jsonify(bot_controller.get_system_status())
@app.route('/api/ia-generator/start', methods=['POST'])
def start_ia_generator():
"""Démarrer le générateur IA"""
success, message = bot_controller.start_ia_generator()
if success:
# Synchroniser l'état de l'interface web
socketio.emit('ia_generator_status_changed', {
'running': True,
'message': message
})
return jsonify({'success': success, 'message': message})
@app.route('/api/ia-generator/stop', methods=['POST'])
def stop_ia_generator():
"""Arrêter le générateur IA"""
success, message = bot_controller.stop_ia_generator()
if success:
# Synchroniser l'état de l'interface web
socketio.emit('ia_generator_status_changed', {
'running': False,
'message': message
})
return jsonify({'success': success, 'message': message})
@app.route('/api/control-twitch/start', methods=['POST'])
def start_control_twitch():
"""Démarrer le contrôleur Twitch"""
success, message = bot_controller.start_control_twitch()
return jsonify({'success': success, 'message': message})
@app.route('/api/control-twitch/stop', methods=['POST'])
def stop_control_twitch():
"""Arrêter le contrôleur Twitch"""
success, message = bot_controller.stop_control_twitch()
return jsonify({'success': success, 'message': message})
if __name__ == '__main__':
# Démarrer les mises à jour en arrière-plan
update_thread = threading.Thread(target=background_updates, daemon=True)
-11
View File
@@ -1,11 +0,0 @@
{
"14h30m20s": "Salut ! Ça va super bien merci ! 😊",
"14h31m28s": "Ce jeu a l'air génial, bonne chance !",
"14h32m50s": "Ça arrive aux meilleurs, tu vas y arriver !",
"14h33m15s": "Bienvenue dans la communauté ! 🎉",
"14h34m35s": "Waouh cette action était épique ! 🔥",
"14h35m25s": "Bonne idée, change de tactique !",
"14h36m10s": "Bravo ! Tu maîtrises de mieux en mieux",
"14h37m28s": "Toujours là pour aider ! 💪",
"01h40m18s": "Plot twist inattendu ! 😮"
}
-11
View File
@@ -1,11 +0,0 @@
{
"14h30m15s": "Salut les viewers ! Comment ça va aujourd'hui ?",
"14h31m22s": "On va jouer à ce nouveau jeu, j'ai hâte de voir ce que ça donne",
"14h32m45s": "Oh non, je suis mort déjà ! C'est plus dur que je pensais",
"14h33m12s": "Merci pour le follow @nouveau_viewer !",
"14h34m30s": "Cette partie est vraiment intense, regardez ça !",
"14h35m18s": "Je pense qu'on devrait essayer une autre stratégie",
"14h36m05s": "Excellent, on progresse enfin dans ce niveau",
"14h37m22s": "N'hésitez pas à poser vos questions dans le chat",
"01h40m18s": "Vous avez vu cette action incroyable ?"
}