
Product
Introducing Webhook Events for Alert Changes
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.
tts-narrator
Advanced tools
Generate narration with Text-To-Speech technology. Please note that you need to have an Azure TTS subscription key or ElevenLabs API key.
The input is a script file in YAML format. Example script files can be found under test/fixtures.
The script file is structured in this way:
settings: script settings
voice: voice settings at script levelchapters: array of chapter
settings: chapter level voice settings that can override script level voice settingssections: array of sections
settings: section level voice settings that can override upper level voice settingsparagraphs: array of paragraphs
settings: paragraph level voice settings that can override upper level voice settingstext: text content that needs to be converted into audiossml: SSML content that needs to be converted into audioThe text field of a paragraph can only be pure text, any XML tags will be escaped. Multi-line strings are supported.
The ssml field of a paragraph can be full or partial SSML fragment. Multi-line strings are supported.
When it is present, the text field will be ignored.
Please note that SSML is not supported by ElevenLabs.
It has command line flags --play and --no-play to control whether generated MP3s should be played back.
This feature is supported by a dev dependency node-speaker.
If you use it as a library in your project, and would like to have the play back capability, you need to install node-speaker as a dependency in your project.
When running on MacOS, to avoid illegal hardware instruction issue, try npm i speaker --mpg123-backend=openal
To use the CLI as an NPM package, you need to install it with all its optional dependencies, like this:
npm i -g --include=optional tts-narrator
USAGE
$ tts-narrator FILE [-h] [-v] [-d] [-s azure|elevenlabs]
[-k <value>] [--api-key-env <value>] [-r <value>] [-f <value>] [-p] [-i]
[-o] [--dry-run] [--ssml | -q] [--chapters <value>] [--sections <value>]
ARGUMENTS
FILE path to the script file (.yml)
FLAGS
-d, --debug output debug information
-f, --outputFormat=<value> [default: 3] Output format for audio
-h, --help Show help
-i, --interactive wait for key press before entering each section
-k, --api-key=<value> Azure Speech service subscription key or
ElevenLabs API key
-o, --overwrite always overwrite previously generated audio files
-p, --[no-]play play generated audio
-q, --quiet output warn and error information only
-r, --region=<value> Region of the text-to-speech service
-s, --service=<option> text-to-speech service to use
<options: azure|elevenlabs>
-v, --version Show CLI version
--api-key-env=<value> Name of the environment variable that holds the
Azure Speech service subscription key or
ElevenLabs API key
--chapters=<value> list of chapters to process, examples:
"1-10,13,15", "4-"
--dry-run don't try to generate or play audio
--sections=<value> list of sections to process, examples:
"1-10,13,15", "5-"
--ssml display generated SSML
DESCRIPTION
Generate narration with Text-To-Speech technology
EXAMPLES
$ tts-narrator myscript.yml --play --interactive --service azure --api-key-env TTS_SUBSCRIPTION_KEY --region australiaeast
$ tts-narrator ./test/fixtures/script3.yml -s azure --ssml -r australiaeast --api-key-env=TTS_SUB_KEY --no-play --interactive -d
$ tts-narrator ./test/fixtures/script3.yml -s azure -r australiaeast --api-key-env=TTS_SUB_KEY --quiet
$ tts-narrator ./test/fixtures/script4.yml -s elevenlabs --api-key-env=ELEVENLABS_API_KEY
$ tts-narrator ./test/fixtures/script3.yml
To use the NPM package as a dependency, you just need to install it normally, like this:
npm i tts-narrator
Example:
const ttsService = new AzureTtsService(...);
const ttsNarrator = new TtsNarrator(ttsService, './output-folder');
const script = await loadScript('./my-script.yml');
await ttsNarrator.narrate(script);
console.log(`One of the generated audio file is: ${script.chapters[0].sections[0].paragraphs[0].audioFilePath}`);
azure-tts-service.AzureTtsService
↳ AzureTtsService
• new AzureTtsService(options?)
| Name | Type |
|---|---|
options? | Omit<AzureAudioGenerationOptions, "outputFilePath"> |
| Property | Description |
|---|---|
Protected Optional options: Omit<AzureAudioGenerationOptions, "outputFilePath"> |
▸ Protected buildMsttsExpressAsStartTag(msttsExpressAsSettings): string
| Name | Type |
|---|---|
msttsExpressAsSettings | Object |
msttsExpressAsSettings.role? | string |
msttsExpressAsSettings.style? | string |
msttsExpressAsSettings.styleDegree? | string |
string
BaseTtsService.buildMsttsExpressAsStartTag
▸ Protected buildProsodyStartTag(prosodySettings): string
| Name | Type |
|---|---|
prosodySettings | Object |
prosodySettings.pitch? | string |
prosodySettings.rate? | string |
prosodySettings.volume? | string |
string
BaseTtsService.buildProsodyStartTag
▸ Protected buildSpeakStartTag(voiceSettings): string
| Name | Type |
|---|---|
voiceSettings | VoiceSettings |
string
BaseTtsService.buildSpeakStartTag
▸ Protected buildVoiceStartTag(voiceSettings): string
| Name | Type |
|---|---|
voiceSettings | VoiceSettings |
string
BaseTtsService.buildVoiceStartTag
▸ generateAudio(ssml, options): Promise<any>
| Name | Type |
|---|---|
ssml | string |
options | AzureAudioGenerationOptions | Pick<AzureAudioGenerationOptions, "outputFilePath"> |
Promise<any>
▸ generateSSML(paragraph): Promise<string>
| Name | Type |
|---|---|
paragraph | NarrationParagraph |
Promise<string>
▸ Protected generateSsmlWithoutValidation(paragraph): Object
| Name | Type |
|---|---|
paragraph | NarrationParagraph |
Object
| Name | Type |
|---|---|
lineOffset | number |
ssml | string |
BaseTtsService.generateSsmlWithoutValidation
▸ Protected validateXML(xml, lineOffset): void
| Name | Type |
|---|---|
xml | string |
lineOffset | number |
void
elevenlabs-tts-service.ElevenLabsTtsService
↳ ElevenLabsTtsService
• new ElevenLabsTtsService(options?)
| Name | Type |
|---|---|
options | { apiKey?: string } & Omit<ElevenLabsAudioGenerationOptions, "outputFilePath"> |
▸ Protected buildMsttsExpressAsStartTag(msttsExpressAsSettings): string
| Name | Type |
|---|---|
msttsExpressAsSettings | Object |
msttsExpressAsSettings.role? | string |
msttsExpressAsSettings.style? | string |
msttsExpressAsSettings.styleDegree? | string |
string
BaseTtsService.buildMsttsExpressAsStartTag
▸ Protected buildProsodyStartTag(prosodySettings): string
| Name | Type |
|---|---|
prosodySettings | Object |
prosodySettings.pitch? | string |
prosodySettings.rate? | string |
prosodySettings.volume? | string |
string
BaseTtsService.buildProsodyStartTag
▸ Protected buildSpeakStartTag(voiceSettings): string
| Name | Type |
|---|---|
voiceSettings | VoiceSettings |
string
BaseTtsService.buildSpeakStartTag
▸ Protected buildVoiceStartTag(voiceSettings): string
| Name | Type |
|---|---|
voiceSettings | VoiceSettings |
string
BaseTtsService.buildVoiceStartTag
▸ generateAudio(specJSON, options): Promise<void>
| Name | Type |
|---|---|
specJSON | string |
options | ElevenLabsAudioGenerationOptions | Pick<ElevenLabsAudioGenerationOptions, "outputFilePath"> |
Promise<void>
▸ generateSSML(paragraph): Promise<string>
| Name | Type |
|---|---|
paragraph | NarrationParagraph |
Promise<string>
▸ Protected generateSsmlWithoutValidation(paragraph): Object
| Name | Type |
|---|---|
paragraph | NarrationParagraph |
Object
| Name | Type |
|---|---|
lineOffset | number |
ssml | string |
BaseTtsService.generateSsmlWithoutValidation
▸ Protected validateXML(xml, lineOffset): void
| Name | Type |
|---|---|
xml | string |
lineOffset | number |
void
narration-script.NarrationChapter
• new NarrationChapter(chapter, index, script)
| Name | Type |
|---|---|
chapter | Chapter |
index | number |
script | NarrationScript |
| Property | Description |
|---|---|
Protected chapter: Chapter | |
index: number | |
script: NarrationScript | |
sections: NarrationSection[] | Implementation of Chapter.sections |
• get key(): string
string
• get settings(): VoiceSettings
▸ getSectionByKey(key): undefined | NarrationSection
| Name | Type |
|---|---|
key | string |
undefined | NarrationSection
narration-script.NarrationParagraph
• new NarrationParagraph(paragraph, index, section, chapter, script)
| Name | Type |
|---|---|
paragraph | Paragraph |
index | number |
section | NarrationSection |
chapter | NarrationChapter |
script | NarrationScript |
| Property | Description |
|---|---|
Optional audioFilePath: string | Path of the generated audio file. Only for in-memory processing, not supposed to be stored in file. |
chapter: NarrationChapter | |
index: number | |
Protected paragraph: Paragraph | |
script: NarrationScript | |
section: NarrationSection |
• get key(): string
string
• get settings(): VoiceSettings
• get ssml(): undefined | string
Full or partial SSML (a kind of XML)
If provided, it will be used instead of text.
If both text and ssml are provided, ssml will be used.
If both are empty, an error will be thrown.
undefined | string
• get text(): undefined | string
Text to be narrated, it can't be XML.
If you want to use XML, use ssml property instead.
If both text and ssml are provided, ssml will be used.
If both are empty, an error will be thrown.
undefined | string
narration-script.NarrationScript
• new NarrationScript(script, scriptFilePath)
| Name | Type |
|---|---|
script | Script |
scriptFilePath | string |
| Property | Description |
|---|---|
chapters: NarrationChapter[] | Implementation of Script.chapters |
Protected script: Script | |
scriptFilePath: string |
• get settings(): ScriptSettings
▸ export(): Script
▸ getChapterByKey(key): undefined | NarrationChapter
| Name | Type |
|---|---|
key | string |
undefined | NarrationChapter
narration-script.NarrationSection
• new NarrationSection(section, index, chapter, script)
| Name | Type |
|---|---|
section | Section |
index | number |
chapter | NarrationChapter |
script | NarrationScript |
| Property | Description |
|---|---|
chapter: NarrationChapter | |
index: number | |
paragraphs: NarrationParagraph[] | Implementation of Section.paragraphs |
script: NarrationScript | |
Protected section: Section |
• get key(): string
string
• get settings(): VoiceSettings
script-processor.ScriptProcessor
ScriptProcessor
• new ScriptProcessor(scriptFilePath, flags, cliConsole?)
| Name | Type |
|---|---|
scriptFilePath | string |
flags | Object & FlagOutput & {} |
cliConsole? | LineLogger<(message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void> |
| Property | Description |
|---|---|
Protected _chalk: undefined | null | Chalk & ChalkFunction & {} | |
Protected _prompts: undefined | null | typeof prompts | |
Protected _script: NarrationScript | |
Protected audioGenerationOptions: undefined | Omit<AudioGenerationOptions, "outputFilePath"> | |
Protected chapterRange: undefined | MultiRange | |
Protected cliConsole: LineLogger<(message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void> | |
Protected flags: Object & FlagOutput & {} | |
Protected scriptFilePath: string | |
Protected sectionRange: undefined | MultiRange | |
Protected ttsService: TtsService |
• Protected get chalk(): undefined | null | typeof prompts
chalk, or null caused by library not available
undefined | null | typeof prompts
• Protected get prompts(): undefined | null | typeof prompts
prompts function, or null caused by library not available
undefined | null | typeof prompts
• get script(): NarrationScript
▸ Protected determineAudioFilePath(ssmlHash, _paragraph): Promise<string>
| Name | Type |
|---|---|
ssmlHash | string |
_paragraph | NarrationParagraph |
Promise<string>
▸ Protected hash(ssml, _paragraph): string
| Name | Type |
|---|---|
ssml | string |
_paragraph | NarrationParagraph |
string
▸ Protected initialiseTtsServiceIfNeeded(): Promise<void>
Promise<void>
▸ Protected loadScriptIfNeeded(): Promise<void>
Promise<void>
▸ Protected parseRanges(): void
void
▸ Protected processGeneratedAudioFile(audioFilePath): Promise<string>
| Name | Type |
|---|---|
audioFilePath | string |
Promise<string>
▸ run(reconstructedCommandLine?): Promise<void>
| Name | Type |
|---|---|
reconstructedCommandLine? | string |
Promise<void>
▸ runWithoutCatch(reconstructedCommandLine?): Promise<void>
| Name | Type |
|---|---|
reconstructedCommandLine? | string |
Promise<void>
tts-narrator.TtsNarrator
Class for generating narration.
Instance of this class can be used to generate narration audio for scripts by calling the narrate(...) method.
Example
const ttsService = new AzureTtsService(...);
const ttsNarrator = new TtsNarrator(ttsService, './output-folder');
const script = await loadScript('./my-script.yml');
await ttsNarrator.narrate(script);
console.log(`One of the generated audio file is: ${script.chapters[0].sections[0].paragraphs[0].audioFilePath}`);
↳ TtsNarrator
• new TtsNarrator(ttsService, audioFileFolder, options?, cliConsole?)
Constructor
| Name | Type | Default value | Description |
|---|---|---|---|
ttsService | TtsService | undefined | The TTS service to be used for generating audio |
audioFileFolder | string | undefined | The folder that generated audio files will be placed |
options? | Partial<Object & FlagOutput & {}> | undefined | Optional settings |
cliConsole | LineLogger<(message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void> | silentLogger | Optional logger |
| Property | Description |
|---|---|
Protected _chalk: undefined | null | Chalk & ChalkFunction & {} | Inherited from ScriptProcessor._chalk |
Protected _prompts: undefined | null | typeof prompts | Inherited from ScriptProcessor._prompts |
Protected _script: NarrationScript | Inherited from ScriptProcessor._script |
Protected audioFileFolder: string | The folder that generated audio files will be placed |
Protected audioGenerationOptions: undefined | Omit<AudioGenerationOptions, "outputFilePath"> | Inherited from ScriptProcessor.audioGenerationOptions |
Protected chapterRange: undefined | MultiRange | Inherited from ScriptProcessor.chapterRange |
Protected cliConsole: LineLogger<(message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void, (message?: any, ...optionalParams: any[]) => void> | Inherited from ScriptProcessor.cliConsole |
Protected flags: Object & FlagOutput & {} | Inherited from ScriptProcessor.flags |
Protected scriptFilePath: string | Inherited from ScriptProcessor.scriptFilePath |
Protected sectionRange: undefined | MultiRange | Inherited from ScriptProcessor.sectionRange |
Protected ttsService: TtsService | Inherited from ScriptProcessor.ttsService |
• Protected get chalk(): undefined | null | typeof prompts
chalk, or null caused by library not available
undefined | null | typeof prompts
ScriptProcessor.chalk
• Protected get prompts(): undefined | null | typeof prompts
prompts function, or null caused by library not available
undefined | null | typeof prompts
ScriptProcessor.prompts
• get script(): NarrationScript
ScriptProcessor.script
▸ Protected determineAudioFilePath(ssmlHash, _paragraph): Promise<string>
| Name | Type |
|---|---|
ssmlHash | string |
_paragraph | NarrationParagraph |
Promise<string>
ScriptProcessor.determineAudioFilePath
▸ Protected hash(ssml, _paragraph): string
| Name | Type |
|---|---|
ssml | string |
_paragraph | NarrationParagraph |
string
▸ Protected initialiseTtsServiceIfNeeded(): Promise<void>
Promise<void>
ScriptProcessor.initialiseTtsServiceIfNeeded
▸ Protected loadScriptIfNeeded(): Promise<void>
Promise<void>
ScriptProcessor.loadScriptIfNeeded
▸ narrate(script): Promise<void>
Generate narration for the script
| Name | Type | Description |
|---|---|---|
script | NarrationScript | the input script which will also be modified for recording audioFilePath |
Promise<void>
nothing
▸ Protected parseRanges(): void
void
▸ Protected processGeneratedAudioFile(audioFilePath): Promise<string>
| Name | Type |
|---|---|
audioFilePath | string |
Promise<string>
ScriptProcessor.processGeneratedAudioFile
▸ run(reconstructedCommandLine?): Promise<void>
| Name | Type |
|---|---|
reconstructedCommandLine? | string |
Promise<void>
▸ runWithoutCatch(reconstructedCommandLine?): Promise<void>
| Name | Type |
|---|---|
reconstructedCommandLine? | string |
Promise<void>
ScriptProcessor.runWithoutCatch
tts-narrator-cli.export=
Command
↳ export=
• new export=(argv, config)
| Name | Type |
|---|---|
argv | string[] |
config | Config |
Command.constructor
| Property | Description |
|---|---|
Static args: Object | Type declaration |
Static description: string = 'Generate narration with Text-To-Speech technology' | Overrides Command.description |
Static examples: string[] | Overrides Command.examples |
Static flags: Object | Type declaration |
Static id: string = ' ' | Overrides Command.id |
▸ run(): Promise<void>
Promise<void>
Command.run
tts-service.BaseTtsService
BaseTtsService
• new BaseTtsService()
▸ Protected buildMsttsExpressAsStartTag(msttsExpressAsSettings): string
| Name | Type |
|---|---|
msttsExpressAsSettings | Object |
msttsExpressAsSettings.role? | string |
msttsExpressAsSettings.style? | string |
msttsExpressAsSettings.styleDegree? | string |
string
▸ Protected buildProsodyStartTag(prosodySettings): string
| Name | Type |
|---|---|
prosodySettings | Object |
prosodySettings.pitch? | string |
prosodySettings.rate? | string |
prosodySettings.volume? | string |
string
▸ Protected buildSpeakStartTag(voiceSettings): string
| Name | Type |
|---|---|
voiceSettings | VoiceSettings |
string
▸ Protected buildVoiceStartTag(voiceSettings): string
| Name | Type |
|---|---|
voiceSettings | VoiceSettings |
string
▸ generateAudio(_ssml, _options): Promise<void>
| Name | Type |
|---|---|
_ssml | string |
_options | AudioGenerationOptions |
Promise<void>
▸ generateSSML(paragraph): Promise<string>
| Name | Type |
|---|---|
paragraph | NarrationParagraph |
Promise<string>
▸ Protected generateSsmlWithoutValidation(paragraph): Object
| Name | Type |
|---|---|
paragraph | NarrationParagraph |
Object
| Name | Type |
|---|---|
lineOffset | number |
ssml | string |
▸ Protected validateXML(xml, lineOffset): void
| Name | Type |
|---|---|
xml | string |
lineOffset | number |
void
tts-service.TtsServiceType
• Azure = "azure"
• ElevenLabs = "elevenlabs"
azure-tts-service.AzureAudioGenerationOptions
↳ AzureAudioGenerationOptions
| Property | Description |
|---|---|
outputFilePath: string | Inherited from AudioGenerationOptions.outputFilePath |
Optional outputFormat: SpeechSynthesisOutputFormat | |
Optional serviceRegion: string | |
Optional subscriptionKey: string |
narration-script.NarrationScriptFile.Chapter
| Property | Description |
|---|---|
Optional key: string | |
sections: Section[] | |
Optional settings: VoiceSettings |
narration-script.NarrationScriptFile.Paragraph
| Property | Description |
|---|---|
Optional key: string | |
Optional settings: VoiceSettings | |
Optional ssml: string | Full or partial SSML (a kind of XML) If provided, it will be used instead of text.If both text and ssml are provided, ssml will be used.If both are empty, an error will be thrown. |
Optional text: string | Text to be narrated, it can't be XML. If you want to use XML, use ssml property instead.If both text and ssml are provided, ssml will be used.If both are empty, an error will be thrown. |
narration-script.NarrationScriptFile.Script
| Property | Description |
|---|---|
chapters: Chapter[] | |
settings: ScriptSettings |
narration-script.NarrationScriptFile.Section
| Property | Description |
|---|---|
Optional key: string | |
paragraphs: Paragraph[] | |
Optional settings: VoiceSettings |
narration-script.ScriptSettings
| Property | Description |
|---|---|
Optional service: TtsServiceType | |
Optional voice: VoiceSettings |
narration-script.VoiceSettings
| Property | Description |
|---|---|
Optional effect: string | Voice effect, corresponding to speak.voice#effect in SSML. |
Optional language: string | Language, corresponding to speak#xml:lang in SSML. |
Optional msttsExpressAs: Object | Corresponding to speak.voice.mstts:express-as in SSML.Type declaration |
Optional name: string | Voice name, corresponding to speak.voice#name in SSML. |
Optional prosody: Object | Corresponding to speak.voice.prosody in SSML.Type declaration |
tts-service.AudioGenerationOptions
AudioGenerationOptions
| Property | Description |
|---|---|
outputFilePath: string |
tts-service.TtsService
▸ generateAudio(ssml, options): Promise<void>
| Name | Type |
|---|---|
ssml | string |
options | AudioGenerationOptions |
Promise<void>
▸ generateSSML(paragraph): Promise<string>
| Name | Type |
|---|---|
paragraph | NarrationParagraph |
Promise<string>
▸ getAudioFileDuration(filePath): Promise<number>
| Name | Type |
|---|---|
filePath | string |
Promise<number>
▸ playMp3File(filePath, infoLogger): Promise<void>
| Name | Type |
|---|---|
filePath | string |
infoLogger | (msg: string) => void |
Promise<void>
Ƭ ElevenLabsAudioGenerationOptions: AudioGenerationOptions & Omit<ElevenLabs.TextToSpeechRequest, "text">
Re-exports AudioGenerationOptions
Re-exports AzureAudioGenerationOptions
Re-exports AzureTtsService
Re-exports BaseTtsService
Re-exports ElevenLabsAudioGenerationOptions
Re-exports ElevenLabsTtsService
Re-exports NarrationChapter
Re-exports NarrationParagraph
Re-exports NarrationScript
Re-exports NarrationScriptFile
Re-exports NarrationSection
Re-exports ScriptProcessor
Re-exports ScriptSettings
Re-exports TtsNarrator
Re-exports TtsService
Re-exports TtsServiceType
Re-exports VoiceSettings
Re-exports escapeXml
Re-exports getAudioFileDuration
Re-exports loadScript
Re-exports normaliseRate
Re-exports playMp3File
Re-exports saveScript
narration-script.NarrationScriptFile
▸ loadScript(scriptFilePath): Promise<NarrationScript>
| Name | Type |
|---|---|
scriptFilePath | string |
Promise<NarrationScript>
▸ saveScript(script): Promise<void>
| Name | Type |
|---|---|
script | NarrationScript |
Promise<void>
▸ saveScript(script, scriptFilePath): Promise<void>
| Name | Type |
|---|---|
script | Script |
scriptFilePath | string |
Promise<void>
Ƭ ScriptProcessorFlags: CommandOptions<{ flags: typeof scriptProcessorFlags }>["flags"]
• Const scriptProcessorFlags: Object
CLI flags that are required/used by the ScriptProcessor.
| Name | Type |
|---|---|
api-key | OptionFlag<undefined | string, CustomOptions> |
api-key-env | OptionFlag<undefined | string, CustomOptions> |
chapters | OptionFlag<undefined | string, CustomOptions> |
debug | BooleanFlag<boolean> |
dry-run | BooleanFlag<boolean> |
interactive | BooleanFlag<boolean> |
outputFormat | OptionFlag<number, CustomOptions> |
overwrite | BooleanFlag<boolean> |
play | BooleanFlag<boolean> |
quiet | BooleanFlag<boolean> |
region | OptionFlag<undefined | string, CustomOptions> |
sections | OptionFlag<undefined | string, CustomOptions> |
service | OptionFlag<undefined | string, CustomOptions> |
ssml | BooleanFlag<boolean> |
▸ escapeXml(text): string
| Name | Type |
|---|---|
text | string |
string
▸ normaliseRate(rate?, min?, max?): number | undefined
| Name | Type | Default value |
|---|---|---|
rate? | string | undefined |
min | number | 0.5 |
max | number | 2 |
number | undefined
FAQs
Generate narration with Text-To-Speech technology
The npm package tts-narrator receives a total of 24 weekly downloads. As such, tts-narrator popularity was classified as not popular.
We found that tts-narrator demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.

Security News
ENISA has become a CVE Program Root, giving the EU a central authority for coordinating vulnerability reporting, disclosure, and cross-border response.

Product
Socket now scans OpenVSX extensions, giving teams early detection of risky behaviors, hidden capabilities, and supply chain threats in developer tools.