Automation

Sprachnotiz in Text

Diktierte Notizen landen als sauberer Text in der Ablage, ohne Cloud. Zwei getrennte Schritte, der Rohtext bleibt liegen, und bei zwei Stimmen gleichzeitig verschwindet eine davon ohne Warnung.

Andreas Neugebauer7 Min. Lesezeit

Stand
21. September 2026
Sprachnotiz in Text
Teilen

Auf dem Weg vom Termin zurück ist die Notiz noch da, am Schreibtisch ist sie weg. Wer nach einem Kundentermin ins Auto steigt, hat drei Dinge im Kopf, die ins Angebot müssen, und wenn er ankommt, sind es noch zwei, und eines davon ist falsch. Wir bauen einen Ablauf, der eine Sprachnotiz vom Handy aufnimmt und als Text ablegt, ohne dass eine Datei den Rechner verlässt. Gebaut haben wir ihn an zwei Wochen eigener Sprachnotizen; die Ausgaben in diesem Beitrag stammen aus einem Lauf am 18. September 2026 mit einer Testaufnahme.

Was du danach in der Hand hast

  • Eine Aufnahme wird lokal in Rohtext umgewandelt, ohne Konto und ohne Cloud
  • Ein lokales Sprachmodell nimmt Füllwörter, Wiederholungen und Versprecher heraus, und der Rohtext bleibt daneben liegen
  • Die Notiz landet unter einem Namen, den ein Programm und ein Mensch in zwei Jahren noch lesen können
  • Ein Skript, das einen Ordner beobachtet und beides für jede neue Aufnahme tut

Was danach nicht geht: zwei Stimmen auseinanderhalten, Erkennungsfehler korrigieren, Aufnahmen über zehn Minuten sauber verarbeiten. Dazu unten mehr.

Voraussetzungen

  • Python 3.12 (geprüft mit 3.12.2) und faster-whisper (pip3 install faster-whisper, geprüft mit 1.2.1). Beim ersten Lauf wird das Whisper-Modell geladen, small hat rund 480 MB. Danach braucht es kein Netz mehr
  • Ollama mit einem lokalen Modell. Bei uns läuft llama3.2 mit drei Milliarden Parametern, weil es auf jedem Laptop läuft. Der Beitrag zu lokalen Modellen erklärt, was das für die Daten bedeutet
  • Eine Aufnahme-App. Die Sprachmemos vom iPhone liefern m4a, und die liest faster-whisper direkt. Auf dem Mac wandelt afconvert alles andere um
  • Kosten: keine. Rechenzeit: für eine Notiz von einer halben Minute zusammen rund 10 Sekunden auf einem Mac ohne Grafikkarte

Der Aufbau

Zwei Schritte, die getrennt bleiben sollten: erst die Aufnahme in Rohtext, dann der Rohtext durch ein Modell, das aufräumt. Wer beides in einem Schritt macht, bekommt einen Text, der gut klingt und Dinge enthält, die nie gesagt wurden. Und man hat keine Möglichkeit mehr, das zu merken.

  1. 01

    Aufnehmen, wie es gerade geht

    Sprachmemos auf dem Handy, Diktiergerät, was da ist. Eine Person, ein Thema, unter zehn Minuten. Die Datei kommt über den Ordner, den das Handy ohnehin synchronisiert, in einen Eingangsordner auf dem Rechner. Diesen Schritt automatisieren wir nicht; er ist bei jedem anders.

  2. 02

    Schritt 1: Aufnahme wird Rohtext

    sprachnotiz.py rohtext liest die Aufnahme mit faster-whisper und schreibt den Text ohne Zeitmarken in eine Datei mit der Endung .roh.txt neben die Aufnahme. Bei einer Sprecherin und einem Thema braucht es keine Zeitmarken. Diese Datei wird danach nie mehr angefasst.

  3. 03

    Schritt 2: Rohtext wird aufgeräumt

    sprachnotiz.py aufraeumen schickt den Rohtext mit der Anweisung aus prompts/aufraeumen.md an Ollama. Füllwörter raus, bei Selbstkorrekturen die letzte Fassung, nichts dazu, nichts weg. Das Ergebnis geht in eine zweite Datei mit der Endung .txt. Eine Längenprüfung warnt, wenn das Ergebnis länger als der Rohtext oder weniger als halb so lang ist, denn dann hat das Modell erfunden oder zusammengefasst.

  4. 04

    Ablage unter einem Namen

    benenne.py schlägt für jede Aufnahme mit Rohtext einen Namen nach dem Schema aus dem Beitrag zur Ordnerstruktur vor: Datum vorn, dann Kunde, dann Belegart, dann eine Kennung. Für Sprachnotizen heißt das 2026-09-18_Bauer-Elektrotechnik_Sprachnotiz_1432. Der Kunde kommt aus einer Liste, die im Rohtext gesucht wird. Umbenannt wird erst mit --anwenden.

