Audio plugins
Audio plugins add narration providers as separate packages. SuiteCut loads the selected package in its narration worker. Built-in Kokoro remains the default.
Install one model family
npm install --save-dev @suitecut/audio-vitsUse @suitecut/audio-vits for VITS and Piper. Other packages are@suitecut/audio-matcha, @suitecut/audio-kokoro-sherpa,@suitecut/audio-kitten, @suitecut/audio-zipvoice,@suitecut/audio-pocket, and @suitecut/audio-supertonic.
import { test } from 'suitecut'
test.use({
suitecutAudioPlugins: [
{
provider: 'piper-amy',
module: '@suitecut/audio-vits',
options: {
model: './models/piper/en_US-amy-low/en_US-amy-low.onnx',
tokens: './models/piper/en_US-amy-low/tokens.txt',
dataDir: './models/piper/en_US-amy-low/espeak-ng-data',
},
},
],
})
test('records Piper narration', async ({ page, suitecut }) => {
await page.goto('https://example.com')
await suitecut.narrate('The report is ready.', {
provider: 'piper-amy',
voice: 'default',
speed: 1.1,
})
})Each package validates only its model family's options. The packages share one Sherpa runtime, which npm deduplicates when a project installs more than one family. The adapters never download models. Download the selected model separately and pass its local file paths in the plugin options. Sherpa publishes compatible files in its TTS model releases.
Listen and set the voice
Piper Amy
Package @suitecut/audio-vits. Model en_US-amy-low. Voicedefault. Speed 1. Sample text: "This is the Piper Amy voice, running through the VITS audio plugin."
Piper Amy has one speaker, so set voice: 'default'. For a multi-speaker model, use its numeric speaker ID as the voice, such as voice: '2', or give the ID a name inspeakerIds.
test.use({
suitecutAudioPlugins: [
{
provider: 'vits-cast',
module: '@suitecut/audio-vits',
options: {
model: './models/cast/model.onnx',
tokens: './models/cast/tokens.txt',
speakerIds: { narrator: 2 },
},
},
],
})
test('uses a named speaker', async ({ suitecut }) => {
await suitecut.narrate('Welcome to the tour.', {
provider: 'vits-cast',
voice: 'narrator',
})
})Plain Playwright
Pass the same references as audioPlugins in record() ordefineSuiteCut(). The provider in narrate() must match the configured provider ID.
Write a plugin
Export one ESM plugin object from the package default entry. Its synthesize() method receives text, voice, speed, output path, and JSON options. It must write mono PCM WAV before it resolves.
import { writeFile } from 'node:fs/promises'
import {
defineSuiteCutAudioPlugin,
encodePcm16Wav,
} from 'suitecut/audio-plugin'
export default defineSuiteCutAudioPlugin({
async synthesize({ text, voice, speed, outputPath, options }) {
const { samples, sampleRate } = await runModel({ text, voice, speed, options })
await writeFile(outputPath, encodePcm16Wav(samples, sampleRate))
},
})Provider IDs use lowercase letters, numbers, dots, underscores, and hyphens. Plugins cannot replace kokoro or macos-say.