The lyrics editor for Better Lyrics.
Create word-synced TTML lyrics with a visual timeline, tap-to-sync, and live preview.
Tools like AMLL TTML Tool are powerful, and if you already know TTML they're great. If you're new to syncing lyrics, the learning curve is steep. There's no obvious place to start, and the interface expects you to understand word-level timing and agent roles before you've synced a single line.
Composer is built around one linear path: import, edit, sync, export. Each tab is one step. You don't need to know what TTML is. Paste your lyrics, tap along with the music, and you have a synced file.
When you want more control, the Timeline does everything from one screen: load audio, add lyrics, drag word blocks on the waveform, split syllables, assign singers, and preview the result. Most people start with the tabs and move to the Timeline once they're comfortable.
- Import an audio file (MP3, WAV, M4A, OGG, FLAC) or paste a YouTube link
- Edit the lyrics, assign singers, and add background vocals
- Sync by tapping along with the music, or by dragging word blocks on the Timeline
- Export TTML, or keep working later from the projects library
Your work saves automatically in the browser as you go. Audio files you load stay on your machine.
- Tap-to-sync: press Space in time with the music to stamp each word, or hold to stretch it. Works with touch too.
- Timeline editor: a DAW-style view with draggable word blocks on a waveform, multi-select, and proportional stretch
- Snapping to neighboring words, the playhead, your own markers, and detected vocal onsets
- Syllable splitting, so each part of a word gets its own timing
- Linked groups for repeated sections like choruses. Edit one instance and the others follow, timing included.
- Vocal separation that isolates the vocal stem in the browser, so you can sync against the voice alone
- Multiple singers, each with their own color, plus background vocals exported with the TTML
x-bgrole - Translations and romanization, generated automatically or written by hand
- Song details and songwriter credits
- A lyric best practices guide that checks your lyrics against common conventions
- Lyrics import from
.txt,.lrc,.srt,.ttml, and.qrcfiles, or pasted straight into the Edit tab - TTML export, with an editable TTML view before you download
- Standalone converters between TTML and LRC, SRT, and QRC
- Project files and backup bundles you can share or restore on another machine
- Projects library with search, recent projects, and storage management
- Live preview rendered with Better Lyrics' own engine
- Themes, with dark and light presets and a custom theme editor
- Keyboard shortcuts for nearly everything, all of them remappable
- Searchable help and settings, plus written guides on TTML and syncing
Composer emits a restricted subset of TTML 1 (W3C Recommendation, Nov 2018). Word-span times are absolute and timestamps omit the hours field when it is zero, so the output is not strict TTML 1. Linked groups and per-instance metadata use foreign-namespace extensions, which the spec allows and downstream tools can ignore.
For the full breakdown, see Help → TTML & standards in the app.
Composer is a static site, and almost everything runs in the browser. A few optional features need a network service:
| Feature | Service | Without it |
|---|---|---|
| YouTube import | Composer Bridge running on your own machine, or a Cobalt instance (VITE_COBALT_API_URL) |
Load audio files instead |
| Translations and romanization | Google Translate, called from the browser | Write them by hand or paste them in |
| Vocal separation | The HTDemucs model, downloaded once from VITE_VOCAL_MODEL_BASE_URL |
The stem picker is hidden |
pnpm install
pnpm buildServe dist/ with any static file server, for example npx serve dist, nginx, Caddy, or Cloudflare. The hosted version deploys to Cloudflare Workers with wrangler.jsonc.
Requires Node 24 and pnpm 10.
pnpm install
pnpm dev # Start dev server with HMR
pnpm test # Run all tests (unit + browser)
pnpm test:unit # Unit tests only (jsdom)
pnpm test:component # Component tests only (Chromium via Playwright)
pnpm lint:fix # Format and lint
pnpm typecheck # Type checkVocal separation uses HTDemucs (Hybrid Transformer Demucs v4) and runs entirely in the browser through ONNX Runtime Web, on WebGPU when available and WASM otherwise. The model is larger than Cloudflare's 25 MiB static asset limit, so it isn't bundled. It's served from a public Cloudflare R2 bucket instead: R2 egress is free, and a custom domain keeps the file cached at Cloudflare's edge without a Worker in the way.
If VITE_VOCAL_MODEL_BASE_URL is unset, the vocal separation picker is hidden.
HTDemucs is the official Facebook AI Research model (facebookresearch/demucs, the Hybrid Transformer variant from Nov 2022). The demucs Python package downloads the PyTorch weights from dl.fbaipublicfiles.com on its own. Two community projects handle the ONNX side:
sevagh/demucs.onnxhas the most complete PyTorch to ONNX export. Its fork ofdemucsmoves STFT and iSTFT outside the graph so the model exports cleanly. The build script below uses it.gianlourbano/demucs-onnxis an onnxruntime-web reference, useful for checking the STFT and inference shapes on the JS side.
# 1. Build fp32 + fp16 ONNX models into ./htdemucs-onnx-out/.
# Takes 10 to 30 minutes on CPU and needs about 10 GB of free disk.
./scripts/build-htdemucs-onnx.sh
# 2. Upload to your R2 bucket (run `wrangler login` first).
./scripts/upload-htdemucs.sh composer-vocal-modelsbuild-htdemucs-onnx.sh clones sevagh/demucs.onnx into /tmp/composer-htdemucs-build/, sets up a Python venv, runs the official converter, then converts the fp32 export to fp16 with onnxconverter-common. At the end it prints the model's input and output names and its SHA-256. Check those against src/audio/separation/worker.ts and src/audio/separation/model-registry.ts.
- Create a public R2 bucket (for example
composer-vocal-models). - Bind a custom domain to it (for example
models.composer.betterlyrics.org). Avoidr2.dev: it's rate-limited and meant for development. - Add a Cloudflare
Cache Everythingpage rule for that hostname so the model is cached at the edge. - Add a CORS rule that allows your site's origin.
- Set
VITE_VOCAL_MODEL_BASE_URL=https://models.composer.betterlyrics.orgat build time.
Cost: free egress, and about $0.0015 a month to store the fp16 model.
React, TypeScript, Vite, Tailwind CSS v4, Zustand, Motion, Vitest
Important
Composer is free for everyone, hosted or self-hosted. If it saves you time or you find it useful, a donation helps keep it going!
Releasing lyrics made with Composer commercially, as a label, distributor or company? See License or reach out at composer@boidu.dev.
Composer is dual-licensed.
The open-source license is AGPL-3.0. You are free to use, modify, and self-host Composer under its terms.
A commercial license is also available. It removes the AGPL copyleft obligations and covers commercial use of Composer's output, such as a record label or distributor publishing generated lyrics as part of a release. For commercial or enterprise licensing, reach out to composer@boidu.dev.