Intermédiaire 25 minSanté

Santé : transcription de consultations

Un médecin qui dicte ses consultations passe des heures le soir à rédiger ses comptes-rendus. ChatGPT ferait ça en 30 secondes — mais le secret médical l'interdit formellement, même avec les plans Enterprise. Whisper (transcription) + Mistral (résumé), tous les deux en local, donnent un flux "audio → compte-rendu structuré" qui ne sort jamais du poste. Ce guide le monte en 25 minutes.

Par Mohamed Meguedmi·Màj 2026-04-11·Testé sur Windows, macOS, Linux

#Le secret médical

Le Code de la santé publique (art. L.1110-4) impose que toute donnée de santé identifiante soit protégée. Envoyer une transcription de consultation chez OpenAI est, dans le cas général, une violation caractérisée. Les plans HIPAA/BAA existent mais ne couvrent pas la France pour les professions libérales.

!
Impact pratique
Un médecin qui utilise ChatGPT pour rédiger ses CR s'expose à sa responsabilité professionnelle et civile. Le local élimine ce risque à la racine : aucune donnée ne quitte le poste.

#Stack : Whisper + LLM

faster-whisper
Fork de Whisper optimisé CTranslate2. 4x plus rapide que l'original. Tourne sur CPU correctement, excellent sur GPU.
Modèle large-v3
Le plus précis pour le français médical. ~3 Go. Transcrit 1h d'audio en 3-5 minutes sur RTX.
Ollama + Mistral / Qwen 14B
Pour synthétiser la transcription en compte-rendu structuré.
pyannote (optionnel)
Diarisation : qui parle quand. Utile pour distinguer médecin / patient.

#1. Installation

Python env
python3 -m venv venv
source venv/bin/activate

pip install faster-whisper ollama
# Optionnel pour diarisation :
pip install pyannote.audio

# Test
faster-whisper --help
Modèles
# Whisper large-v3 : téléchargé au premier usage (~3 Go)
# Mistral via Ollama :
ollama pull mistral

#2. Transcrire l'audio

transcribe.py
from faster_whisper import WhisperModel

model = WhisperModel("large-v3", device="cuda", compute_type="float16")

def transcribe(audio_path):
    segments, info = model.transcribe(
        audio_path,
        language="fr",
        beam_size=5,
        vad_filter=True,  # coupe les silences
        word_timestamps=False,
    )
    lines = []
    for s in segments:
        timestamp = f"[{int(s.start // 60):02d}:{int(s.start % 60):02d}]"
        lines.append(f"{timestamp} {s.text.strip()}")
    return "\n".join(lines)

if __name__ == "__main__":
    import sys
    print(transcribe(sys.argv[1]))
CPU ok pour audio court
Sur 10 minutes d'audio, un MacBook M1 transcrit en ~3 minutes avec large-v3 en int8. Pas besoin de GPU pour un usage en cabinet.

#3. Résumer en compte-rendu

summarize.py
import requests

SYSTEM_CR = """Tu es un assistant pour médecin généraliste français.
À partir d'une TRANSCRIPTION BRUTE d'une consultation, tu produis un
compte-rendu médical structuré.

FORMAT DE SORTIE :
## Motif de consultation
## Antécédents (mentionnés)
## Examen clinique
## Diagnostic / Hypothèses
## Traitement / Prescriptions
## Suivi

RÈGLES :
- Reste TEXTUEL : n'ajoute aucun élément non mentionné dans la transcription.
- Reformule en vocabulaire médical standard.
- Si une section n'est pas abordée, écris "Non mentionné".
"""

def summarize(transcription):
    r = requests.post("http://localhost:11434/api/chat", json={
        "model": "mistral",
        "messages": [
            {"role": "system", "content": SYSTEM_CR},
            {"role": "user",   "content": transcription},
        ],
        "stream": False,
        "options": {"temperature": 0.2, "num_ctx": 16384},
    })
    return r.json()["message"]["content"]

#Diarisation : distinguer qui parle

pyannote.audio permet d'attribuer chaque segment à un speaker (SPEAKER_00, SPEAKER_01). Utile pour une consultation à deux interlocuteurs. Modèle open source, téléchargeable depuis HuggingFace (nécessite un token HF, gratuit).

Diarisation basique
from pyannote.audio import Pipeline

pipeline = Pipeline.from_pretrained(
    "pyannote/speaker-diarization-3.1",
    use_auth_token="hf_xxx",
)

diarization = pipeline("consultation.wav")
for turn, _, speaker in diarization.itertracks(yield_label=True):
    print(f"{turn.start:.1f}s–{turn.end:.1f}s : {speaker}")

#Workflow type en cabinet

  1. 01
    Dictaphone après consultation
    Le médecin enregistre 1-2 minutes de notes vocales sur son téléphone ou un dictaphone.
  2. 02
    Import sur le poste
    Transfert du fichier audio (WAV, MP3, M4A). Un dossier audio/inbox surveillé par un watcher script.
  3. 03
    Pipeline auto
    Un script détecte le nouveau fichier, transcrit avec Whisper, résume avec Mistral, sauvegarde le CR en .md à côté.
  4. 04
    Relecture
    Le médecin ouvre le .md, corrige, intègre à son logiciel de gestion (DOCTOlib, Weda, Axisanté…).
Base légale
Traitement sur base du consentement explicite du patient (informé de l'enregistrement) ou de l'intérêt légitime (rédaction du CR dans son intérêt).
Registre des traitements
L'activité doit apparaître au registre (obligatoire même pour cabinet solo). Description courte du pipeline local.
Durée de conservation
L'audio brut doit être supprimé après génération du CR. Le CR suit la durée de conservation des dossiers médicaux (20 ans après dernier acte).
Chiffrement du disque
FileVault (Mac), BitLocker (Windows), LUKS (Linux). Indispensable même en local — un ordi volé avec des données de santé en clair est une fuite RGPD.
Audit
En cas de contrôle CNIL, vous devez pouvoir démontrer que rien n'est envoyé au cloud. Un screenshot de votre firewall bloquant les connexions sortantes de Whisper/Ollama est un élément de preuve solide.
Ce guide vous a aidé ?

Un retour, une erreur, une précision ? Faites-nous signe, ça améliore le guide pour tout le monde.