Skip to main content

A new tool from Storyteller: stalign

· 10 min read
Shane Friedman
Storyteller Creator

It’s been a long time coming: there’s now a standalone Storyteller alignment command line tool (and npm library)!

Continuing tefkah’s amazing work with Ghost Story, we now publish stalign to npm as @storyteller-platform/align and to GitLab as stalign.

The packages published to the GitLab Package Registry are standalone executable applications — this means that you don’t need Node.js installed to run them! You will still need ffmpeg installed and available on your PATH in order for the audio processing and transcription steps to run.

What is stalign?

This is a command line interface (CLI) for running just the alignment pipeline that Storyteller uses to automatically align audiobooks and ebooks. It’s also an npm package, and Storyteller uses it directly through this programmatic interface. That means that when you run the CLI, you’re using exactly the same code that Storyteller uses for alignment!

How to use it

Installation

If you already have Node.js and npm installed, you can use npx to run the CLI. Note that stalign requires at least Node.js v24 or higher:

npx @storyteller-platform/align --help

If you want to use the standalone executable instead, so that you don’t have to worry about Node.js versions, you can download the latest executable from GitLab: https://gitlab.com/storyteller-platform/storyteller/-/packages?orderBy=created_at&sort=desc&search[]=stalign. Make sure you download the executable for your operating system and architecture. On macOS and Linux, you can use chmod +x ./stalign-<os>-<arch> to make the downloaded file executable. You can also place the file somewhere on your path, e.g., ~/.local/bin, and rename it to stalign. Then you can simply run:

stalign --help

Usage

$ ~/Downloads/stalign-linux-x64 --help
Usage: stalign process [--parallel INTEGER] [--codec TYPE] [--bitrate BITRATE] [--max-length INTEGER] [--no-progress] [--log-level TYPE] [--time]
INPUT OUTPUT
stalign-linux-x64 transcribe [--parallel INTEGER] [--language LOCALE] (--engine/-e whisper.cpp [--model/-m MODEL] [--threads INTEGER] [--processors
INTEGER] [--cpu-override CPU_ENGINE] | --engine/-e whisper-server --whisper-server-url URL [--whisper-server-api-key STRING] | --engine/-e
openai-cloud [--openai-model STRING] [--openai-api-key STRING] [--openai-organization STRING] [--openai-base-url URL] | --engine/-e google-cloud
--google-cloud-api-key STRING | --engine/-e microsoft-azure --azure-service-region STRING --azure-subscription-key STRING | --engine/-e
amazon-transcribe --amazon-transcribe-region STRING --amazon-transcribe-access-key-id STRING --amazon-transcribe-secret-access-key STRING | --engine/
-e deepgram --deepgram-api-key STRING [--deepgram-model STRING]) [--no-progress] [--log-level TYPE] [--time] INPUT OUTPUT
stalign-linux-x64 markup [--granularity/-g TYPE] [--language LOCALE] [--no-progress] [--log-level TYPE] [--time] INPUT_PATH OUTPUT_PATH
stalign-linux-x64 align --transcriptions PATH --output PATH --audiobook PATH --epub PATH [--reports PATH] [--no-progress] [--log-level TYPE] [--time]
[--language LOCALE] [--granularity/-g TYPE]
stalign-linux-x64 [--processed-audio PATH] [--transcriptions PATH] [--markedup PATH] [--parallel-transcodes INTEGER] [--parallel-transcribes INTEGER]
--output PATH [--codec TYPE] [--bitrate BITRATE] [--max-length INTEGER] (--engine/-e whisper.cpp [--model/-m MODEL] [--threads INTEGER] [--processors
INTEGER] [--cpu-override CPU_ENGINE] | --engine/-e whisper-server --whisper-server-url URL [--whisper-server-api-key STRING] | --engine/-e
openai-cloud [--openai-model STRING] [--openai-api-key STRING] [--openai-organization STRING] [--openai-base-url URL] | --engine/-e google-cloud
--google-cloud-api-key STRING | --engine/-e microsoft-azure --azure-service-region STRING --azure-subscription-key STRING | --engine/-e
amazon-transcribe --amazon-transcribe-region STRING --amazon-transcribe-access-key-id STRING --amazon-transcribe-secret-access-key STRING | --engine/
-e deepgram --deepgram-api-key STRING [--deepgram-model STRING]) [--granularity/-g TYPE] [--language LOCALE] --audiobook PATH --epub PATH [--reports
PATH] [--no-progress] [--log-level TYPE] [--time]
stalign-linux-x64 help [COMMAND...]
stalign-linux-x64 completion [SHELL] [ARG...]
stalign-linux-x64 completions [SHELL] [ARG...]
stalign-linux-x64 --help
stalign-linux-x64 --version

