Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Caching

Status: Current Last updated: 2026-09-15 17:23 EDT

What gets cached

Batchalign caches only audio-task results:

AnalysisCached?
Forced alignment word timings (align)Yes
ASR results for utterance timing recovery (align’s UTR pre-pass)Yes
Dedicated speaker evidence (transcribe --diarization enabled or standalone diarize)Yes
Media conversion (.mp4/.m4a.wav)Yes
Raw Rev.AI transcript evidence (transcribe, benchmark, Rev-backed align UTR)Yes
Other ordinary ASR output (transcribe)No
Morphosyntax (morphotag)No: always recomputed
Utterance segmentation (utseg)No: always recomputed
Translation (translate)No: always recomputed
Coreference (coref)No: always recomputed
OpenSMILE features (opensmile)No
AVQI scores (avqi)No

The text-NLP cache that previously covered morphotag, utseg, and translate was removed after a benchmark on a 15,748-file corpus showed it was about 25× slower than just re-inferring (6-16% hit rate; 2,500 ms SQLite lookup beat ~100 ms inference savings). See the architecture page on Caching for the detailed reasoning.

In practice: a re-run of morphotag on the same corpus takes the same time as the first run. A re-run of align on the same audio is much faster. A repeat transcribe --diarization enabled run with the same speaker settings reuses the exact normalized speaker turns that the first run consumed, instead of calling the diarization backend again. BA3 also retains backend-shaped evidence separately, so a changed local normalization algorithm can derive new turns without repeating inference.

For Rev.AI transcription, BA3 reads the transcript endpoint as bytes, requires strict UTF-8 JSON, and stores that exact application response before converting its monologues and elements to BA3 tokens. It does not use lossy or encoding-normalizing text decoding. Unknown provider fields are retained for future projections. A warm run therefore avoids both Rev submission and polling, and later post-processing experiments can replay the same provider transcript evidence locally.

Dedicated speaker evidence

The speaker cache applies to the dedicated diarization stage of transcribe and to standalone diarize, for all three speaker engines (pyannote-ai, pyannote, and nemo). It is especially useful with the paid pyannoteAI service.

The key includes:

  • a BLAKE3 digest of the full media-source bytes;
  • the canonical audio-preparation recipe revision;
  • the selected speaker backend;
  • the expected speaker count;
  • the speaker-model revision; and
  • the stored evidence schema version.

Paths and modification times are deliberately excluded. Renaming or copying an unchanged recording therefore reuses its speaker evidence. Re-encoding the recording changes its bytes and causes a miss even if it sounds identical.

BA3 stores two different artifacts:

  1. Raw inference evidence. For pyannoteAI this is the completed provider job ID, complete output object, and optional warning. Local Pyannote and NeMo retain their backend-specific segment evidence.
  2. Derived speaker segments. These are the sorted millisecond intervals consumed by transcript speaker projection. Their identity includes both the raw-evidence fingerprint and a separate normalization-algorithm revision.

Changing only BA3’s normalization algorithm invalidates the second artifact, not the first. BA3 re-normalizes the retained provider response locally and does not upload audio or submit another paid pyannoteAI job. Changing the model, speaker count, backend, audio bytes, or preparation recipe changes the raw identity and therefore requires inference.

BA3 validates schema versions, fingerprints, backend provenance, provider job identity, speaker labels, interval direction, and ordering. A missing raw entry permits inference; a corrupt raw or derived entry fails the file instead of being treated as a miss and silently causing another billable call. Concurrent identical requests in one BA3 server are serialized: the first miss performs and commits inference, while followers wait and then replay the result.

BA3 also rereads the source after a speaker-cache miss and verifies that its bytes still match the digest used for the cache decision. Speaker inference is prepared from that verified in-memory copy. If another process replaces the media between lookup and inference, the file fails instead of running a paid job under the wrong cache identity.

Raw Rev.AI transcript evidence

Normal transcribe, benchmark, and Rev-backed align UTR runs check durable raw Rev evidence before submitting anything to Rev. Only a missing entry, or an explicit --override-media-cache, authorizes submission. Corrupt evidence fails closed without a service call, and concurrent identical requests are coalesced. Concurrent identical forced refreshes also share the first fresh commit rather than each issuing a sequential paid call.

The key includes the full bytes of the provider-visible inference media, media preparation recipe, normalized upload filename, multipart MIME type, requested language, expected speaker count, Rev request-policy revision, provider/model alias, and request-identity revision. The stored envelope contains the resolved language plus the exact admitted transcript response JSON bytes. It does not store credentials or temporary job IDs.

Before a paid call, BA3 rereads the prepared source and verifies that the exact bytes still have the digest used for the cache decision. If the file changed between preparation and submission, the run fails instead of uploading different bytes under the old key. The authorization is then consumed into one evidence-inference run plus a separate commit permit; the inference capability cannot be cloned into repeated runs. An auto-language run intentionally contains both Rev language identification and transcription requests.

