arkennemasis fal · MiniMax Speech 2.6 HD · $0.1/1k chars
Pause Markers, Loudness Normalization, 10,000 Characters a Call
- audio
- audio_path
- duration_ms
- info
This is the generation where MiniMax TTS stopped being "good voice, no control." Three things arrived at once: real pause markers you type into the script, a built-in loudness normalization block, and a text budget that jumped from 5,000 to 10,000 characters. Still $0.10 per 1,000 characters.
What changed, and why you'd care
Pause markers. The field is called prompt on this generation (not text), and it accepts <#x#> where x is the pause in seconds, 0.01 to 99.99 to two decimals. You place them between speakable segments, and you can't use two consecutively. That's the difference between a narration that pauses where the writing does and one that pauses where the model felt like it.
Loudness normalization, on by default: target loudness −18 LUFS, target range 8 LU, target peak −0.5 dBTP - each of those a widget. If you've ever hand-compressed ten voice-over clips to get them to sit at the same level in an edit, you know what this is worth. It's also the reason a batch of clips from this node will cut together without a gain pass.
10,000 characters per call. Same rate, double the room - a full long-form script in one submit, no stitching.
How it works
Standard fal plumbing as the pack does it everywhere: FAL_KEY read from the .env beside the launcher, input validation, cost estimate from the character count against max_cost_usd, one billed submit, polling with a status label on the node, and a download into output/fal/fal-ai_minimax_speech-2.6-hd/. Nothing gets uploaded, so nothing before the submit can bill you. MiniMax's voice models are closed and hosted - there's no local equivalent, and that's the point: MiniMax positions this line against ElevenLabs, and the reason to pay is multi-language reliability that local TTS still doesn't quite match.
Inputs
prompt- your script, 1 to 10,000 characters, with<#x#>pauses. This box sets the price.voice_setting_voice_id- free text, defaultWise_Woman, MiniMax's predefined IDs. Empty leaves it to the model.voice_setting_emotion-(not set)orhappy,sad,angry,fearful,disgusted,surprised,neutral.language_boost- the explicit language picker (withauto). Set it; this is what stops your German script being read with English instincts.voice_setting_speed(0.5–2.0),voice_setting_pitch(−12 to 12),voice_setting_vol(0.01–10),voice_setting_english_normalization(numbers and units read properly, slightly slower).- Normalization:
normalization_setting_enabled(default on),normalization_setting_target_loudness(−70 to −10 LUFS),normalization_setting_target_range(0–20 LU),normalization_setting_target_peak(−3 to 0 dBTP). - Output:
audio_setting_format(mp3,pcm,flac),audio_setting_bitrate(32k–256k),audio_setting_sample_rate(8k–44.1k),audio_setting_channel(1 mono, 2 stereo),pronunciation_dict(JSON replacements for names),output_format(urlorhex; leave it).
Optional: max_cost_usd ($20 default, 0 = off - the node refuses before sending when the estimate is over it), max_concurrent (default 1), reuse_identical_run (identical text returns the file you already paid for, restart included), extra_json (JSON merged into the request last).
Outputs: audio (waveform + sample rate, playable on the node), audio_path, duration_ms - the measured read, which you feed into Narration Length to size shots or Word Timings to time captions - and info (request id, estimate, saved files, fal's answer).
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Hishamahmer/comfyui-arkennemasis
pip install httpx
Or ComfyUI Manager → Install via Git URL, then restart. And add the key:
FAL_KEY=your-key-from-fal.ai/dashboard/keys
in the .env next to run_nvidia_gpu.bat. It appears under arkennemasis/fal/Audio/MiniMax.
Using it well
Write pauses deliberately: <#0.6#> between clauses, <#1.2#> between paragraphs reads far more natural than a comma-and-hope. Leave english_normalization on for anything with numbers in it, and set language_boost even for English.
If you're targeting a platform rather than a broadcast mix, nudge target_loudness up toward the −16 to −14 LUFS range - most streaming platforms normalize around there, and delivering at −18 just means everything else in your edit is louder. And remember the reuse behaviour: re-running identical text returns the previous file for free, which is thrifty right up until it confuses you.
Inputs (22)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | Text to convert to speech. Paragraph breaks should be marked with newline characters. **NOTE**: You can customize speech pauses by adding markers in the form `<#x#>`, where `x` is the pause duration in seconds. Valid range: `[0.01, 99.99]`, up to two decimal places. Pause markers must be placed between speakable text segments and cannot be used consecutively. | |
| voice_setting_speed | FLOAT | 1.000.5–2 | Speech speed (0.5-2.0) |
| voice_setting_vol | FLOAT | 1.000.01–10 | Volume (0-10) |
| voice_setting_english_normalization | BOOLEAN | false | Enables English text normalization to improve number reading performance, with a slight increase in latency |
| voice_setting_pitch | INT | 0-12–12 | Voice pitch (-12 to 12) |
| voice_setting_emotion | COMBO | (not set) | Emotion of the generated speech '(not set)' leaves it to the model. |
| voice_setting_voice_id | STRING | Wise_Woman | Predefined voice ID to use for synthesis Empty leaves it out. |
| audio_setting_format | COMBO | mp3 | Audio format |
| audio_setting_bitrate | COMBO | 128000 | Bitrate of generated audio |
| audio_setting_sample_rate | COMBO | 32000 | Sample rate of generated audio |
| audio_setting_channel | COMBO | 1 | Number of audio channels (1=mono, 2=stereo) |
| language_boost | COMBO | (not set) | Enhance recognition of specified languages and dialects '(not set)' leaves it to the model. |
| output_format | COMBO | hex | Format of the output content (non-streaming only) |
| pronunciation_dict | STRING | Custom pronunciation dictionary for text replacement JSON. Empty leaves it out. | |
| normalization_setting_target_range | FLOAT | 8.000–20 | Target loudness range in LU (default 8.0) |
| normalization_setting_target_loudness | FLOAT | -18.00-70–-10 | Target loudness in LUFS (default -18.0) |
| normalization_setting_enabled | BOOLEAN | true | Enable loudness normalization for the audio |
| normalization_setting_target_peak | FLOAT | -0.50-3–0 | Target peak level in dBTP (default -0.5). |
| max_cost_usdopt | FLOAT | 20.00–100000 | Safety cap. If the estimated cost of this run is above this many US dollars the node stops BEFORE sending anything to fal. 0 = no cap. |
| reuse_identical_runopt | BOOLEAN | true | If these exact inputs (the settings AND the same pictures/clips/audio) were already paid for and the files are still in output/fal, return them instead of paying again - also after a ComfyUI restart. Turn off for a fresh take with the same settings. |
| extra_jsonopt | STRING | Advanced: a JSON object merged into the request last, for any fal field this node has no box for. Example: {"seed": 7}. Leave empty normally. | |
| max_concurrentopt | INT | 11–32 | How many paid fal calls may run at the same time in one run, across every fal node. 1 (default) = one after another. This node starts its paid part only while fewer than this many fal calls are running. Once any fal node fails, the ones still waiting are not started, so nothing more is billed. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |
| audio_path | STRING | — |
| duration_ms | INT | — |
| info | STRING | JSON: request id, cost estimate, saved files and fal's full answer. |