mirror of
https://github.com/wiseguru/ReWrite-Voice-Notes.git
synced 2026-07-22 07:49:19 +00:00
big readme update.
This commit is contained in:
parent
f5aa5bba7c
commit
1ebc62219b
2 changed files with 99 additions and 50 deletions
|
|
@ -2,7 +2,8 @@
|
|||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(npm run *)",
|
||||
"WebSearch"
|
||||
"WebSearch",
|
||||
"WebFetch(domain:docs.obsidian.md)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
146
README.md
146
README.md
|
|
@ -2,26 +2,15 @@
|
|||
|
||||
An Obsidian plugin that captures speech (live recording or pasted transcript), runs it through a transcription provider, cleans and structures it with an LLM, and inserts the result into your vault.
|
||||
|
||||
You bring your own provider keys. Nothing is sent to a ReWrite server; the plugin only talks to the endpoints you configure.
|
||||
You bring your own provider keys. Nothing is sent to a ReWrite server; the plugin only talks to the endpoints you configure. It can also run entirely on-device: pair the plugin-managed whisper.cpp transcription with a local OpenAI-compatible LLM (Ollama or llama.cpp) and no audio or text ever leaves your machine.
|
||||
|
||||
## Features
|
||||
## Highlights
|
||||
|
||||
- Record audio directly in Obsidian, or paste a pre-existing transcript.
|
||||
- 8 transcription providers: OpenAI Whisper, OpenAI-compatible (whisper.cpp, faster-whisper-server, etc.), Groq, AssemblyAI, Deepgram, Rev.ai, Mistral Voxtral, and a plugin-managed local whisper.cpp server (desktop).
|
||||
- 5 LLM providers for cleanup: Anthropic Claude, OpenAI GPT, OpenAI-compatible (Ollama, LM Studio, plus cloud services like DeepSeek, Kimi, Qwen, GLM), Google Gemini, Mistral.
|
||||
- Desktop and Mobile profiles, auto-selected by environment with a manual override.
|
||||
- 7 starter templates (General cleanup, Todo list, Daily note, Meeting notes, Idea capture, Lecture, Podcast), stored as editable Markdown files in your vault and ordered by filename (prefix with `01-`, `02-`, etc. to reorder).
|
||||
- **Shared core**: a single vault Markdown file (`ReWrite/SharedCore.md`) holds the cleanup ground rules (don't act on the transcript, fix grammar/fillers, output only the result) that prefix every template, so you edit the baseline once. Trim it to save tokens, set `disableSharedCore: true` in a template's frontmatter to skip it there, or delete the file to turn it off entirely.
|
||||
- Quick Record command for one-shot capture with no modal: ribbon icon, command palette, or a custom hotkey.
|
||||
- Three insert modes: at the cursor, append to the active note, or create a new note with `{{date}}` / `{{time}}` filename templating. The modal's per-run Destination control overrides the template's mode, folder, and filename for a single run without editing the template.
|
||||
- **Process text with a template**: run any template over the current selection or whole note body, no audio needed, from the command palette or the editor right-click menu.
|
||||
- **Reprocess audio**: rerun the pipeline over an audio file already in your vault, from the command palette, the file-explorer right-click menu, or by placing the cursor inside an `![[audio]]` embed. Useful for retrying with a different template or provider, and for long-form content like lectures and podcasts (see [Long-form audio](#long-form-audio-lectures-podcasts)).
|
||||
- **Speaker identification (diarization)**: opt-in `Speaker A:` / `Speaker B:` labels for multi-speaker recordings, preserved through cleanup. Available with AssemblyAI, Deepgram, and Rev.ai.
|
||||
- **Saved recordings**: each recording is written to your attachments folder and linked back into the output with an `![[...]]` embed, so the original audio stays in your vault.
|
||||
- **Ad-hoc voice instructions**: speak your assistant's name followed by an instruction mid-recording (e.g. "Scrivener, turn this into a checklist") and the directive is extracted and added to the cleanup prompt for that run only. The trigger word is configurable.
|
||||
- **Assistant prompt**: a vault Markdown file defines the persona and standing instructions prefaced to the cleanup step, so you can shape tone and behavior without touching settings.
|
||||
- **Known nouns**: a vault Markdown file of proper nouns (with optional misheard variants) that the LLM preserves verbatim, fixing names the transcriber tends to mangle.
|
||||
- **API key encryption**: keys are stored in Obsidian's built-in secret storage (OS-encrypted; the default when available) or with a strength-checked passphrase using Argon2id/PBKDF2 AES-GCM (cross-platform fallback). There is no unencrypted option.
|
||||
- Record in Obsidian, or paste and reprocess existing audio, then clean and structure it with an LLM and insert it into your vault.
|
||||
- Bring-your-own keys across 8 transcription and 5 LLM providers, cloud or fully local; nothing goes to a ReWrite server.
|
||||
- 10 editable Markdown templates (general cleanup, todo, daily note, meeting, lecture, podcast, guides, book log, and more) plus a shared-core baseline you edit once.
|
||||
- Speaker diarization, saved-audio embeds, spoken ad-hoc instructions, known-nouns preservation, and per-run destination overrides.
|
||||
- API keys encrypted at rest (OS secret storage, or an Argon2id/PBKDF2 passphrase) on desktop and mobile.
|
||||
|
||||
## Tested providers
|
||||
|
||||
|
|
@ -74,13 +63,30 @@ Notes:
|
|||
endpoints instead, e.g. `https://api.moonshot.cn/v1` (Kimi) and
|
||||
`https://dashscope.aliyuncs.com/compatible-mode/v1` (Qwen).
|
||||
|
||||
## Using ReWrite
|
||||
|
||||
Once you have configured at least one transcription and one LLM provider (or just an LLM, for text-only flows), the day-to-day flow is:
|
||||
|
||||
- **Open the modal** with the ribbon mic icon, the "Open" command, or a hotkey you bind to it. Pick a template, then **Record** your voice, **Paste** an existing transcript, or pull text **From note**. The output is cleaned to the template's format and inserted at the cursor, appended to the current note, or written to a new note. When you record, the original audio is saved to your attachments folder and linked back into the result with an `![[...]]` embed.
|
||||
- **Quick Record** captures with no modal: ribbon, command palette, or hotkey. "Quick record (last used)" uses your last template; "Quick record (set template)" uses the one you pin in settings. Press again to stop.
|
||||
- **Process text with template** runs any template over the current selection (or the whole note if nothing is selected), no audio needed, from the command palette or the editor right-click menu.
|
||||
- **Reprocess audio** reruns the pipeline over an audio file already in your vault, from the command palette, the file-explorer right-click menu, or by placing the cursor inside an `![[audio]]` embed. Handy for retrying with a different template or provider.
|
||||
|
||||
Long-form audio (lectures, meetings, interviews, podcasts) uses the very same pipeline: drop the file anywhere in your vault and **Reprocess** it with the **Lecture** or **Podcast** template. For multi-hour recordings choose a provider with a high ceiling such as **AssemblyAI** or **Rev.ai** (OpenAI Whisper and Groq cap at 25 MB, Mistral Voxtral at 30 minutes), and turn on **Identify speakers** in the profile's transcription settings to get `Speaker A:` / `Speaker B:` labels preserved through cleanup. Only process audio you have the right to use; downloading third-party content (e.g. from YouTube) without permission may violate its terms or copyright.
|
||||
|
||||
## Install
|
||||
|
||||
### Manual install (current method)
|
||||
### Obsidian community plugins (recommended)
|
||||
|
||||
Until the plugin is in the community plugin directory, install manually:
|
||||
1. In Obsidian, open Settings, Community plugins, and turn off Restricted mode if it is on.
|
||||
2. Click Browse, search for "ReWrite (Voice Notes)", and click Install, then Enable.
|
||||
3. Open Settings, ReWrite (Voice Notes), enter at least one provider API key, and pick a model for both the transcription and LLM provider.
|
||||
|
||||
1. Build or download the release artifacts: `main.js`, `manifest.json`, `styles.css`.
|
||||
### Manual install (latest release)
|
||||
|
||||
If the plugin is not yet listed, or you want a specific build:
|
||||
|
||||
1. Download `main.js`, `manifest.json`, and `styles.css` from the latest entry on the GitHub Releases page.
|
||||
2. Create the folder `<YourVault>/.obsidian/plugins/rewrite-voice-notes/`.
|
||||
3. Copy the three files into that folder.
|
||||
4. In Obsidian, go to Settings, Community plugins, and enable "ReWrite (Voice Notes)". (Make sure Restricted mode is off.)
|
||||
|
|
@ -97,17 +103,80 @@ npm run build
|
|||
|
||||
`main.js`, `styles.css`, and `manifest.json` will be at the repo root. Copy them into your vault as described above.
|
||||
|
||||
## Local whisper.cpp server (desktop, optional)
|
||||
## Plugin map
|
||||
|
||||
### Commands
|
||||
|
||||
All commands are available from the command palette; most also have a UI entry point.
|
||||
|
||||
| Command | What it does |
|
||||
| --- | --- |
|
||||
| Open | Opens the main modal with your last-used template selected. Also the ribbon mic icon. |
|
||||
| Quick record (last used) | Starts recording immediately with a floating mini-UI, using the last-used template. Press again to stop. |
|
||||
| Quick record (set template) | Same one-shot capture, but always uses the template you pin in settings. |
|
||||
| Process text with template | Runs a template over the editor selection (or whole note). Also on the editor right-click menu ("ReWrite with template..."). |
|
||||
| Reprocess audio file with template | Reruns the pipeline over an audio file already in the vault. Also on the file-explorer and editor menus. |
|
||||
| Start whisper host / Stop whisper host | Starts or stops the local whisper.cpp server (desktop, when the active profile uses it). |
|
||||
|
||||
A status-bar item shows the local whisper.cpp server's live state on desktop when that provider is active.
|
||||
|
||||
### Vault files
|
||||
|
||||
The plugin keeps its editable configuration as Markdown files in your vault (defaults shown; all paths are configurable). Click **Populate** in settings to create them on first run.
|
||||
|
||||
| Path | Purpose |
|
||||
| --- | --- |
|
||||
| `ReWrite/Templates/` | One Markdown file per template (YAML frontmatter + a prompt body). Sorted by filename, so prefix with `01-`, `02-`, etc. to reorder. |
|
||||
| `ReWrite/SharedCore.md` | The cleanup ground rules prepended to every template prompt. Edit once to change the baseline; delete to turn it off. |
|
||||
| `ReWrite/AssistantPrompt.md` | The persona and standing instructions prefaced to the cleanup step. |
|
||||
| `ReWrite/KnownNouns.md` | Proper nouns the LLM should preserve verbatim, with optional misheard variants. |
|
||||
| `ReWrite/Template guide.md` | A human-facing explanation of the template format. Never sent to an LLM. |
|
||||
| `ReWrite/Template update report.md` | Written by the Update button when a shipped default has changed and needs your review. |
|
||||
| Attachments folder | Saved recordings (Obsidian's attachment location, or a folder you configure). Each is linked into the output via `![[...]]`. |
|
||||
|
||||
### Templates
|
||||
|
||||
The 10 bundled templates are starting points; they are just files, so edit, rename, reorder, or add your own. `newFile` templates can have the LLM fill in frontmatter properties and generate the filename from the content.
|
||||
|
||||
| Template | Behavior |
|
||||
| --- | --- |
|
||||
| General cleanup | Light prose polishing (grammar, fillers); inserts at the cursor. |
|
||||
| Todo list | Turns spoken items into a checklist. |
|
||||
| Daily note | New file named by date; fills Calendar / Goals / Tasks, then a Braindump of the full cleaned transcript. |
|
||||
| Meeting notes | New file; offers a context hint; sets subject / participants / date properties and a content-derived title. |
|
||||
| Meeting transcript | Like Meeting notes, but forces diarization on for speaker-labeled input. |
|
||||
| Idea capture | Quick capture of a single idea. |
|
||||
| Lecture | New file; restructures a talk into Summary / Key concepts / Definitions / etc.; subject / lecturer / course properties + title. |
|
||||
| Podcast | New file; tolerates diarized or flat input; podcast / episode / host / guests properties + title. |
|
||||
| Guides | New file; turns a walkthrough into strict two-level how-to steps; topic / tool properties + title. |
|
||||
| Book log | New file; short book-log body; title / author / series properties + content title. |
|
||||
|
||||
Diarization, when enabled on a capable provider, adds `Speaker X:` prefixes that the cleanup step preserves.
|
||||
|
||||
## Self Hosting
|
||||
|
||||
ReWrite can run with no cloud dependency by combining a local LLM for cleanup with the plugin-managed local whisper.cpp server for transcription.
|
||||
|
||||
### Local LLM (Ollama / llama.cpp)
|
||||
|
||||
Local LLM servers that speak the OpenAI `/chat/completions` dialect work through the **OpenAI-compatible** LLM provider. In a profile, set LLM provider to "OpenAI-compatible (cloud or local)", then fill in the base URL and model.
|
||||
|
||||
- **Ollama**: run `ollama serve` and `ollama pull <model>` (e.g. `llama3.1`). Base URL `http://localhost:11434/v1`, model = the pulled name. Ollama ignores the API key, so any non-empty placeholder is fine.
|
||||
- **llama.cpp**: run `llama-server -m <model.gguf>`. Base URL `http://localhost:8080/v1`, model = whatever name the server reports.
|
||||
|
||||
The base URL must include the version path (`/v1`); the adapter appends `/chat/completions` to whatever you enter. Pair this with the local whisper.cpp server below for a setup where nothing leaves your machine.
|
||||
|
||||
### Local whisper.cpp server (desktop, optional)
|
||||
|
||||
If you want fully on-device transcription with no network calls, the plugin can spawn a [whisper.cpp](https://github.com/ggerganov/whisper.cpp) `whisper-server` binary that you supply. The plugin only reads the absolute paths you configure; it never downloads binaries, never looks them up on PATH, and never spawns anything you did not explicitly point it at. Desktop only.
|
||||
|
||||
### Disclosure
|
||||
#### Disclosure
|
||||
|
||||
When you click Start in settings, the plugin launches whisper-server as a child process and communicates with it over loopback (`http://127.0.0.1:<port>`). The process is captured in a ring-buffered log you can view in settings. When you click Stop, or when the plugin is unloaded, the process is terminated. No code is downloaded or executed beyond the binary you provide.
|
||||
|
||||
**Network exposure**: whisper-server has no authentication and no TLS, so anyone who can reach its port can submit audio and exercise its native audio-decoding code. To keep it private, ReWrite always passes `--host 127.0.0.1` (loopback only) and **refuses to start** if you put a `--host` pointing at a non-loopback interface (such as `0.0.0.0` or a LAN IP) in Extra args. If you run whisper-server yourself from a terminal instead of letting the plugin manage it, bind it to `127.0.0.1` the same way; do not expose it to your network unless you have put your own authenticating proxy in front of it.
|
||||
|
||||
### Setup
|
||||
#### Setup
|
||||
|
||||
1. Obtain a `whisper-server` binary:
|
||||
- **Windows**: download the latest `whisper-bin-x64.zip` (CPU) or `whisper-cublas-12.4.0-bin-x64.zip` (NVIDIA GPU) from the [whisper.cpp releases page](https://github.com/ggerganov/whisper.cpp/releases), unzip somewhere stable (e.g. `C:\Tools\whisper.cpp\`), and use the path to `whisper-server.exe` inside that folder.
|
||||
|
|
@ -123,7 +192,7 @@ When you click Start in settings, the plugin launches whisper-server as a child
|
|||
4. Click Start. The status indicator transitions from Stopped to Starting to Running. View log shows whisper-server's stdout/stderr if startup fails.
|
||||
5. In the profile you want to use it from, set Transcription provider to "Local whisper.cpp (desktop only)". The Transcription model field is decorative for this provider; whisper-server uses whichever model file is loaded at startup.
|
||||
|
||||
### Building `whisper-server` on Linux
|
||||
#### Building `whisper-server` on Linux
|
||||
|
||||
whisper.cpp doesn't publish prebuilt Linux binaries, so you need to compile it once. The build is quick (under a minute on a modern laptop) and produces a single executable that you then point the plugin at.
|
||||
|
||||
|
|
@ -156,7 +225,7 @@ whisper.cpp doesn't publish prebuilt Linux binaries, so you need to compile it o
|
|||
|
||||
If `cmake --build` fails with `error: 'std::filesystem' has not been declared` or similar C++17 errors, your distro's default GCC is too old. Install a newer one (`sudo apt install g++-12` on Ubuntu) and rerun the `cmake -B build ...` step with `-DCMAKE_CXX_COMPILER=g++-12` appended.
|
||||
|
||||
### FUTO whisper-acft models
|
||||
#### FUTO whisper-acft models
|
||||
|
||||
[whisper-acft](https://github.com/futo-org/whisper-acft) is a set of Whisper checkpoints finetuned by FUTO so that whisper.cpp's encoder tolerates a dynamic `audio_ctx` (the number of audio frames the encoder processes). With stock Whisper models, lowering `audio_ctx` to match shorter clips makes the decoder unstable; the ACFT models were retrained to handle this gracefully, which can cut latency on short utterances substantially (often a 2x to 4x speedup on the small models, depending on hardware).
|
||||
|
||||
|
|
@ -196,7 +265,7 @@ The published checkpoints are quantized to `q8_0` and ship in the same GGML cont
|
|||
|
||||
If transcription quality drops noticeably (truncated sentences, missing trailing words), raise `-ac` toward 1500 until it stabilizes. The right value depends on how long your typical recording is; there is no single best number.
|
||||
|
||||
### Troubleshooting
|
||||
#### Troubleshooting
|
||||
|
||||
- **Port already in use**: another process is bound to the configured port. Change the port (or stop the other process). The plugin will not kill processes it did not start.
|
||||
- **Antivirus quarantine on Windows**: Windows Defender or third-party AV may flag `whisper-server.exe` on first run. The plugin cannot work around this; whitelist the binary in your AV settings.
|
||||
|
|
@ -205,26 +274,6 @@ If transcription quality drops noticeably (truncated sentences, missing trailing
|
|||
- **`unknown argument: -ac` (or `--audio-context`) in the log**: your `whisper-server` build predates the dynamic audio-context flag. Update to a current whisper.cpp release, or remove the `-ac` value from Extra args (you can still use the FUTO model files without the flag, you just lose the latency benefit).
|
||||
- **FUTO model loads but transcripts are truncated or jumbled**: `-ac` is set too low for the length of audio you are dictating. Raise it (e.g. `768` to `1024` to `1500`) until the output is stable.
|
||||
|
||||
## Long-form audio (lectures, podcasts)
|
||||
|
||||
ReWrite is not just for quick voice memos. The same pipeline cleans up and structures long recordings such as lectures, meetings, interviews, and podcasts. Nothing special is required: you process a long file the same way you reprocess any audio already in your vault.
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Get the audio file.** A mic recording you made, an export from a meeting tool (Zoom, Teams, Meet), a ripped CD, or any audio file you already have. For YouTube specifically, a third-party downloader such as [`yt-dlp`](https://github.com/yt-dlp/yt-dlp) can extract the audio track. **Make sure you have the right to the audio first**: downloading YouTube content without permission violates YouTube's Terms of Service and may infringe copyright. Only process audio you are allowed to.
|
||||
2. **Drop the file into your vault** anywhere (for example an `Attachments` or `Recordings` folder).
|
||||
3. **Reprocess it.** Right-click the file in the file explorer and choose **"Reprocess audio with template..."**. The same action is available from the command palette (**"Reprocess audio file with template"**) and from the editor menu when your cursor sits inside an `![[audio]]` embed.
|
||||
4. **Pick a template.** **Lecture** restructures a single-speaker talk into Summary / Key concepts / Definitions / Examples / Open questions / References. **Podcast** produces Summary / Speakers / Topics discussed / Notable quotes / References / Takeaways.
|
||||
5. **Choose a destination** if the template's default folder is wrong (the modal's Destination control isn't on the reprocess path, so set the folder/filename on the template itself, or move the note afterward).
|
||||
|
||||
### Duration and size caps
|
||||
|
||||
Very long recordings can exceed a provider's limits. The per-provider byte and duration ceilings live in [src/transcription/limits.ts](src/transcription/limits.ts). For multi-hour content, prefer **AssemblyAI** (up to 10 h) or **Rev.ai** (up to 17 h); OpenAI Whisper and Groq cap at 25 MB, and Mistral Voxtral at 30 minutes.
|
||||
|
||||
### Speaker labels (diarization)
|
||||
|
||||
For podcasts, meetings, and interviews, you can turn on **Identify speakers** in the transcription section of your profile settings. When enabled, the transcript comes back with `Speaker A:` / `Speaker B:` (or `Speaker 1:` / `Speaker 2:`) prefixes, and the cleanup step preserves them. This works **only** with **AssemblyAI**, **Deepgram**, and **Rev.ai**; the toggle is hidden for providers that cannot diarize (OpenAI Whisper, Groq, Mistral Voxtral, local whisper.cpp). Diarization quality varies: the speaker count is a guess and labels can drift mid-conversation. The Podcast template handles both labeled and unlabeled transcripts, so it works either way.
|
||||
|
||||
## Excluding `secrets.json.nosync` from sync
|
||||
|
||||
API keys are stored in `<YourVault>/.obsidian/plugins/rewrite-voice-notes/secrets.json.nosync`, separately from the rest of the plugin's settings.
|
||||
|
|
@ -310,7 +359,7 @@ secrets.json.nosync
|
|||
|
||||
Obsidian on iOS and Android runs in a constrained WebView. A few things behave differently from desktop:
|
||||
|
||||
- **iOS screen-off**: `MediaRecorder` silently stops capturing audio when the screen turns off on iOS. The plugin cannot prevent this; keep the screen on while recording, or use the Paste tab with an OS-level dictation keyboard.
|
||||
- **Screen-off during recording**: mobile WebViews suspend (and stop `MediaRecorder` capture) when the screen sleeps. To counter this, the plugin holds a screen wake lock for the duration of an active recording on both iOS and Android, so screen-off mid-recording is largely mitigated on supported OS versions. It is best-effort: on older WebViews, in an insecure context, or if the OS denies the request, it silently falls back to the old behavior, so keeping the screen on (or using the Paste tab with an OS-level dictation keyboard) is still the safe habit.
|
||||
- **Mobile encryption**: if your Obsidian version provides secret storage on mobile (1.11.4 or later), keys use it just like on desktop. Otherwise the plugin prompts you to set a passphrase before any key can be saved, and keys are then encrypted with Argon2id/PBKDF2 AES-GCM. The `secrets.json.nosync` file (which holds encrypted keys only in passphrase mode) uses the `.nosync` filename so iCloud Drive will skip it; for other sync tools, apply the exclusion rules above.
|
||||
- **Recording size limit**: each transcription provider enforces its own ceiling (OpenAI Whisper and Groq are the tightest at 25 MB; AssemblyAI, Deepgram, and Rev.ai allow gigabytes). These are provider-API limits, not Obsidian ones, and are most likely to bite on long mobile recordings with the 25 MB providers.
|
||||
|
||||
|
|
@ -318,7 +367,6 @@ Obsidian on iOS and Android runs in a constrained WebView. A few things behave d
|
|||
|
||||
- No audio playback or waveform display.
|
||||
- LLM responses are not streamed; you see the cleaned output once the whole response arrives.
|
||||
- No speaker diarization.
|
||||
- No long-audio chunking; clips that exceed the active provider's size or duration limit error out instead of being split.
|
||||
- The OpenAI-compatible transcription endpoint expects a server that mirrors Whisper's `/v1/audio/transcriptions` shape (whisper.cpp, faster-whisper-server). The OpenAI-compatible LLM endpoint expects a `/chat/completions` shape (Ollama, LM Studio, etc.).
|
||||
- Anthropic Claude calls go through Obsidian's `requestUrl`, which bypasses browser CORS. If you reuse the same endpoint from another tool that uses `fetch`, you will need their browser-direct-access header.
|
||||
|
|
|
|||
Loading…
Reference in a new issue