Skip to main content

Transcript Weaver

Transcript Weaver is a Python 3.10+ Unix-style pipeline for safely acquiring, transforming, and filing transcripts:

Installation

Install Transcript Weaver with all currently advertised functionality, including Otter support:

python3 -m pip install transcript-weaver

For local development from a repository checkout:

python3 -m pip install --editable .

Otter acquisition currently supports WSL on Windows and controls the user's existing Windows Chrome through Chrome DevTools integration. Browser automation is intentional: Otter currently reserves its supported public API for Enterprise workspaces. The Playwright Python dependency is installed with Transcript Weaver, but Weaver does not require Playwright to download or maintain a separate bundled browser. Windows Chrome, WSL-to-Windows connectivity, a dedicated Chrome profile, and one-time port-proxy setup are still required; see docs/otter.md for the rationale and setup instructions before attempting trwinp otter.

trwinp -> normalized JSON -> trweave -> enriched JSON -> trwout
trwinp otter | trweave franks-example | trwout franks-example

Standard output is reserved for JSON packets. Diagnostics and errors use standard error. Ordinary successful operation is silent except that trwinp and trweave emit their packet. trwout writes a file and emits no normal output.

Packet contract

trwinp emits schema version 1, the creating project version, and a canonical UTC recording time:

{
  "schema_version": 1,
  "trw_version": "1.0.0001",
  "run": {"id": "20260805-120000-a1b2"},
  "datetime": "2026-08-05T08:30:00Z",
  "source": {"type": "otter", "name": "Morning note", "reference": "https://otter.ai/u/example"},
  "transcript": "Speaker 1 10:00 : Um, I am grateful this moring Transcribe by https://otter.ai",
  "metadata": {"duration_seconds": 180.0}
}

trweave deeply verifies that all those fields remain unchanged and permits the provider to add fields. A valid result includes:

{
  "schema_version": 1,
  "trw_version": "1.0.0001",
  "run": {"id": "20260805-120000-a1b2"},
  "datetime": "2026-08-05T08:30:00Z",
  "source": {"type": "otter", "name": "Morning note", "reference": "https://otter.ai/u/example"},
  "transcript": "Speaker 1 10:00 : Um, I am grateful this moring Transcribe by https://otter.ai",
  "metadata": {"duration_seconds": 180.0},
  "weave": {"type": "gratitude", "update_transcript": "- I am grateful for this morning."}
}

The same valid run.id survives every stage. A missing ID is generated by any stage, and a malformed ID is rejected. The trw_version field is informational bug-report metadata, not a compatibility gate: downstream stages preserve it when present but accept packets created by any version, including legacy packets without the field. When Otter exposes a reliable media duration, trwinp records it as metadata.duration_seconds. Franks Example deterministically routes values greater than 300 seconds to unknown; exactly 300 seconds remains content-classified.

Configuration

On first use, the packaged schema-v1 configuration and prototype-derived prompts/example.md are copied atomically to the platform's per-user configuration directory. Existing files are never merged, migrated, repaired, or overwritten. Tests always inject disposable paths.

Older configuration files are not automatically migrated. If you want to replace an early prototype configuration with the complete example, first back it up and then run a command so Transcript Weaver can create the new defaults:

mv ~/.config/transcript-weaver/config.json ~/.config/transcript-weaver/config.json.backup
printf 'configuration check' | trwinp stdin > /tmp/transcript-weaver-packet.json

Alternatively, add the fields named by the validation error to your existing file. The program will never overwrite your real-vault settings.

A coherent configuration looks like this:

