# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project TranscribeStation est une application de bureau PyQt6 pour la gestion de fichiers audio à transcrire, avec support natif des pédales Olympus (RS27H/N, RS28H/N, RS31H/N). Interface entièrement en français. ## Commandes essentielles ### Développement (mode venv) ```bash python3 -m venv .venv source .venv/bin/activate pip install PySide6>=6.5.0 numpy>=1.24.0 soundfile>=0.12.0 hid>=1.0.5 python transcribe_station.py ``` ### Installation automatique (Debian 12/13) ```bash chmod +x install.sh && ./install.sh ./launch.sh ``` ### Compilation en binaire standalone ```bash pip install pyinstaller Pillow python build.py # auto-détection OS python build.py --linux # binaire Linux + raccourci GNOME python build.py --windows # binaire Windows + raccourci Menu Démarrer (via Wine) python build.py --both # les deux plateformes python build.py --clean # nettoyer dist/ et build/ python build.py --install-only # installer raccourcis sans recompiler ``` Les binaires sont produits dans `dist/linux/TranscribeStation` et `dist/windows/TranscribeStation.exe`. ### Dépendances système (Debian) ```bash sudo apt-get install -y libhidapi-dev libhidapi-hidraw0 libusb-1.0-0 \ gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \ gstreamer1.0-plugins-ugly gstreamer1.0-libav ``` ### Permissions pédales USB (udev) ```bash # Ajouter à /etc/udev/rules.d/99-olympus-pedal.rules # SUBSYSTEM=="hidraw", ATTRS{idVendor}=="07b4", MODE="0666" sudo udevadm control --reload-rules && sudo udevadm trigger ``` ## Architecture L'application est **monolithique** : toute la logique métier et UI réside dans `transcribe_station.py` (~2 150 lignes). Le fichier `build.py` (~567 lignes) gère la compilation PyInstaller et les raccourcis OS. ### Classes principales (transcribe_station.py) | Classe | Rôle | |--------|------| | `AppSettings` | Persistance des préférences (Linux: `~/.config/TranscribeStation/settings.json`, Windows: `%APPDATA%\TranscribeStation\settings.json`) | | `DictationStatus` | Enum : TODO / IN_PROGRESS / SUSPENDED / DONE | | `DictationFile` | Dataclass représentant un fichier audio + métadonnées + statut | | `FootPedalWorker` | QThread : lecture HID non-bloquante, reconnexion auto (retry 2s) | | `WaveformWidget` | QWidget : rendu de la forme d'onde via QPainter, seek à la souris | | `PlayerPanel` | QWidget : QMediaPlayer + WaveformWidget + contrôles transport | | `DictationTable` | QTableWidget : liste des fichiers, source de vérité `_files` | | `FolderTree` | QTreeWidget : sidebar gauche, filtres par statut + navigation dossiers | | `SettingsDialog` | QDialog : onglets Pédalier + Général | | `MainWindow` | QMainWindow : orchestration principale | ### Flux de données clé 1. **Ouverture dossier** → scan audio (`.wav .mp3 .flac .ogg .mp4 .m4a .dss .ds2`) → lecture `.transcribe_station.json` → `DictationTable` 2. **Double-clic fichier** → statut passe à `IN_PROGRESS` → `PlayerPanel.set_file()` → chargement waveform (numpy/soundfile) 3. **Pédales** → `FootPedalWorker` (thread HID) → signaux Qt → actions player (`rewind 0x04`, `play 0x02`, `forward 0x08`) 4. **Changement statut** → clic droit `DictationTable` → mise à jour `DictationFile` → sauvegarde `.transcribe_station.json` ### Persistance - **Par dossier :** `.transcribe_station.json` (JSON, DictationFile sérialisés via `to_dict()`/`from_dict()`) - **Préférences globales :** `~/.config/TranscribeStation/settings.json` ### Thèmes Deux thèmes (light/dark) définis par des palettes de couleurs hardcodées dans `MainWindow`. Pas de fichiers externes. Sélection via `AppSettings.theme`. ### Backend audio `QMediaPlayer` + `QAudioOutput` (GStreamer sur Linux). Les formats `.dss`/`.ds2` nécessitent des plugins GStreamer spéciaux (non garantis). ## Constantes importantes - `VID` pédales Olympus : `0x07B4` - `PID` RS27H/N : `0x0110`, RS28H/N : `0x0111`, RS31H/N : `0x0112` - Skip par défaut : `3000 ms` - Formats audio supportés : `.wav .mp3 .flac .ogg .mp4 .m4a .dss .ds2` - Raccourcis clavier : 15 définis dans `MainWindow._build_toolbar()` et `keyPressEvent()`