Was wir weglassen: keine Sprechertrennung, keine Zusammenfassung, keine Übergabe an ein CRM. Die Notiz ist ein Textdokument im Projektordner, mehr nicht. Was aus so einer Notiz später wird, etwa ein Protokoll mit Zusagen oder ein Angebot, beschreiben die Beiträge zum Protokoll aus der Besprechung und zum Weg vom Termin zum Angebot.

Die Stelle, die die Substanz trägt

Der zweite Schritt ist ein einziger Aufruf an Ollama. Die Substanz steckt nicht im Code, sondern in der Anweisung und in der Prüfung danach.

def schritt2_aufraeumen(rohtext: str, modell: str, url: str) -> str:
    """Rohtext -> aufgeräumter Text über Ollama. Der Rohtext wird nicht verändert."""
    system = PROMPT.read_text(encoding="utf-8")
    daten = json.dumps({
        "model": modell,
        "system": system,
        "prompt": "Rohtext:\n\n" + rohtext,
        "stream": False,
        "options": {"temperature": 0.1},
    }).encode("utf-8")
    anfrage = urllib.request.Request(f"{url}/api/generate", data=daten,
                                     headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(anfrage, timeout=600) as antwort:
        return json.load(antwort)["response"].strip()


def pruefe_laenge(rohtext: str, ergebnis: str) -> None:
    rein, raus = len(rohtext.split()), len(ergebnis.split())
    if raus > rein:
        print("Warnung: Ergebnis ist länger als der Rohtext. Prüfen, ob etwas dazuerfunden wurde.", file=sys.stderr)
    elif raus < rein * 0.5:
        print("Warnung: Ergebnis ist weniger als halb so lang wie der Rohtext. Prüfen, ob etwas fehlt.", file=sys.stderr)

Die Temperatur steht auf 0,1, weil wir keine Abwechslung wollen, sondern dieselbe Notiz beim zweiten Lauf gleich aufgeräumt. Die Längenprüfung ist grob, aber sie fängt die zwei Fehler, die ein Sprachmodell bei dieser Aufgabe macht: Es fasst zusammen, obwohl es nur aufräumen soll, oder es rundet den Text mit Sätzen ab, die niemand gesagt hat. Beides sieht man an der Wortzahl, bevor man den Text liest.

Die Anweisung selbst hat sieben Regeln, und die wichtigste ist die vierte: Eigennamen, Zahlen, Beträge und Termine werden buchstäblich übernommen, auch wenn sie falsch erkannt aussehen. Das klingt widersinnig, denn genau die will man ja richtig haben. Aber ein Modell, das „zwölfer Teilerschränke“ eigenmächtig zu „zwölf Verteilerschränke“ macht, macht beim nächsten Mal aus „4.980“ ein „4.890“, und das merkt niemand. Korrigieren tut ein Mensch, der den Rohtext daneben hat.

Beim Benennen ist die eine Zeile, die zählt, die Kundensuche:

def finde_kunde(rohtext: str, kunden: list[str]) -> str | None:
    """Erster Kundenname aus der Liste, der im Rohtext vorkommt."""
    t = rohtext.lower()
    for k in kunden:
        if k.lower() in t:
            return k
    return None

Absichtlich nur exakte Treffer, keine Ähnlichkeitssuche. Der Beitrag zur Ordnerstruktur beschreibt, wie eine Ähnlichkeitstabelle aus Müller einen Möller gemacht hat und eine Rechnung beim falschen Kunden gelandet wäre. Wird kein Kunde gefunden, heißt die Notiz „ohne-kunde“ und steht auf der Prüfliste. Das ist kein Mangel, sondern der Grund, warum man dem Rest der Liste trauen kann.

Was dabei herauskommt

Die Testaufnahme vom 18. September ist eine Notiz nach einem Kundentermin, 35 Sekunden, mit Füllwörtern und einer Selbstkorrektur, gesprochen von der Systemstimme des Mac. Schritt 1 mit dem Modell small, 5,7 Sekunden:

Lim, also, kurze Notiz nach dem Termin bei Bauer Elektrotechnik. Le, der Herr
Bauer will das Angebot für die, für die Halle bis Montag, nein, bis Mittwoch
haben. Lim, es geht um ungefähr Le, zwölfer Teilerschränke, und, ja, die
Kabeltrassen kommen von ihm selbst. Was ich noch, Lim, was ich noch nachfragen
muss ist die Sache mit der, mit der Brandschutzabnahme, da wusste er nicht,
wer das macht. Ach so, und die Rechnung vom letzten Mal, die, Le, die 4.980
Euro, die ist laut ihm angewiesen, das war's.

Gesprochen war „Ähm“ und „äh“; Whisper hat daraus „Lim“ und „Le“ gemacht, was an der synthetischen Stimme liegen kann. Und aus „zwölf Verteilerschränke“ wurden „zwölfer Teilerschränke“. Schritt 2 mit llama3.2, 2,9 Sekunden, 88 Wörter rein, 62 raus:

Kurze Notiz nach dem Termin bei Bauer Elektrotechnik. Der Herr Bauer will das
Angebot für die Halle bis Mittwoch haben. Es geht um zwölfer Teilerschränke
und die Kabeltrassen kommen von ihm selbst. Was ich noch nachfragen muss ist
die Sache mit der Brandschutzabnahme, da wusste er nicht, wer das macht. Die
Rechnung vom letzten Mal, die 4.980 Euro, ist laut ihm angewiesen.

Das ist der Text, den man haben will. Die Füllwörter sind weg, auch „Lim“ und „Le“, die in keiner Liste standen. Aus „bis Montag, nein, bis Mittwoch“ wurde „bis Mittwoch“. Der Betrag stimmt, die fünf Aussagen sind alle da, in der Reihenfolge, in der sie gesprochen wurden. Und „zwölfer Teilerschränke“ steht weiter drin, genau wie es die Regel verlangt.

Dann benenne.py über den Ordner, ohne --anwenden:

  ->  Neue Aufnahme 2026-09-18 14.32.wav       2026-09-18_Bauer-Elektrotechnik_Sprachnotiz_1432.wav   (aus Dateiname)

  1 benannt, 0 zur Prüfung  (nichts verändert, --anwenden fehlt)

Das Datum kommt aus dem Dateinamen, den Sprachmemos vergibt, der Kunde aus dem Rohtext. Rohtext und aufgeräumter Text werden mit umbenannt und behalten ihre Endungen.

Einhängen in den Ablauf

Für Sprachnotizen braucht es keinen n8n-Ablauf. ordner_ueberwachen.sh sieht alle 30 Sekunden in den Eingangsordner, und für jede Aufnahme, neben der noch keine .roh.txt liegt, lässt es beide Schritte laufen. Es misst die Dateigröße zweimal im Abstand von zwei Sekunden, damit es nicht eine Datei anfasst, die das Handy noch synchronisiert.

sh ordner_ueberwachen.sh ~/Sprachnotizen/eingang

Das Skript benennt nichts um. Einmal am Tag, oder wenn man ohnehin im Ordner ist, ruft man benenne.py auf, sieht sich die Vorschläge an und wendet sie an. Das dauert eine Minute und ist die Stelle, an der man „ohne-kunde“ sieht und einträgt, wer gemeint war. Wer will, hängt das in n8n an einen Local-File-Trigger; nötig ist es nicht.

Was das nicht kann

Bei zwei Stimmen gleichzeitig wird der Text unbrauchbar, und zwar auf eine Art, die man nicht sieht. Wir haben am 18. September zwei Systemstimmen übereinandergelegt: Eine spricht die Notiz zu Bauer Elektrotechnik, die andere gleichzeitig einen Satz zur Kern Hausverwaltung mit einem Betrag von 4.980 Euro. Whisper hat die erste Stimme vollständig und richtig erkannt. Von der zweiten steht kein Wort im Rohtext. Keine Warnung, kein Kauderwelsch, einfach nichts. Für Besprechungen zu zweit braucht es eine Trennung der Sprecher, die wir hier nicht behandeln; der Beitrag zur Spracherkennung im Besprechungsraum beschreibt, was dabei sonst noch klemmt.

Über zehn Minuten wird der zweite Schritt unzuverlässig. Bei unseren eigenen Notizen hat das Modell ab dieser Länge angefangen, Absätze zusammenzufassen statt aufzuräumen, und die Längenprüfung schlug an. Die Grenze liegt am Modell mit drei Milliarden Parametern und daran, dass eine lange Notiz mehrere Themen hat, die das Modell für Wiederholungen hält. Das Skript warnt bei Aufnahmen über zehn Minuten, bricht aber nicht ab. Besser ist, vorher zu teilen: ein Thema, eine Aufnahme. Am 18. September haben wir nur kurze Aufnahmen geprüft; die Zehn-Minuten-Grenze stammt aus dem Alltag, nicht aus einer Messung.

Erkennungsfehler bleiben stehen. Das ist keine Grenze, die wir bedauern, sondern eine Regel. Ein Modell, das „zwölfer Teilerschränke“ korrigieren darf, darf auch Beträge korrigieren, und dann korrigiert es irgendwann falsch. Wer die Erkennung selbst besser haben will, nimmt das Whisper-Modell medium oder gibt eine Namensliste als Initial-Prompt mit; wie das geht, steht im Beitrag zur Spracherkennung im Besprechungsraum.

Zum Nachbauen

Das Paket zu diesem Beitrag enthält die zwei Schritte als ein Skript, die Anweisung für das Aufräumen, das Benennungsskript mit Trockenlauf, die Ordnerüberwachung und die Testaufnahme mit beiden Texten. Entpacken, faster-whisper installieren, Ollama starten, dann:

  • sprachnotiz.py: rohtext, aufraeumen oder beides. Der Rohtext bleibt in jedem Fall liegen. Whisper-Modell über WHISPER_MODELL, Sprachmodell über MODELL wählbar
  • prompts/aufraeumen.md: die sieben Regeln mit Beispiel. Wer sie ändert, sollte Regel drei und vier stehen lassen
  • benenne.py und kunden.txt: Ablage nach Datum, Kunde, Belegart, Kennung. Erst Vorschlag, dann --anwenden
  • ordner_ueberwachen.sh: Eingangsordner beobachten, beide Schritte je neuer Aufnahme
  • testdaten/: die Aufnahme vom 18. September als m4a, ihr Rohtext, der aufgeräumte Text, und die Probe mit zwei Stimmen gleichzeitig samt Rohtext

Sprachnotiz in Text: zwei Schritte, Rohtext bleibt, Ablage mit Namen

ZIP · 285,1 kB

Python-Skript mit getrenntem Whisper- und Aufräumschritt (Ollama), Aufräum-Prompt, Benennungsskript mit Trockenlauf, Ordnerüberwachung und Testdaten (Aufnahme, Rohtext, aufgeräumter Text).

Herunterladen

Stand dieses Artikels

Gebaut an zwei Wochen eigenen Sprachnotizen; die Ausgaben in diesem Beitrag stammen aus Läufen am 18. September 2026 mit Python 3.12.2, faster-whisper 1.2.1 mit dem Modell small auf dem Prozessor eines Mac, Ollama mit llama3.2 (3B). Die Testaufnahmen sind mit der Systemstimme Anna aus say erzeugt, also sauber und ohne Straßenlärm; echte Notizen aus dem Auto sind schlechter. Geprüft: beide Schritte, die Längenprüfung, das Benennen im Trockenlauf und mit --anwenden, zwei Stimmen gleichzeitig. Nicht geprüft am 18. September: Aufnahmen über zehn Minuten, das Modell medium, ein größeres Sprachmodell als llama3.2, die Ordnerüberwachung über mehrere Stunden.

Häufige Fragen

Läuft das ohne Internet?

Ja. Beide Schritte laufen mit lokalen Modellen, die Aufnahme verlässt den Rechner nicht. Nur beim ersten Lauf lädt faster-whisper das Modell herunter, danach nicht mehr.

Wie lang darf eine Notiz sein?

Zehn Minuten sind unproblematisch. Darüber lohnt es sich, die Aufnahme vorher zu teilen, weil das Aufräum-Modell bei langen Texten anfängt zusammenzufassen. Das Skript warnt, wenn eine Aufnahme länger ist.

Kann ich ein anderes Modell zum Aufräumen nehmen?

Ja, über die Umgebungsvariable MODELL, jedes Modell, das Ollama geladen hat. Ein größeres Modell räumt sauberer auf und hält sich besser an die Regel, nichts zu erfinden. Die Längenprüfung sollte trotzdem bleiben.

© 2026 ernsthaft.ai, ein Angebot der abi group GmbH

Alle genannten Produktnamen, Logos und Marken sind Eigentum der jeweiligen Inhaber. Ihre Nennung bedeutet keine Empfehlung oder Verbindung zu ernsthaft.ai oder der abi group GmbH.

Build v1.11.1+ae65e16