Configuration
anyscribe uses two locations: a visible workspace for your transcripts and a hidden directory for app internals.
scribeandascliare shorter aliases foranyscribe— all three commands are interchangeable everywhere in this guide.
File Locations
| File | Path | What it stores |
|---|---|---|
| Workspace | ~/anyscribe/ |
Your Obsidian vault with all transcripts (configurable) |
| Config | ~/.anyscribe/config.yaml |
Your preferences (provider, language, etc.) |
| API Keys | ~/.anyscribe/.env |
Secret API keys (never committed to git) |
| Downloads | ~/.anyscribe/downloads/ |
Downloaded audio/video files |
| Logs | ~/.anyscribe/logs/ |
Processing logs |
| Sessions | ~/.anyscribe/sessions/ |
Cached sessions (legacy; no longer used for Instagram) |
| Temp | ~/.anyscribe/tmp/ |
Temporary downloads (auto-cleaned) |
Upgrading from an older version? If you have transcripts at
~/.anyscribe/workspace/, anyscribe will automatically move them to~/anyscribe/on your next transcription.Upgrading from the old
anyscribeclipackage? The app folder moved from~/.anyscribecli/to~/.anyscribe/. This normally happens automatically on your next transcription, but if your keys ever seem to have vanished after upgrading, runanyscribe migrate(add--dry-runfirst to preview). It moves your config, keys, and downloads across without ever overwriting anything already in the new folder. See Commands → anyscribe migrate.Tip: Run
anyscribe doctorto see if all these exist and are healthy.
config.yaml
This is your main settings file. The onboarding wizard creates it, but you can also edit it directly.
# ~/.anyscribe/config.yaml
provider: openai # Explicit provider (used when quality is `custom`)
provider_models: {} # Which model each provider should use (empty = defaults)
extra_models: {} # Your own OpenRouter model names, added to the picker
quality: balanced # accuracy | balanced | cost | free | custom — picks the provider
language: auto # Language for transcription
local_model: base # Offline Whisper size (local provider only)
keep_media: false # Whether to save audio files
output_format: clean # How to format transcripts
diarize: false # Enable speaker diarization by default
prompt_download: never # Ask to download video after transcription
local_file_media: skip # What to do with local files after transcription
workspace_path: "" # Empty = ~/anyscribe (default), or set a custom path
instagram: # Instagram settings
browser: "" # Browser to read cookies from (e.g. firefox, chrome)
Note: API keys are stored in
~/.anyscribe/.env, not in config.yaml. Secrets never go in config.Adding and removing keys: Set a key with
anyscribe config set openai_api_key sk-…, or in the Web UI under Settings → Providers (expand a provider to paste one). To remove a saved key, open that provider in the Web UI and click Remove key → Remove? — it's deleted from.env. You can also just delete the line from~/.anyscribe/.envby hand. A key you set through your shell environment (e.g.export OPENAI_API_KEY=…in your shell profile) isn't stored in.env, so the Web UI can't remove it — unset it in your shell.Everything here is also editable in the Web UI (
anyscribe ui→ Settings) — the page opens with a "Next run" banner showing exactly what your next transcription will use and why, the provider and model controls are always visible (a tier just pre-selects them), and a "Downloads & media" section covers download prompting, local-file handling, kept media, and the Instagram cookie browser. Nothing needs the terminal.
Settings Explained
One knob picks the provider
quality and provider are not two competing settings — they are one knob with
two positions. quality is either a tier (accuracy, balanced, cost,
free), in which case the tier picks the provider, or it is custom, in which
case your provider line is used as-is.
anyscribe config set quality accuracy # tier picks the provider (ElevenLabs)
anyscribe config set provider deepgram # also sets quality = custom, so it sticks
Setting a provider always writes
quality: customin the same save. That's deliberate: without it, the next run would go back to the tier's provider and your choice would silently vanish. This happens wherever you set a provider —anyscribe config set provider, the Web UI Settings page, the MCPset_configtool.
To see which one is winning right now, run anyscribe config
with no subcommand:
Next run: deepgram · nova-3 (quality: balanced)
The (...) at the end names the reason: config (your provider line),
quality: <tier>, flag (a --provider you passed), or diarize.
provider
Which API to use for transcription when quality is custom. Default: openai.
| Value | Service | What you need |
|---|---|---|
openai |
OpenAI Whisper API | OPENAI_API_KEY in .env |
deepgram |
Deepgram Nova (diarization + hi-Latn) | DEEPGRAM_API_KEY |
openrouter |
OpenRouter (audio-via-chat models) | OPENROUTER_API_KEY |
elevenlabs |
ElevenLabs Scribe v2 (highest accuracy, 90+ languages) | ELEVENLABS_API_KEY |
sargam |
Sarvam AI (23 Indic languages + English) | SARGAM_API_KEY |
groq |
Groq (fast, cheap Whisper large-v3-turbo) | GROQ_API_KEY |
local |
faster-whisper (offline, free) | None needed |
Tip: If you don't have a strong opinion, leave
qualityon a tier (below) and don't touchproviderat all — the tier chooses for you.Why multiple providers? Different services handle different languages better. OpenAI Whisper is a good default, ElevenLabs has high accuracy across 90+ languages, Sarvam excels at Indian languages, and the local provider is free and works offline.
Local provider requires
pip install faster-whisper. Models download automatically on first use. Works on CPU (slower) or GPU (fast with CUDA).
provider_models
Which model each provider should use. A provider is the service (OpenAI, Groq...); a model is the specific engine inside it. Every provider has a sensible default, so this setting starts empty and most people never touch it.
Set one with anyscribe config set:
anyscribe config set provider_models.openai gpt-transcribe
anyscribe config set provider_models.groq whisper-large-v3
Which produces:
provider_models:
openai: gpt-transcribe
groq: whisper-large-v3
Each provider gets its own line, so switching providers keeps each one's chosen model. Any provider not listed uses its default.
To see the options, run anyscribe config (no subcommand) or anyscribe providers list — both show every provider, the model it would use, and the alternatives.
To go back to the default, delete that line from config.yaml.
For one run only, skip config entirely and use the --model flag: anyscribe "url" -p openai -m gpt-transcribe. That wins over whatever is in provider_models.
If you set a model a provider doesn't have, anyscribe refuses and prints the valid list. (OpenRouter is the exception — it takes any audio-capable model name, so anyscribe passes yours straight through. See extra_models below to keep your own names in the picker.)
Timestamps are handled for you. OpenAI's default model,
gpt-transcribe, is cheaper and more accurate thanwhisper-1— but it can't tell you when something was said. If youroutput_formatistimestampedordiarized, anyscribe quietly switches that run towhisper-1and prints a note saying so:
→ openai · whisper-1 (config) switched to whisper-1 — gpt-transcribe can't produce timestampsThe switch only happens when anyscribe picked the model. If you passed
-m gpt-transcribefor that run, anyscribe respects it and you get plain paragraphs — you asked for that model explicitly.The
localprovider isn't set here. Its models are files on your machine, so they live inlocal_model(below).
extra_models
Your own model names for OpenRouter, merged into every model picker
(the anyscribe config dashboard, anyscribe providers list, the Web UI dropdown).
anyscribe config set extra_models.openrouter "qwen/qwen3-omni-flash,openai/gpt-audio"
anyscribe config set extra_models.openrouter "" # empty value clears the list
extra_models:
openrouter:
- qwen/qwen3-omni-flash
- openai/gpt-audio
They show up alongside the built-in suggestions, marked (custom) so you can
tell yours apart. In the Web UI, the OpenRouter model box is a free-text field
with the same merged list as suggestions.
Only OpenRouter accepts this.
anyscribe config set extra_models.deepgram …is rejected on purpose. OpenRouter is a router — it will forward any model name and the model does the rest. Every other provider needs code that knows how to read that specific model's response, so their lists are curated and shipped with anyscribe releases. If a provider added a model you want, that's an anyscribe update, not a config change — runanyscribe update.
quality
Pick what you want — higher accuracy or lower cost — and anyscribe chooses the
provider for you. Default: balanced (Deepgram). This is the easiest way to use
anyscribe; you rarely need to touch provider directly.
| Value | Picks | Best for |
|---|---|---|
balanced (default) |
Deepgram nova-3 |
Strong accuracy + native speaker labels |
accuracy |
ElevenLabs scribe_v2 |
Highest accuracy, primarily-English |
cost |
Groq whisper-large-v3-turbo |
Cheapest + fastest cloud (~$0.04/hr) |
free |
Local faster-whisper | Offline, $0 (needs anyscribe local setup) |
custom |
Whatever provider says |
You picked a provider yourself |
Change it with anyscribe config set quality cost, per-run with
anyscribe transcribe <url> --quality cost, or from the picker in the Web UI.
How it works: the tier picks a provider. If you pass
--provider(or pick one in the Web UI), that wins for that run.customisn't a tier — it's the "hands off, use myprovider" setting, and anyscribe writes it for you whenever you set a provider.Need a key: each tier needs that provider's key in
.env—accuracyneedsELEVENLABS_API_KEY,costneedsGROQ_API_KEY, etc.freeneeds no key.If the tier's key is missing, anyscribe says so and keeps going with your configured
providerinstead of failing:
→ openai · gpt-transcribe (config) WARNING: quality 'balanced' wants deepgram but no DEEPGRAM_API_KEY is set — using openai insteadEither add the key (
anyscribe config set deepgram_api_key …) or pick a tier you have a key for. The warning appears on every surface — CLI runs,anyscribe config, the Web UI, and MCP results.
language
What language to expect in the audio. Default: auto (let the API auto-detect).
Use standard language codes: en (English), es (Spanish), fr (French), hi (Hindi), ar (Arabic), zh (Chinese), ja (Japanese), ko (Korean), etc.
Each provider expects codes in a slightly different format — Whisper-family providers (openai, local) use ISO 639-1 like en, Deepgram uses BCP-47 codes (a standard format for language tags, like en-US or hi-Latn), and Sarvam uses BCP-47 with -IN suffixes like hi-IN. If you're unsure, the web UI (anyscribe ui) shows a per-provider dropdown of every supported code on the Transcribe page Options panel.
When to set this explicitly: Auto-detection works well for most videos, but if you're transcribing content in a specific language and getting wrong results, setting the language explicitly helps. You can also override per-video:
anyscribe transcribe <url> --language hi
keep_media
Whether to save the downloaded audio file alongside the transcript. Default: false.
When true, audio files are saved to ~/.anyscribe/downloads/audio/<platform>/ (separate from the Obsidian workspace). This uses more disk space but lets you re-listen or re-transcribe later without downloading again.
Disk space: A 10-minute video at 64kbps mono is about 5MB of audio. If you transcribe a lot, this adds up.
output_format
How to format the transcript text. Default: clean.
| Value | Description |
|---|---|
clean |
Plain text transcript, paragraphs only |
timestamped |
Transcript with [mm:ss] timestamps per segment |
diarized |
Speaker-grouped turns with timestamps (for multi-speaker audio) |
Tip: When you use
--diarize, the output format is automatically set todiarizedunless you've explicitly set it totimestamped.Web UI label: The
diarizedvalue is shown aswith-speaker-labelsinanyscribe ui. The wire value (what gets stored inconfig.yaml) is unchanged — picking either spelling produces the same output.
diarize
Whether to enable speaker diarization (identifying who said what) by default. Default: false.
When enabled, providers that support diarization (OpenAI, Deepgram, Sarvam) will label each speaker in the transcript. You can also enable per-transcription with --diarize without changing this default.
Auto-routing: When
--diarizeis used (or this is set totrue) without an explicit--provider, anyscribe automatically switches to Deepgram if a Deepgram API key is configured. Deepgram handles large files natively and produces the most consistent speaker labels. Override with--provider openaiif needed.Automatic speaker detection: The number of speakers is detected automatically from the audio — you never need to specify how many speakers are in the recording. Deepgram analyzes voice characteristics (pitch, tone, cadence) to distinguish speakers.
Language tip: For mostly-English meetings, auto-detect works well. For Hindi or Hinglish (Hindi-English mix), add
--language hi-Latnfor romanized Latin script output. See Providers for the full language guide.When to enable: If you primarily transcribe meetings, interviews, or podcasts with multiple speakers. Leave off for single-speaker content like YouTube videos.
prompt_download
Whether to offer downloading the video/audio file after each transcription. Default: never.
| Value | Description |
|---|---|
never |
Don't ask — just transcribe (default) |
ask |
Ask after each transcription if you want the video/audio too |
always |
Always download the full video after transcription |
Tip: You can always download manually with
anyscribe download "<url>"regardless of this setting.
local_file_media
What to do with the original file when transcribing local audio/video files. Default: skip.
| Value | Description |
|---|---|
skip |
Leave the original file where it is (default) |
copy |
Copy to ~/.anyscribe/downloads/audio/local/ for organization |
move |
Move to the downloads directory (removes the original) |
ask |
Ask each time what to do |
Why skip by default? Unlike URL downloads where audio is temporary, local files already exist on your disk. Copying them wastes space unless you want everything organized in one place.
local_model
Which Whisper model the local provider uses when transcribing. Default: base.
| Value | Download | RAM | Quality |
|---|---|---|---|
tiny |
~75 MB | ~400 MB | lowest |
base (default) |
~145 MB | ~600 MB | good for most |
small |
~480 MB | ~1.2 GB | noticeably better |
medium |
~1.5 GB | ~2.5 GB | near-large for many languages |
large-v3 |
~3 GB | ~5 GB | highest |
large-v3-turbo |
~1.6 GB | ~3 GB | near large-v3, ~6x faster on CPU |
distil-large-v3.5 |
~1.5 GB | ~2.8 GB | near large-v3 for English; weaker on other languages |
Want better quality without the wait?
large-v3-turbois the sweet spot — close tolarge-v3accuracy at roughly six times the speed on a CPU, and half the download. Pickdistil-large-v3.5only if everything you transcribe is in English.
Change it with anyscribe config set local_model small or from the default-model dropdown inside the Local provider panel in the Web UI. You can only select a model that's been cached — pull others with anyscribe model pull <size>. A one-off override is available via ASCLI_LOCAL_MODEL=medium anyscribe "<url>" (ASCLI_ is the legacy env prefix, still honored).
Not set until setup. This field has no effect until you run
anyscribe local setup --model <size>(or the equivalent Web UI button). The field is still present inconfig.yamlwith the default value ofbase.
Instagram cookies (instagram.browser)
Tells anyscribe which browser to read Instagram cookies from. Cookies let anyscribe download reels that need a logged-in session — including private reels and reels that are getting rate-limited for anonymous users.
Most common values: firefox, chrome, safari. Also supported: brave,
edge, chromium, vivaldi, opera. Leave empty (the default) to skip
cookies — many public reels work fine without them.
anyscribe config set instagram.browser firefox
What anyscribe actually does: When you set this, anyscribe tells yt-dlp to read cookies from the browser's profile directory. yt-dlp handles the extraction using the browser's built-in decryption — your password is never asked for or stored.
Pre-0.8.3 upgrade note: Older versions of anyscribe asked for an Instagram username and password and stored the password in
~/.anyscribe/.env. Those are no longer used — you can safely remove theINSTAGRAM_PASSWORDline from your.envfile when convenient.
.env (API Keys and Secrets)
API keys and passwords are stored separately from config for security:
# ~/.anyscribe/.env
OPENAI_API_KEY=sk-proj-...
DEEPGRAM_API_KEY=...
# ELEVENLABS_API_KEY=xi-...
# OPENROUTER_API_KEY=sk-or-...
# SARGAM_API_KEY=...
# GROQ_API_KEY=gsk-...
Important: This file contains secrets. It's excluded from git by default. Never share it or commit it to a repository.
OPENROUTER_MODELno longer does anything. Older versions read that line to choose an OpenRouter model. Since 0.15.0 the model lives with every other model choice — runanyscribe config set provider_models.openrouter <slug>and delete theOPENROUTER_MODELline from.env.Pre-0.8.3 upgrade note: Older versions of anyscribe stored
INSTAGRAM_PASSWORDin this file. It's no longer used — you can safely remove theINSTAGRAM_PASSWORDline when convenient. Instagram downloads now use browser cookies instead (seeinstagram.browserbelow).
Changing your API key
The easiest way is to use anyscribe config set:
anyscribe config set openai_api_key sk-proj-...
anyscribe config set deepgram_api_key YOUR_KEY
anyscribe config set elevenlabs_api_key xi-...
anyscribe config set sargam_api_key YOUR_KEY
anyscribe config set openrouter_api_key sk-or-...
anyscribe config set groq_api_key gsk-...
These are stored in ~/.anyscribe/.env automatically.
Or re-run onboarding:
anyscribe onboard --force
This shows your current settings (API keys masked) and lets you change only what you need — no need to re-enter everything.
Or edit the file directly with any text editor — here's nano as an example:
nano ~/.anyscribe/.env
Workspace Structure
Your transcripts live in the workspace (pure markdown, no binaries). Downloaded files are stored separately in the app directory.
~/anyscribe/ # Obsidian vault (configurable)
├── .obsidian/ # Obsidian app config
├── _index.md # Master index — newest first
├── sources/
│ ├── youtube/ # YouTube transcripts
│ ├── instagram/ # Instagram transcripts
│ └── local/ # Local file transcripts
└── daily/YYYY-MM-DD.md # Daily processing log
~/.anyscribe/ # App internals (hidden)
├── downloads/ # Downloads (separate from vault)
│ ├── audio/<platform>/ # Audio files (if keep_media=true)
│ └── video/<platform>/ # Video files (anyscribe download)
├── sessions/ # Cached sessions (legacy; no longer used for Instagram)
└── logs/ # Processing logs
Why are downloads separate? Keeping binaries out of the Obsidian vault means the vault stays lightweight and fast — even with hundreds of transcripts.
workspace_path
Where to store your transcript workspace. Default: ~/anyscribe/ (when set to empty string or omitted).
Set a custom path to use an existing Obsidian vault or a different location:
anyscribe config set workspace_path ~/Documents/transcripts
Tip: Leave this empty to use the default
~/anyscribe/. The workspace is visible in Finder/file managers — no need to navigate to hidden folders.
How files are named
- File names: A "slug" of the video title — lowercase, hyphens instead of spaces, max 60 characters
- Collisions: If two videos have the same slug, the second gets
-2appended
Transcript frontmatter
Each markdown file has YAML properties at the top that Obsidian can search and filter:
---
source: https://youtube.com/watch?v=... # Original URL
platform: youtube # Where it came from
title: "Video Title" # Video title
duration: "12:34" # Length of the video
language: en # Detected language
provider: openai # Which API transcribed it
date_processed: 2026-03-26 # When you ran the transcription
word_count: 1500 # Total words in transcript
reading_time: "8 min" # Estimated reading time
tags: # For Obsidian tag filtering
- transcript
- youtube
tldr: "Video Title" # Quick summary
---
What you can change vs what's fixed
Most things you'd want to adjust are settings you can change anytime. A few things are fixed in the code — they're tuned defaults that keep transcription reliable, and changing them means editing anyscribe's source and reinstalling.
things you set (knobs) things baked in (constants)
┌──────────────────────────┐ ┌──────────────────────────────┐
│ config.yaml settings │ │ audio quality (16kHz/mono) │
│ .env API keys + secrets │ │ how big files get split up │
│ --flags on commands │ │ where app files live │
│ the Web UI settings page │ │ Web UI is localhost-only │
└──────────────────────────┘ └──────────────────────────────┘
change anytime, no restart changing these needs a code edit
You can change anytime (this whole page): your provider, the model that provider uses, language, output format, diarization, whether media is kept, your workspace location, the local model, and all your API keys.
Fixed in the code (and why):
| What's fixed | Current value | Why it's not a setting |
|---|---|---|
| Audio quality | 16 kHz, mono, 64 kbps mp3 | Tuned for the best transcription accuracy per megabyte. Higher quality wouldn't improve the text. |
| File-splitting limits | Split if over 25 MB or 30 min, into 18-min pieces | Driven by the transcription APIs' own upload and timeout limits, not your preference. |
| The list of models you can pick from | e.g. OpenAI offers gpt-transcribe, whisper-1, gpt-4o-transcribe, gpt-4o-mini-transcribe |
Each provider's list is curated to models anyscribe knows how to read. You choose freely within the list via provider_models or --model; new entries arrive with anyscribe releases (anyscribe update). OpenRouter is the exception — it forwards any model name, so you can add your own with extra_models.openrouter. |
| App folder location | ~/.anyscribe |
The fixed home for config, logs, and downloads. Your transcripts' location (workspace_path) is configurable. |
| Web UI address | 127.0.0.1 (your machine only) |
The Web UI has no password, so it only listens to your own computer. The port is changeable with anyscribe ui --port 9000. |
Want one of these to be a real setting? These are deliberate defaults, not oversights — see the developer note in docs/building/architecture.md for which ones are candidates to become configurable. If you have a concrete need (say, a custom audio bitrate), that's a reasonable feature request.
Resetting Everything
To start fresh, delete the app directory and re-run onboarding:
Warning: This deletes your config, API keys, and transcripts. Back up
~/anyscribe/first if you want to keep your transcripts. If you used a custom workspace path, back up that location instead.
rm -rf ~/.anyscribe ~/anyscribe
anyscribe onboard