Request-identity revision 2 names this stronger provider presentation. Entries from revision 1 do not satisfy the new keys. Storage schema 3 adds exact JSON retention without changing the revision-2 request key: schema-2 entries remain replayable and are explicitly traced as legacy_typed_projection, while new provider responses are traced as exact_provider_json. Replay-only mode never turns either storage migration into a paid call.

For controlled Rev transcribe and Rev-backed align experiments, --debug-dir PATH additionally writes versioned *_rev_evidence.json causal sidecars. Each records the keyed media and multipart presentation, request identity, replayed versus fresh-miss outcome, raw evidence key, transcript fidelity, and deterministic projection revision without exposing the credential or local source path.

Dedicated-speaker transcribe runs likewise write *_speaker_evidence.json. This joins the source digest, request/model semantics, raw and derived cache identities, cache outcome, normalization revision, segment-projection revision, segment count, and a versioned digest of the exact normalized timing/label projection. The companion .turns.json holds those normalized segments in the canonical review format.

BA3’s regression suite exercises this at the complete Rust transcribe-pipeline boundary, not only at the cache row. It closes and reopens SQLite, replays the same retained Rev response, and requires identical final CHAT plus identical ASR-response debug output with no second inference call. The Rev causal sidecars intentionally differ in exactly one meaning: the cold run records a fresh missing-key inference and the warm run records replay. Their media, request, retained-evidence, and projection identities must remain equal.

The old batch pre-submission shortcut has been removed because it submitted paid jobs before a cache hit could be known. Cold misses currently fan out through BA3’s normal per-file worker limit. Reintroducing wider parallel submission is a performance follow-up; it must consume the same typed miss authorization and cannot restore the old unguarded optional-job-ID path.

Other ASR engines remain uncached in ordinary transcribe runs. Align’s UTR ASR also keeps its older normalized-result cache. If that derived entry is missing, Rev-backed UTR can re-project the durable raw transcript without a service call. A corrupt normalized UTR entry fails closed instead of silently falling through to inference. The legacy Rev pre-submission path no longer exists.

How to guarantee cache-backed stages do not infer

Use --require-media-cache for replay-only experiments:

batchalign3 --require-media-cache transcribe recordings/ -o output/ \
  --asr-engine rev --diarization enabled

batchalign3 --require-media-cache align corpus/ -o output/

For every cache-backed stage reached by the command, a reusable hit is required. Missing raw Rev or speaker evidence fails the file before an inference authorization can be constructed, so the miss cannot become a Rev or pyannoteAI call. Forced alignment likewise refuses to send missing groups to its worker. Existing clean %wor evidence can still satisfy an FA group.

Raw and derived evidence remain separate. If normalized speaker turns are missing but the backend-shaped speaker response exists, BA3 derives and stores new turns locally. Rev-backed UTR can similarly rebuild its normalized UTR entry from retained raw Rev evidence; if the raw entry is also missing, the raw-evidence gate refuses the provider call.

Forced alignment also keeps raw and derived layers. On a normal hit, BA3 prefers the admitted worker response and reruns the current local timing projection; an admitted versioned derived envelope is the fallback when raw evidence is absent or refused. Both envelopes prove the requested engine, selected-worker version, semantic group key, and word cardinality. Historical bare timing vectors are refused and treated as misses because they cannot prove whether the result came from the requested engine or an unversioned fallback. This means experiments with Rust-side timing interpretation can reuse identified direct model work automatically.

A live Wave2Vec-to-Whisper fallback is intentionally not cached today. It is valid for the current output and is recorded in the debug trace, but the Wave request’s version namespace does not identify the effective Whisper model. Persisting that response would make later replay ambiguous, so a future run repeats the fallback. --override-media-cache and --override-media-cache-tasks forced_alignment bypass both FA layers and therefore request fresh model inference.

When a current build first opens an older cache, it also removes from live lookup any legacy raw FA row whose requested engine contradicts the model family in its stored namespace. Those rows did not retain an exact producer version and cannot be safely reused or relabeled. Their exact stored bytes are retained in the database’s cache_quarantine table for audit. This cleanup can turn an apparent historical hit into an honest miss; --require-media-cache still refuses that miss without running inference. batchalign3 cache stats reports the quarantine total and its stable reason counts separately from reusable entries.

This flag is not a general offline, no-network, or zero-compute mode. Ordinary non-Rev ASR output is not cached, so Whisper, Tencent, Aliyun, FunAudio, or Qwen transcription can still run its configured inference path, including a network service where that backend uses one. OpenSMILE and AVQI are outside the analysis cache. The guarantee is specifically that a missing entry at a cache-backed boundary cannot authorize inference.

--require-media-cache is mutually exclusive with --override-media-cache and --override-media-cache-tasks: one run cannot both require existing evidence and request fresh evidence.

What invalidates the cache

