Advanced Features

This guide covers the supported pipeline-first API for controlled generation and long-form rendering.

Paragraph-wise rendering

prepare_units() prepares the complete document once, then renders selected paragraphs one at a time. This preserves document-global SSMD offsets, voice bindings, pauses, and marker ownership while bounding live generated waveform memory:

from pathlib import Path

import soundfile as sf

from pykokoro import KokoroPipeline, PipelineConfig

with KokoroPipeline(PipelineConfig(voice="af_sarah")) as pipeline:
    with pipeline.prepare_units(script, unit="paragraph") as prepared:
        for result in prepared.render(skip_indices={0, 1}):
            try:
                sf.write(
                    Path(f"paragraph-{result.descriptor.index:04d}.wav"),
                    result.audio,
                    result.sample_rate,
                )
            finally:
                result.release_audio()

Descriptors are available before inference and contain source-order indices, clean-text offsets, segment ownership, marker names, and a text_hash. Store the pykokoro-audio-unit-v1 schema beside hashes in a resume manifest. Hashes include audio-semantic settings, not tracing, retention, cache directories, or machine-local runtime toggles. Set PipelineConfig(model_identity="model-v1") to give a local model a stable resume identity.

AudioUnitResult.release_audio() is destructive and idempotent. The iterator releases the previous result before yielding the next one, so callers must persist or copy its array inside the loop. Closing prepared units releases prepared segment arrays but does not close the reusable pipeline backend.

Preparation is global rather than text-streaming: parsing, segmentation, G2P, and phoneme preprocessing still operate on the full document. The bounded part is unit audio generation and postprocessing.

SSMD 0.8 metadata

Portable YAML headers can define logical voices, pause defaults, title metadata, and markers. Bind logical roles to provider voices through SSMDRenderConfig and render paragraph units with the same lifecycle shown above. See examples/paragraph_ssmd_voices.py for a complete script and marker offsets.

Generation and pauses

from pykokoro import GenerationConfig, KokoroPipeline, PipelineConfig

generation = GenerationConfig(
    lang="en-us",
    speed=1.05,
    pause_mode="manual",
    pause_clause=0.2,
    pause_sentence=0.5,
    pause_paragraph=1.0,
)

with KokoroPipeline(PipelineConfig(voice="af_bella", generation=generation)) as pipeline:
    result = pipeline.run("A short sentence ...s followed by another.")
    result.save_wav("pauses.wav")
    result.release_audio()

Automatic pauses use local SSMD/header defaults when present and otherwise the configured GenerationConfig values. Explicit break events take precedence; explicit zero durations remain zero.

Voice blending

Voice blending is represented by VoiceBlend from the concrete voice-manager module and passed through PipelineConfig:

import soundfile as sf

from pykokoro import KokoroPipeline, PipelineConfig
from pykokoro.voice_manager import VoiceBlend

blend = VoiceBlend.parse("af_bella:50,af_sarah:50")
with KokoroPipeline(PipelineConfig(voice=blend)) as pipeline:
    result = pipeline.run("This is a blended voice.")
    sf.write("blended.wav", result.audio, result.sample_rate)
    result.release_audio()

Composable stages

The pipeline stages follow this order:

doc_parser -> g2p -> phoneme_processing -> audio_generation -> audio_postprocessing

Custom stages can be injected into KokoroPipeline for tests, experiments, and dependency-light processing. Importing the pipeline and running fully custom stages does not require ONNX Runtime. Default audio stages require one of the provider extras.

spaCy policy

TokenizerConfig(use_spacy=...) is tri-state and local-only:

  • False: never use spaCy;

  • None: choose the best compatible installed model or fall back;

  • True: require a compatible local model;

  • explicit model or size: require that exact local request.

No path downloads a spaCy model automatically. Selection metadata is retained in the prepared document metadata for both sentence splitting and G2P.

Migration from the removed API

The old single-object API is not part of the current package. Use the pipeline lifecycle:

from pykokoro import KokoroPipeline, PipelineConfig

with KokoroPipeline(PipelineConfig(voice="af_bella")) as pipeline:
    result = pipeline.run(text)
    audio = result.audio.copy()
    sample_rate = result.sample_rate
    result.release_audio()

Historical scripts are retained under examples/legacy/ for reference only and are not indexed or tested as maintained usage examples.