A CLI to automatically align audiobooks and EPUB files, producing EPUBs with Media Overlays.

help Show help information.
completion Generate shell completion script or provide completions.
completions Generate shell completion script or provide completions.
--help Show help information.
--version Show version information.
process Process audiobook files for transcription.
transcribe Transcribe a directory of audiobook files.
markup Mark up an EPUB file at the provided granularity level
align Run forced alignment to determine where each sentence|word is spoken in the audiobook and produce a new EPUB package with
Media Overlays and embedded audio.
--processed-audio PATH
--transcriptions PATH
--markedup PATH
--parallel-transcodes INTEGER [1]
--parallel-transcribes INTEGER [1]
--output PATH
--granularity, -g TYPE [sentence] (choices: word, sentence)
--language LOCALE BCP 47 language tag representing the primary language of the audio (e.g. en-US)
--no-progress Disable the progress bar
--log-level TYPE Log level. If enabled, will disable progress bar. [silent] (choices: silent, debug, info, warn, error)
--time Whether to print timing statistics

Audio processing:
--codec TYPE The audio codec to transcode to. If unspecified, will copy audio data without transcoding. [copy] (choices: libopus,
lipmp3lame, aac, copy)
--bitrate BITRATE The audio bitrate to transcode to ()
--max-length INTEGER The maximum allowed length of a processed audio track, in minutes [120]

whisper.cpp:
--engine, -e whisper.cpp (choices: whisper.cpp)
--model, -m MODEL The whisper model to use [tiny.en] (choices: tiny, tiny.en, tiny-q5_1, tiny.en-q5_1, tiny-q8_0, base, base.en, base-q5_1, ...)
--threads INTEGER [4]
--processors INTEGER The number of processors to use (values greater than 1 may affect timing accuracy) [1]
--cpu-override CPU_ENGINE When provided, will use this whisper variant even if another is available (choices: blas, cpu)

whisper-server:
--engine, -e whisper-server (choices: whisper-server)
--whisper-server-url URL
--whisper-server-api-key STRING

openai-cloud:
--engine, -e openai-cloud (choices: openai-cloud)
--openai-model STRING
--openai-api-key STRING
--openai-organization STRING
--openai-base-url URL

google-cloud:
--engine, -e google-cloud (choices: google-cloud)
--google-cloud-api-key STRING

microsoft-azure:
--engine, -e microsoft-azure (choices: microsoft-azure)
--azure-service-region STRING
--azure-subscription-key STRING

amazon-transcribe:
--engine, -e amazon-transcribe (choices: amazon-transcribe)
--amazon-transcribe-region STRING
--amazon-transcribe-access-key-id STRING
--amazon-transcribe-secret-access-key STRING

deepgram:
--engine, -e deepgram (choices: deepgram)
--deepgram-api-key STRING
--deepgram-model STRING [nova-3]

Alignment:
--audiobook PATH
--epub PATH
--reports PATH

stalign has four subcommands: process, markup, transcribe, and align. It can also be run without specifying a subcommand, in which case the entire alignment pipeline will be run on the input book files.

stalign help process

Usage: stalign process [--parallel INTEGER] [--codec TYPE] [--bitrate BITRATE] [--max-length INTEGER] [--no-progress] [--log-level TYPE] [--time]
INPUT OUTPUT

Process audiobook files for transcription.

--parallel INTEGER How many files to attempt to transcode in parallel. [1]
--no-progress Disable the progress bar
--log-level TYPE Log level. If enabled, will disable progress bar. [silent] (choices: silent, debug, info, warn, error)
--time Whether to print timing statistics
INPUT
OUTPUT

Audio processing:
--codec TYPE The audio codec to transcode to. If unspecified, will copy audio data without transcoding. [copy] (choices: libopus,
lipmp3lame, aac, copy)
--bitrate BITRATE The audio bitrate to transcode to ()
--max-length INTEGER The maximum allowed length of a processed audio track, in minutes [120]
stalign help markup

Usage: stalign-linux-x64 markup [--granularity/-g TYPE] [--language LOCALE] [--no-progress] [--log-level TYPE] [--time] INPUT_PATH OUTPUT_PATH