{
  "schema_version": 1,
  "logging": {"retained_runs": 5},
  "providers": {
    "gemini": {
      "model": "gemini-3.5-flash-lite",
      "credential": {"source": "pass", "name": "api/gemini"}
    }
  },
  "weave": {
    "franks-example": {
      "provider": "gemini",
      "prompt_file": "prompts/example.md"
    }
  },
  "out": {
    "franks-example": {
      "timezone": "America/Los_Angeles",
      "vault": {
        "path": "transcript-weaver-test-output",
        "relative_to": "cwd"
      },
      "packet_fields": {
        "category": "weave.type",
        "content": "weave.update_transcript"
      },
      "destination_roots": {
        "journals": "SubDir1/SubDir2"
      },
      "destinations": {
        "gratitude": {
          "operation": "insert",
          "root": "journals",
          "file": "Gratitude Journal.md",
          "format": "## {date}\n\n{content}\n\n"
        },
        "dream": {
          "operation": "insert",
          "root": "journals",
          "file": "Dream Journal.md",
          "format": "## {date}\n\n{content}\n\n"
        },
        "ses": {
          "operation": "insert",
          "root": "journals",
          "file": "SEs Journal.md",
          "format": "## {date}\n\n{content}\n\n"
        },
        "sacred": {
          "operation": "insert",
          "root": "journals",
          "file": "Sacred Journey.md",
          "format": "## {date}\n\n{content}\n\n"
        },
        "unknown": {
          "operation": "create",
          "directory": "00 Inbox",
          "filename": "unknown-{date}-{time}.md",
          "format": "## {date}\n\n{content}\n\n"
        }
      }
    }
  }
}

Provider, weave, output, and destination names are matched case-insensitively. Names differing only by case are rejected.

Path objects use path plus relative_to: "cwd" or relative_to: "config" for relative paths. For an absolute path such as /mnt/d/Notes or a home-relative path such as ~/Obsidian/Notes, omit relative_to. Existing path strings remain supported for compatibility. Keys beginning with _comment are embedded documentation and are ignored; other unexpected keys are rejected.

Each output profile’s vault is the common root for all its destinations. An optional destination_roots object defines reusable relative paths beneath the resolved vault. A destination selects a root with its explicit root field; root names are matched case-insensitively, and names differing only by case are rejected. Unknown root names produce an error listing the available roots. Placeholder forms such as {journals} are not supported.

Resolution with a selected root is:

vault + destination root + destination file/directory

When root is omitted, the backward-compatible resolution is:

vault + destination file/directory

Destination roots, files, and directories must be relative. They cannot escape the resolved vault with .. or by resolving through a link to a location outside it. In the example, the four journals are under vault/SubDir1/SubDir2; the unrooted unknown destination remains under the vault-level 00 Inbox.

Weaving

Need an LLM API but do not have one yet? See Free and Low-Cost LLM APIs for general information about free tiers, low-cost gateways, and important trade-offs. Transcript Weaver does not currently support every provider discussed there.

trweave PROMPT_OR_PROFILE first treats its argument as a path, resolving a relative path from the current working directory. A readable UTF-8 regular file supplies the complete prompt and uses the configured Gemini provider. Otherwise, the argument is resolved as a weave profile. No extension guessing or file searching occurs.

Gemini credentials are read from pass; secrets never belong in configuration. The implementation uses Gemini's REST API directly, requests JSON, and retries transient network errors and HTTP 429/5xx responses up to four times, waiting 1, 4, 9, and 16 seconds. Every retry is reported on standard error and is also written to the persistent run log when --log is enabled. Every input field is immutable. If the provider replaces transcript, Weaver preserves the original and uses that attempted replacement only when needed to populate weave.update_transcript; no duplicate top-level transformed-text field is emitted. Other deleted or modified input fields remain errors. Fenced, explanatory, partial, non-object, or invalid weave responses are rejected.

Output

trwout OUTPUT_PROFILE extracts category and content through the configured dotted packet fields. It converts the packet's UTC datetime to the profile's IANA timezone without modifying the packet. {date}, {time}, and {content} are the only formatting placeholders.

  • insert atomically places date-only headings in ascending local-date order.
  • Multiple entries on the same local date are retained in arrival order, separated by ---, and a warning identifying the date is written to standard error.
  • append atomically appends the configured rendered text.
  • create creates a standalone file atomically and refuses to overwrite one.