What changedWhat re-runsWhat stays cached
Edited the transcript wordsFA (per-group cache key includes text)UTR ASR (only depends on audio)
Re-recorded or replaced the audioFA, UTR ASR, Rev evidence, speaker evidence(n/a, audio is the cache key)
Changed the language codeUTR ASR and Rev evidence(other corpora’s entries)
Changed expected speaker countRev evidence and speaker evidenceFA and UTR ASR
Changed speaker backendSpeaker evidenceFA, UTR ASR, and Rev evidence
Changed only the speaker normalization algorithmDerived speaker segmentsRaw speaker inference evidence
Upgraded batchalign or an identified model revisionAffected audio evidenceEntries from unchanged engines/models

Cache keys hash the inputs relevant to each task. FA and UTR use the legacy path/mtime/size AudioIdentity; Rev and speaker evidence use a true digest of the inference-media bytes. Rev also keys provider-visible presentation, so copies and renames share results only when their normalized upload extensions match. Engine or model revision strings are stored alongside each entry.

pyannoteAI currently exposes the precision-2 model alias, but not an immutable backend build hash. BA3 scopes cloud evidence to that alias and its own evidence schema. If the provider changes the implementation behind the same alias and you want fresh evidence, use --override-media-cache. The local Pyannote and NeMo identifiers likewise include their configured model identity and the BA3 package version; floating external model revisions remain a reason to force a refresh during controlled experiments.

How to force fresh results

Use the --override-media-cache global flag:

batchalign3 --override-media-cache align corpus/ -o output/

# Force and store fresh Rev and dedicated speaker evidence. This may incur charges.
batchalign3 --override-media-cache transcribe recordings/ -o output/ \
  --diarization enabled

This skips all applicable cache lookups, forcing fresh inference. New results replace the matching entries and are stored for future runs. With Rev ASR or --speaker-engine pyannote-ai, this can make new paid service calls even when reusable evidence exists.

The narrower --override-media-cache-tasks flag accepts forced_alignment, utr_asr, rev_asr_evidence, and speaker_diarization_raw_evidence. This permits a controlled transcribe run to refresh Rev while replaying speaker evidence, or the reverse, instead of repeating both paid boundaries.

Use this when you suspect cached results are wrong, or after manually updating model files outside of a normal batchalign upgrade.

UTR ASR results after an upgrade

UTR ASR results are stored under a namespace naming the timing-recovery engine AND the models it ran, for example utr-asr-v1:whisper_utr:whisper|asr=openai/whisper-large-v3@06f233fe.... Earlier builds stored them under the forced-alignment engine’s version instead, and then under the recovery engine’s name alone. The first align run on this build therefore misses those older UTR ASR entries once, recomputes them, and stores them under the new namespace; later runs hit as before. Forced-alignment entries are unaffected, because their namespace did not change: it is still exactly the forced-alignment engine name the worker reports.

Naming the models is what makes an upgrade safe rather than merely noticed. Upgrading a recovery model now lands in a different namespace, so results produced by the previous weights are never reused for the new ones. Nothing reads the older rows: a namespace move makes them unreachable by construction, so there is no compatibility path to keep true.

This costs one recompute, not two. The namespace already moved once in this release, and the model identity was folded into that same move deliberately.

With --require-media-cache, that one recompute is refused like any other miss for Whisper and Tencent recovery. Rev recovery can still rebuild the entry from retained raw Rev evidence without a new provider call.

Where the caches are stored

CachemacOS defaultLinux default
Analysis cache DB~/Library/Caches/batchalign3/cache.db~/.cache/batchalign3/cache.db
Media conversion cache~/Library/Application Support/batchalign3/media_cache/~/.local/share/batchalign3/media_cache/

The analysis cache is a single SQLite database file. The media cache stores converted WAV artifacts for inputs such as .mp4 and .m4a.

For isolated runs or testing, you can relocate them with environment variables:

export BATCHALIGN_ANALYSIS_CACHE_DIR=/tmp/ba-analysis-cache
export BATCHALIGN_MEDIA_CACHE_DIR=/tmp/ba-media-cache

BATCHALIGN3_ANALYSIS_CACHE_DIR is accepted as an alias for the analysis cache setting. If both spellings are set, the canonical BATCHALIGN_ANALYSIS_CACHE_DIR value wins. Set the variable before starting a server: a client process cannot relocate the cache owned by an already-running server.

How to clear the cache

Use the built-in cache command:

batchalign3 cache stats          # See cache size and entry count
batchalign3 cache clear --yes    # Clear the cache

cache stats and cache clear operate on both the analysis cache and the media conversion cache.

Or delete the cache.db file and/or the media-cache directory directly.

To selectively refresh without clearing everything, use --override-media-cache on specific runs instead, old entries for other corpora remain available.

Old text-NLP cache entries

If you used batchalign before the text-NLP cache was removed, your cache.db may still contain old morphosyntax_v*, utseg_v*, and translate_v* rows. Those are dead weight, they’re never read anymore. Run batchalign3 cache clear --yes (or rm -f ~/Library/Caches/batchalign3/cache.db*) to reclaim the disk space.


This page last changed: 2026-09-16 (commit 197c81e6). The whole book last changed: 2026-09-16 (commit 34d249d8).