{"slug": "parakeet-java-automatic-speech-recognition-in-pure-java", "title": "Parakeet.java: Automatic Speech Recognition in Pure Java", "summary": "A pure-Java implementation of NVIDIA's Parakeet automatic speech recognition model, called Parakeet.java, matches the reference parakeet.cpp engine word-for-word at F16 quantization with 0.00% WER difference on LibriSpeech test-clean, according to benchmarks published by developer qxoticai. On an AMD Ryzen 7 PRO 8840U laptop with 8 threads, the tdt-0.6b-v3 Q4_K model reached 25.1x real-time factor versus parakeet.cpp's 12.6, while the smaller tdt_ctc-110m Q4_K model hit 81.2x versus 45.8x, transcribing an hour of speech in 44 seconds. The implementation runs without ONNX Runtime, whisper.cpp or a Python runtime, supports streaming transcription, word timings and confidence scores, and offers GraalVM Native Image support that loads a 600M model in about 0.2 seconds.", "body_md": "**Automatic Speech Recognition for the JVM**\n\nAn implementation of [NVIDIA Parakeet](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3) for\nthe JVM: blazing fast on ordinary CPUs, competitive with the native implementations. No ONNX Runtime, no whisper.cpp,\nno Python runtime. Just the JVM.\n\n<sub>Live transcription of JFK's 1961 inaugural address. [Play it with sound.](https://cdn.jsdelivr.net/gh/qxoticai/assets@e1fe3eacf469cf2962083a924d6daf260759e926/qxotic/parakeet-live-transcription.mp4)</sub>\n\n- **Competitive with the reference engines.** Keeps pace\nwith[parakeet.cpp](https://github.com/mudler/parakeet.cpp) and[sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx) , word for word identical.\n- **Matches the reference with 100% accuracy.** At`F16` the transcript matches[parakeet.cpp](https://github.com/mudler/parakeet.cpp) exactly;\nthe rest is quantization noise, not drift.\n- **Streaming support.** Audio in as it arrives, text out in pieces, with a draft tail that keeps up with the speaker.\n- **Word timings and confidence.** Every token carries its audio span and how sure the decoder was.\n- **Multilingual.** Parakeet v3 transcribes and punctuates without a language flag.\n- **First-class support for GraalVM's Native Image.** Low memory footprint, standalone images, fast startup e.g. 600M model is loaded and ready to transcribe in about 0.2 s.\n\nLibriSpeech test-clean, first 100 utterances (901 s), 8 threads on an AMD Ryzen 7 PRO 8840U\nlaptop, median of 3 runs. The last column scores each run against parakeet.cpp's transcript rather\nthan against the reference, so 0% means both engines heard exactly the same words.\n[How to reproduce this, step by step](https://github.com/qxoticai/qxotic/blob/main/jinfer/jinfer-parakeet/WER.md).\n\n| Model | Engine | WER | RTFx | WER vs. parakeet.cpp | \n|---|---|---|---|---|\n| tdt-0.6b-v3 `Q4_K` | **jinfer** | 2.04% | **25.1** | 0.17% | \n|  | parakeet.cpp | 2.04% | 12.6 | - | \n| tdt-0.6b-v3 `Q8_0` | **jinfer** | 2.04% | **21.6** | 0.04% | \n|  | parakeet.cpp | 2.04% | 14.9 | - | \n| tdt-0.6b-v3 `F16` | jinfer | 2.04% | 13.6 | 0.00% | \n|  | parakeet.cpp | 2.04% | **15.3** | - | \n| tdt_ctc-110m `Q4_K` | **jinfer** | 1.99% | **81.2** | 0.34% | \n|  | parakeet.cpp | 2.12% | 45.8 | - | \n| v3 int8 ONNX | sherpa-onnx | 2.16% | 18.6 | 1.27% | \n\n*RTFx* is seconds of audio transcribed per wall second, model load excluded. The small model\ntranscribes an hour of speech in 44 seconds.\n\nFor the full matrix - both models, three engines, five quantizations, 1 to 16 threads and three\nJVMs, on a second machine - see [BENCHMARKS.md](https://github.com/qxoticai/qxotic/blob/main/jinfer/jinfer-parakeet/BENCHMARKS.md).\n\n| Checkpoint | Languages | Parameters | GGUF ( `Q8_0` ) | \n|---|---|---|---|\n| [parakeet-tdt-0.6b-v3](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3) | multilingual | 600M | [tdt-0.6b-v3-q8_0.gguf](https://huggingface.co/mudler/parakeet-cpp-gguf/resolve/main/tdt-0.6b-v3-q8_0.gguf?download=true) | \n| [parakeet-tdt-0.6b-v2](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v2) | English | 600M | [tdt-0.6b-v2-q8_0.gguf](https://huggingface.co/mudler/parakeet-cpp-gguf/resolve/main/tdt-0.6b-v2-q8_0.gguf?download=true) | \n| [parakeet-tdt-1.1b](https://huggingface.co/nvidia/parakeet-tdt-1.1b) | English | 1.1B | [tdt-1.1b-q8_0.gguf](https://huggingface.co/mudler/parakeet-cpp-gguf/resolve/main/tdt-1.1b-q8_0.gguf?download=true) | \n| [parakeet-tdt_ctc-1.1b](https://huggingface.co/nvidia/parakeet-tdt_ctc-1.1b) | English | 1.1B | [tdt_ctc-1.1b-q8_0.gguf](https://huggingface.co/mudler/parakeet-cpp-gguf/resolve/main/tdt_ctc-1.1b-q8_0.gguf?download=true) | \n| [parakeet-tdt_ctc-110m](https://huggingface.co/nvidia/parakeet-tdt_ctc-110m) | English | 110M | [tdt_ctc-110m-q8_0.gguf](https://huggingface.co/mudler/parakeet-cpp-gguf/resolve/main/tdt_ctc-110m-q8_0.gguf?download=true) | \n\nEvery checkpoint also ships `Q4_K`, `Q5_K`, `Q6_K` and `F16` in\n[mudler/parakeet-cpp-gguf](https://huggingface.co/mudler/parakeet-cpp-gguf), named the same way:\nswap the quantization in the file name. `Q8_0` balances quality and size, `Q4_K` runs quickest.\nThe CLI downloads and caches them by reference, so no manual download is needed:\n\n```\njinfer pull mudler/parakeet-cpp-gguf/tdt-0.6b-v3-q8_0.gguf\njinfer -m mudler/parakeet-cpp-gguf/tdt-0.6b-v3-q8_0.gguf --transcribe speech.wav\n```\n\nAny format ffmpeg reads, resampled by `jinfer-codecs`. The transcript goes to stdout, so it pipes.\n\nRaw 16 kHz mono PCM on stdin, transcribed as it arrives. The microphone comes from ffmpeg, so the capture flags are the only part that differs:\n\n```\n# Linux (PulseAudio or PipeWire)\nffmpeg -nostats -loglevel error -f pulse -i default -ar 16000 -ac 1 -f s16le - \\\n  | jinfer -m mudler/parakeet-cpp-gguf/tdt-0.6b-v3-q4_k.gguf --transcribe -\n# macOS (AVFoundation; ffmpeg -f avfoundation -list_devices true -i \"\" names the inputs)\nffmpeg -nostats -loglevel error -f avfoundation -i \":0\" -ar 16000 -ac 1 -f s16le - \\\n  | jinfer -m mudler/parakeet-cpp-gguf/tdt-0.6b-v3-q4_k.gguf --transcribe -\n# Windows (DirectShow; ffmpeg -list_devices true -f dshow -i dummy names the inputs)\nffmpeg -nostats -loglevel error -f dshow -i audio=\"Microphone\" -ar 16000 -ac 1 -f s16le - ^\n  | jinfer -m mudler/parakeet-cpp-gguf/tdt-0.6b-v3-q4_k.gguf --transcribe -\n```\n\nOn a terminal, stderr shows the live view: final words settle into the scrollback, each committed\npiece lands in color and fades into the text, the provisional tail follows in grey italics with a\nband of light sweeping through it, and a waveform dances with the voice. Doubtful words are\nflagged, so a name the model is unsure of stands out. `--theme mint|nord|catppuccin|ember|frost|mono`\npicks the palette; colors degrade to 256, to 16, and to plain attributes under `NO_COLOR`.\n\nRedirected, the same run logs final text and partials as plain lines, so it scripts.\n\nThrough [LangChain4j](https://github.com/qxoticai/qxotic/blob/main/jinfer/jinfer-langchain4j/README.md), which resolves the model ref and downloads\nit on first use:\n\n``` js\ntry (var transcriber = JinferTranscriptionModel.builder()\n        .model(\"mudler/parakeet-cpp-gguf/tdt-0.6b-v3-q8_0.gguf\")\n        .build()) {\n    Transcription transcription = transcriber.transcribe(Path.of(\"speech.wav\"));\n    System.out.println(transcription.text());\n    for (Transcription.Word word : transcription.words())\n        System.out.printf(\"%s  %.2f  %s%n\", word.start(), word.confidence(), word.text());\n}\n```\n\nOr through [Spring AI](https://github.com/qxoticai/qxotic/blob/main/jinfer/jinfer-spring-ai/README.md), with `jinfer-spring-ai` on the classpath:\n\n``` js\ntry (var transcriber = JinferTranscriptionModel.builder()\n        .model(\"mudler/parakeet-cpp-gguf/tdt-0.6b-v3-q8_0.gguf\")\n        .build()) {\n    AudioTranscriptionResponse response = transcriber.call(\n            new AudioTranscriptionPrompt(new FileSystemResource(\"speech.wav\")));\n    System.out.println(response.getResult().getOutput());\n}\n```\n\nLive audio needs `jinfer-parakeet` directly: feed samples as they arrive, print the final pieces,\nand poll the provisional tail for a responsive UI.\n\n```\nstatic <S extends RuntimeState> void live(TranscriptionModel<?, ?, S> model, float[] pcm) {\n    try (S state = model.newState();\n            TranscriptionStream stream = model.stream(state)) {\n        int chunk = model.sampleRate() / 2; // feed half a second at a time\n        for (int at = 0; at < pcm.length; at += chunk) {\n            Transcription piece = stream.feed(pcm, at, Math.min(chunk, pcm.length - at));\n            System.out.print(piece.text()); // final text, often empty, never revised\n            System.err.print(\"\\r\" + stream.partial().text()); // provisional, replaced next time\n        }\n        System.out.println(stream.finish().text()); // the rest, final\n    }\n}\n```\n\nFinal pieces never change and join, in order, into the whole transcript. Token times are offsets from the start of the stream.\n\nAudio is decoded in chunks with context on both sides, as NeMo streams Parakeet: 10 s of left context, a 2 s chunk, 2 s of right context. Only the chunk's tokens become final, while the decoder carries its state across chunks, so words continue across boundaries. Final text trails the speaker by 2 to 4 s; the provisional tail, decoded over a shorter window, refreshes twice a second while speech comes in.\n\nOffline transcription runs the same path with 46 s chunks, so a two hour recording never holds a two hour attention matrix.\n\nParakeet v3 emits cased, punctuated text and one timing per token. It consumes mono 16 kHz audio;\nanything else is refused rather than silently resampled, since a rate mismatch quietly degrades\nrecognition. Short windows around digital silence can blank\n([NVIDIA-NeMo/Speech#15757](https://github.com/NVIDIA-NeMo/Speech/issues/15757)), so live recording\nwith a room noise floor transcribes better than padded silence.", "url": "https://wpnews.pro/news/parakeet-java-automatic-speech-recognition-in-pure-java", "canonical_source": "https://github.com/qxoticai/qxotic/tree/main/jinfer/jinfer-parakeet", "published_at": "2026-09-23 15:12:56+00:00", "updated_at": "2026-09-23 15:30:39.113676+00:00", "lang": "en", "topics": ["artificial-intelligence", "machine-learning", "natural-language-processing", "ai-tools", "developer-tools"], "entities": ["Parakeet.java", "NVIDIA", "Parakeet", "parakeet.cpp", "sherpa-onnx", "qxoticai", "GraalVM Native Image", "LibriSpeech"], "alternates": {"html": "https://wpnews.pro/news/parakeet-java-automatic-speech-recognition-in-pure-java", "markdown": "https://wpnews.pro/news/parakeet-java-automatic-speech-recognition-in-pure-java.md", "text": "https://wpnews.pro/news/parakeet-java-automatic-speech-recognition-in-pure-java.txt", "jsonld": "https://wpnews.pro/news/parakeet-java-automatic-speech-recognition-in-pure-java.jsonld"}}