Skip to content

feat(tts): add a Core ML Kokoro variant - #1384

Open
msluszniak wants to merge 2 commits into
rne-rewritefrom
@ms/rewrite-kokoro-coreml
Open

feat(tts): add a Core ML Kokoro variant#1384
msluszniak wants to merge 2 commits into
rne-rewritefrom
@ms/rewrite-kokoro-coreml

Conversation

@msluszniak

@msluszniak msluszniak commented Aug 25, 2026

Copy link
Copy Markdown
Member

Description

Adds a Core ML variant of Kokoro for iOS. Core ML cannot express the token axis dynamically, so its models fix it at 128 and every chunk is padded up to it; the frame axis stays dynamic (16..296), so durations and audio length are unchanged and no tempo scaling is involved.

The task accepts this as a second allowed spec (padded) next to the existing dynamic one, and the padded branch collapses minTokens/maxTokens onto the model's token count, so the existing worklet pads chunks with no other change. The synthesizer declares its frame range and the audio-length relation through get_model_schema; the duration predictor is fully static.

On an iPhone 16 the static-shape synthesizer measured 627 ms on Core ML against 4741 ms on XNNPACK (warm); on desktop the dynamic frame axis costs ~5% over static at full length and scales down with the frame count (486 ms at 296 frames, 181 ms at 120). Verified end to end on an iPhone 16 running this branch, with both models fetched from the published v0.10.0 tag. fp32 and CPU_ONLY: fp16 lands at 0.973 spectral correlation against eager versus 0.9993, and ComputeUnit.ALL gave a 25 minute compile plus an execute failure.

Introduces a breaking change?

  • Yes
  • No

Type of change

  • Bug fix (change which fixes an issue)
  • New feature (change which adds functionality)
  • Documentation update (improves or adds clarity to existing documentation)
  • Other (chores, tests, code style improvements etc.)

Tested on

  • iOS
  • Android

Testing instructions

Run apps/speech, open the Kokoro screen, pick Core ML in the Backend picker (iOS only, shown for the languages served by the standard weights) and synthesize. Compare against XNNPACK on the same text and voice.

Screenshots

Related issues

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings

Core ML cannot export Kokoro's token axis dynamically, so its models fix it
and every chunk is padded up to that length. Add it as a second allowed spec
next to the dynamic one, and wire the Core ML presets into the registry and
the speech demo.
@msluszniak msluszniak self-assigned this Aug 25, 2026
@msluszniak msluszniak added platform: ios Issues and tasks related to iOS performance Related to all issues and tasks focused on improving performance labels Aug 25, 2026
@msluszniak
msluszniak marked this pull request as ready for review August 25, 2026 15:55
Same contract as the standard Core ML pair, so the entries just spread their
XNNPACK twins and swap modelPaths, keeping the phonemizer and voices
(pm_mateusz, df_anna) defined once.

No app change: the Backend picker already gates on COREML_FP32 being present
for the selected language, so both light up on their own.
@msluszniak
msluszniak requested review from IgorSwat and barhanc and removed request for IgorSwat August 25, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance Related to all issues and tasks focused on improving performance platform: ios Issues and tasks related to iOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant