whisper.cpp bringt einen optionalen Core-ML-Encoder-Pfad für Apple Silicon mit. Es ist die Funktion, die man bei einer Mac-Diktier-App erwarten würde. Voice Type deaktiviert sie zwangsweise und nutzt stattdessen das Metal-Backend.
Der Grund ist ein Shape-Mismatch, und er entsteht dadurch, wie das Live-Diktat Audio in Batches bündelt.
TL;DR
- Ein kompiliertes Core-ML-Encoder-Bundle erwartet eine feste Eingabeform.
- Das Live-Diktat erzeugt Batches unterschiedlicher Länge, weil der Batcher sich weigert, eine Phrase mittendrin zu zerschneiden.
- Voice Type deaktiviert deshalb den Core-ML-Pfad bei der Kontexterstellung und läuft auf Metal, das Audio variabler Länge akzeptiert.
- Mit dem Pfad entfiel auch ein Download von 163 MB bis 1,17 GB pro Modell.
Warum die Batches unterschiedlich lang sind
Voice Type schickt dem Erkenner keine Abschnitte fester Länge nach Timer. Ein Streaming-Sprachaktivitätsdetektor markiert Sprachbereiche, und der Batcher sammelt ganze Bereiche. Er teilt keinen Bereich, nur weil ein Timer ausgelöst hat.
Die Regeln, die entscheiden, wann ein Batch ans Modell geht, hängen alle von der Sprache ab, nicht von der Uhr:
- Das Ziel für einen Live-Batch beträgt 29 Sekunden, begrenzt auf einen Bereich von 15 bis 29 Sekunden.
- Ein Batch, der kürzer als 5 Sekunden ist, wird nie durch eine Pause abgeschickt. Er wartet, und die nächste Phrase schließt sich ihm an.
- Ein Pausen-Flush braucht mindestens 400 ms Stille nach einem abgeschlossenen Sprachbereich.
- Würde das Hinzufügen des nächsten ganzen Bereichs das Ziel überschreiten, wird zuerst der aktuelle Batch abgeschickt, und der ganze Bereich eröffnet den nächsten.
- Wenn du die Hotkey-Taste loslässt, wird alles Übrige abgeschickt, unabhängig von der Länge.
Die Folge: Die Batchlänge ist eine Verteilung, keine Konstante. Ein Batch kann 5 Sekunden oder 31 lang sein. Das ist das richtige Verhalten für Diktat, denn die Alternative wäre, ein Wort an einer Fenstergrenze zu halbieren.
Was das auf Core ML kostet
Ein Core-ML-Modell wird vorab zu einem .mlmodelc-Bundle kompiliert, in das die Eingabedimensionen fest eingebaut sind. Gibst du ihm Audio einer Länge, für die es nicht kompiliert wurde, hast du zwei Möglichkeiten: Du füllst auf die feste Form auf, was bedeutet, Encoder-Arbeit für Stille zu bezahlen, oder du hältst mehrere kompilierte Varianten vor, was mehrere Bundles auf der Festplatte bedeutet.
Voice Type wählt keins von beiden. Der Core-ML-Encoder-Pfad wird dort zwangsweise deaktiviert, wo der Whisper-Kontext erstellt wird, und der Kommentar nennt genau diesen Grund: Einschränkungen durch Eingaben fester Form. Die Backend-Richtlinie wählt dann standardmäßig Metal und weicht nur auf die CPU aus, wenn man im Simulator läuft, wenn ein Benutzer-Default die GPU abschaltet oder wenn der abgesicherte Modus nach einem Absturz eingerastet ist.
Metal nimmt jede Länge, die der Batcher liefert.
Was durch die Entfernung frei wurde
Die Core-ML-Unterstützung wurde nicht nur deaktiviert, sondern entfernt. Ältere Builds installierten neben den Gewichten jedes Modells ein Encoder-Bundle, ggml-<name>-encoder.mlmodelc, das je nach Modell etwa 163 MB bis 1,17 GB groß war. Diese Bundles wurden pro Modell heruntergeladen, entpackt und bereitgestellt.
Weil kein Codepfad sie mehr löscht, enthält die App eine einmalige Migration, die beim Upgrade die verwaisten Encoder-Bundles aus dem Modellverzeichnis entfernt und darauf achtet, die danebenliegenden .bin-Gewichte nie anzufassen.
Das für Nutzer sichtbare Ergebnis des Abschaltens von Core ML ist also ein kleinerer Download und ein kleineres Modellverzeichnis – obendrein bei einem Erkenner, dem es egal ist, wie lang dein Satz war.
Der gestrichelte Zweig ist der Pfad, den die App bewusst nicht nimmt. Quelle: whisper.cpp.swift/LibWhisper.swift.
Was Metal tatsächlich ausführt
Metal ist Apples Low-Level-GPU-API und erledigt in dieser App zwei getrennte Aufgaben.
Der Whisper-Kontext läuft auf dem Metal-Backend, sodass Encoder und Decoder auf der GPU ausgeführt werden. Davon getrennt läuft die Audioaufbereitung pro Batch als eigene Signalverarbeitungsstufe, bevor das Modell irgendetwas sieht: Entfernen des Gleichspannungsanteils, die Filter und die Lautstärkeregelung, dann das Resampling auf die 16 kHz, die das Modell erwartet.
Beide lesen aus dem Unified Memory, sodass Audiopuffer zwischen Aufnahmepfad und Modell nicht über einen Bus kopiert werden.
Was wir nicht behaupten
Wir veröffentlichen hier keine Finalisierungszeit. Wir haben derzeit kein Benchmark-Skript, das wir dir zusammen mit der Zahl in die Hand geben könnten, und eine Latenzangabe ohne Möglichkeit, sie nachzuvollziehen, ist Marketing.
Strukturell wahr und ohne Benchmark belegbar ist: Die Arbeit, die beim Loslassen der Hotkey-Taste noch übrig ist, wird durch das Batch-Ziel begrenzt, nicht dadurch, wie lange du gesprochen hast. Ein zweiminütiges und ein dreißigminütiges Diktat enden mit gleich viel Restarbeit.
Um es auf deinem eigenen Rechner zu messen, diktiere zehnmal denselben Satz und miss die Zeit zwischen dem Loslassen der Hotkey-Taste und dem Erscheinen des Texts. Diese Zahl zählt, und sie gehört dir.
Abwägungen
Modellgröße gegen Genauigkeit. Kleinere Modelle finalisieren schneller und verpassen mehr Wörter. Voice Type liefert mehrere Größen von 27 MB bis 550 MB, sodass du die Abwägung selbst triffst.
Die größeren Modelle passen zu einem Apple-Silicon-Mac mit reichlich Unified Memory. Die kleineren passen zu einem Rechner mit 8 GB, auf dem ein größeres Modell seine Zeit mit Auslagern statt mit Dekodieren verbringt.
Siehe auch: Technologie-Überblick · Sprachaktivitätserkennung · Latenz-Demo