Mark up an EPUB file at the provided granularity level

--granularity, -g TYPE [sentence] (choices: word, sentence)
--language LOCALE BCP 47 language tag representing the primary language of the audio (e.g. en-US)
--no-progress Disable the progress bar
--log-level TYPE Log level. If enabled, will disable progress bar. [silent] (choices: silent, debug, info, warn, error)
--time Whether to print timing statistics
INPUT_PATH
OUTPUT_PATH
stalign help transcribe

Usage: stalign transcribe [--parallel INTEGER] [--language LOCALE] (--engine/-e whisper.cpp [--model/-m MODEL] [--threads INTEGER] [--processors
INTEGER] [--cpu-override CPU_ENGINE] | --engine/-e whisper-server --whisper-server-url URL [--whisper-server-api-key STRING] | --engine/-e
openai-cloud [--openai-model STRING] [--openai-api-key STRING] [--openai-organization STRING] [--openai-base-url URL] | --engine/-e google-cloud
--google-cloud-api-key STRING | --engine/-e microsoft-azure --azure-service-region STRING --azure-subscription-key STRING | --engine/-e
amazon-transcribe --amazon-transcribe-region STRING --amazon-transcribe-access-key-id STRING --amazon-transcribe-secret-access-key STRING | --engine/
-e deepgram --deepgram-api-key STRING [--deepgram-model STRING]) [--no-progress] [--log-level TYPE] [--time] INPUT OUTPUT

Transcribe a directory of audiobook files.

--parallel INTEGER How many files to attempt to transcode in parallel. [1]
--language LOCALE BCP 47 language tag representing the primary language of the audio (e.g. en-US)
--no-progress Disable the progress bar
--log-level TYPE Log level. If enabled, will disable progress bar. [silent] (choices: silent, debug, info, warn, error)
--time Whether to print timing statistics
INPUT
OUTPUT

whisper.cpp:
--engine, -e whisper.cpp (choices: whisper.cpp)
--model, -m MODEL The whisper model to use [tiny.en] (choices: tiny, tiny.en, tiny-q5_1, tiny.en-q5_1, tiny-q8_0, base, base.en, base-q5_1, ...)
--threads INTEGER [4]
--processors INTEGER The number of processors to use (values greater than 1 may affect timing accuracy) [1]
--cpu-override CPU_ENGINE When provided, will use this whisper variant even if another is available (choices: blas, cpu)

whisper-server:
--engine, -e whisper-server (choices: whisper-server)
--whisper-server-url URL
--whisper-server-api-key STRING

openai-cloud:
--engine, -e openai-cloud (choices: openai-cloud)
--openai-model STRING
--openai-api-key STRING
--openai-organization STRING
--openai-base-url URL

google-cloud:
--engine, -e google-cloud (choices: google-cloud)
--google-cloud-api-key STRING

microsoft-azure:
--engine, -e microsoft-azure (choices: microsoft-azure)
--azure-service-region STRING
--azure-subscription-key STRING

amazon-transcribe:
--engine, -e amazon-transcribe (choices: amazon-transcribe)
--amazon-transcribe-region STRING
--amazon-transcribe-access-key-id STRING
--amazon-transcribe-secret-access-key STRING

deepgram:
--engine, -e deepgram (choices: deepgram)
--deepgram-api-key STRING
--deepgram-model STRING [nova-3]
stalign help align

Usage: stalign align --transcriptions PATH --output PATH --audiobook PATH --epub PATH [--reports PATH] [--no-progress] [--log-level TYPE] [--time]
[--language LOCALE] [--granularity/-g TYPE]

Run forced alignment to determine where each sentence|word is spoken in the audiobook and produce a new EPUB package with Media Overlays and embedded audio.

--transcriptions PATH
--output PATH
--no-progress Disable the progress bar
--log-level TYPE Log level. If enabled, will disable progress bar. [silent] (choices: silent, debug, info, warn, error)
--time Whether to print timing statistics
--language LOCALE BCP 47 language tag representing the primary language of the audio (e.g. en-US)
--granularity, -g TYPE [sentence] (choices: word, sentence)

Alignment:
--audiobook PATH
--epub PATH
--reports PATH

Caveats

The --granulariy flag doesn’t currently do anything — support for word-level granularity is coming soon!

There seems to be an issue with our macOS automated builds, and we haven’t figured out Windows builds yet. In the meantime, you can still use npx to run stalign on those platforms. We will have full OS support soon!