feat(workflows): make the voice-to-voice template real - #2499
Open
Hoang130203 wants to merge 1 commit into
Open
Conversation
config/n8n/05-voice-to-voice.json was a manualTrigger plus a sticky note
saying "Customize the nodes below to match your setup", with
"connections": {} — an empty canvas behind a catalog card advertising
"Speak, get AI response as audio".
Now the full loop:
audio in -> whisper:8000 /v1/audio/transcriptions
-> llama-server:8080 /v1/chat/completions
-> tts:8880 /v1/audio/speech
-> audio out
curl -X POST http://localhost:5678/webhook/ods-voice \
-F 'file=@question.wav' --output answer.mp3
Every hop is an in-network address, so neither the audio nor the
transcript leaves the machine.
Details that matter for it to actually work:
- The TTS call sets responseFormat=file with outputPropertyName=speech,
and the responder returns that binary property. Without the file
format n8n would try to parse the MP3 as JSON.
- The system prompt tells the model to answer in two or three spoken
sentences with no markdown, since the reply is read aloud rather than
displayed. Callers can override it with a `system` form field.
- The multipart upload is referenced as `file` — n8n names a webhook
binary property after the form field key, and options.binaryPropertyName
would produce `data0` rather than renaming it.
- `voice` defaults to af_heart, matching the tts README example.
This was referenced Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
config/n8n/05-voice-to-voice.jsonwas a placeholder —manualTrigger+sticky note +
"connections": {}— behind a catalog card advertising "Speak,get AI response as audio",
"featured": true,"setupTime": "2 minutes".It is now the full loop, on your own hardware:
curl -X POST http://localhost:5678/webhook/ods-voice \ -F 'file=@question.wav' --output answer.mp3Optional form fields:
voice(defaultaf_heart, matching the tts README),system(override the assistant prompt),stt_model.Every hop uses the manifest's in-network
port, not the published one, soneither the audio nor the transcript ever leaves
ods-network.Three details this needed to actually work
options.response.response.responseFormat = "file"withoutputPropertyName: "speech", and the responder usesrespondWith: "binary"/responseDataSource: "set"/inputFieldName: "speech". Without the file format n8n would try to parsethe MP3 as JSON and fail at the last step.
sentences, no markdown, no lists, no code blocks, because the reply is read
aloud. A default chat prompt produces bullet points that Kokoro then reads
out as literal asterisks.
file, notdata. n8n'shandleFormData()names a webhook binary property after the form field key, and setting
options.binaryPropertyNameappends a counter (data0) rather thanrenaming it — see feat(workflows): make the voice transcription template real #2498 for the code path.
AI Assistance
AI assisted with drafting the node graph, the spoken-output prompt, and this
description. I verified all three endpoints and ports against their service
manifests, and confirmed the binary-response parameter shapes against the node
definitions rather than from memory.
Release Lane
release/2.6.xmainStable hotfix reason:
Changed Surface
(One JSON file under
config/n8n/. An import payload for n8n; no ODS codeexecutes it. The catalog entry is unchanged.)
Risk And Validation
git diff --checkrelease/2.6.xCommands/results:
Caveat, and it is a bigger one for this workflow than the others: Docker is
not running on my dev host, so I could not run the three-hop chain end to end.
Static validation proves the file imports and that every node parameter and
version is real; it does not prove the data actually threads through three
services. This is the longest chain of the set, so it is the one I would most
want a live run on. Say the word and I will get one on a machine with Docker
before you merge.
Operational Change Check
An import payload for n8n. Nothing in the installer, compose stack,
ods-cli,or dashboard-api executes it. No existing install changes until a user imports
it.
Notes For Reviewers
This is the workflow whose catalog dependencies were wrong. It declares
["whisper", "llama-server", "kokoro"], andkokoromatches no service, socheck_workflow_dependencies()silently reports it satisfied — the card says"ready" even with TTS stopped. #2495 fixes that with a
kokoro->ttsalias.Worth landing that one first, or this workflow will look installable on a box
with no TTS and fail at the last hop.
Voice list.
af_heartis the tts README's example voice. If ODS pins adifferent default anywhere I did not find it, point me at it.
Part of the series making the 18 stub templates real: #2496 (chat,
code-assistant), #2497 (summarizer), #2498 (transcription). Independent files,
no overlapping lines.