The example stores Dream Journal.md, Gratitude Journal.md, SEs Journal.md, and Sacred Journey.md beneath the configured vault-relative journal root. Unknown material is routed to the vault-relative 00 Inbox directory as unknown-{date}-{time}.md. The packaged prompt asks for approximately 72-character word-boundary wrapping while keeping long-form unknown content substantially verbatim.

Logging and privacy

All commands accept --log, --verbose, and --debug-artifacts. Logs are optional, grouped by run ID, and retained according to logging.retained_runs. They may contain stage, profile, model, operation, relative destination, timing, and sanitized failure information. Ordinary logs never contain transcripts, prompts, transformed content, provider bodies, credentials, or complete journals.

If a provider changes or deletes an immutable packet field, trweave writes the complete original and provider JSON documents under <log-directory>/packet-failures/. These files are intentionally sufficient for a manual diff and therefore may contain complete transcripts and other private packet data. Inspect them before sharing. They are grouped by run ID and bounded by logging.retained_runs; the current failure is always retained. Debug artifacts are also potentially sensitive.

Project version and distribution builds

src/transcript_weaver/_version.py is the single source of truth for the project version used by package metadata, transcript_weaver.__version__, and the packet field trw_version. The public format is major.minor.build, with a four-digit build component. Python packaging canonicalizes numeric release components, so application version 1.0.0001 appears in wheel/sdist filenames and Core Metadata as the PEP 440-equivalent 1.0.1; the packaged _version.py and emitted packets retain 1.0.0001.

Create distributions with:

python -m transcript_weaver.build

That intentional command takes an exclusive build lock, increments the build component once, atomically updates the source version, and builds both distributions. It restores the previous source version if the build fails. Imports, tests, installs, and ordinary packaging metadata inspection do not increment the version. A stale lock must be investigated and removed manually after confirming no build is active.

Development and tests

pytest -m 'not live_otter and not live_gemini'
ruff check .
ruff format --check .
mypy
python -m transcript_weaver.build

The default suite is offline and uses fake providers and miniature temporary vaults. Live Otter and Gemini checks are opt-in. After all offline checks pass:

TRANSCRIPT_WEAVER_LIVE_GEMINI=1 pytest --no-cov -m live_gemini tests/test_live_gemini.py

The live Otter functional test uses the configured WSL/Windows Chrome session:

TRANSCRIPT_WEAVER_LIVE_OTTER=1 pytest --no-cov -m live_otter tests/test_live_otter.py

That command reads pass api/gemini and sends only the harmless test transcript to Gemini. It does not access an Obsidian vault or Otter.

License

Copyright © 2026 Frank Merrow.

Transcript Weaver is free software licensed under the GNU General Public License, version 3 or later. See the LICENSE file for the complete terms.

Metadata

Release files for transcript-weaver 1.0.11

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for transcript-weaver 1.0.11
File Size Uploaded
transcript_weaver-1.0.11.tar.gz 68.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for transcript-weaver 1.0.11
File Interpreter ABI Platform
transcript_weaver-1.0.11-py3-none-any.whl Python 3 none any Details

Total release size: 124.6 kB

Release files / transcript_weaver-1.0.11.tar.gz

Download URL transcript_weaver-1.0.11.tar.gz
Size 68.0 kB
Tags Source
SHA-256 checksum
How to use checksums
30b63c6ad47d581eb88cc1f5b7490136a1ba5e97dfd9f8da6e30315209969e43
BLAKE2b-256 checksum
How to use checksums
b2e662db3adb65959d4af9ef9e357ca575b958ef359d57c452bdfce67f01227d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.12

Release files / transcript_weaver-1.0.11-py3-none-any.whl

Download URL transcript_weaver-1.0.11-py3-none-any.whl
Size 56.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a6701cc45d0cead2ebbdfaa1eafe173d098ebdf080f6d4a2f5adb20dc477a426
BLAKE2b-256 checksum
How to use checksums
27a0e8629a7b9e2338a59dd07e0665ad23ea98b48a1dc656f07a1d2125d2b0f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.12

Release history Release notifications | RSS feed

This release

1.0.11 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page