Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,11 @@ examples/exp*
.claude/
*.wav
*.jsonl
/audiobook_outputs/
/audiobook-artifacts/
/outputs/audiobook/
/preview.json
/chunk-*.json
/audiobook_plan.json
/checkpoint.json
/qc_report.json
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Changelog

## Unreleased

- Add local DOCX audiobook planning and JSON output.
- Add consent-gated OpenRouter chunk structuring.
- Add OpenRouter result merge and generation checkpoint workflow.
- Add FFmpeg concat/remastering helpers with non-overwrite safeguards.
- Add audiobook QC reporting and CLI gate behavior.
- Add SpecOps governance and eval scenarios for PR 184.
44 changes: 44 additions & 0 deletions PROJECT_MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Project Memory

## API Project Vault Decision Record

Date: 2026-06-11

The next planned audiobook feature is a local-first API and project vault. It
adds a dedicated frontend page for provider API configuration, SQLite-backed
project preservation, token/cost accounting, audio asset indexing, checkpoints,
and backup/restore.

## Durable Decisions

- API keys may be entered through the frontend, but must not be displayed after
save.
- SQLite is the project source of truth, but must not store provider keys in
plaintext.
- Browser code must not call OpenRouter directly. Provider operations must go
through a loopback-only local backend that injects credentials outside the
browser.
- Audio files stay on disk; SQLite stores metadata, hashes, paths, and lineage.
- Backups must preserve project state and generated assets, but exclude secrets,
authorization headers, raw provider requests, and raw provider responses by
default.
- Restore must defend against zip-slip, path traversal, symlink overwrite,
malformed schemas, and unconfirmed replacement.
- Token and cost data must distinguish estimates from provider-reported actuals.
- Live OpenRouter testing remains opt-in, approval-gated, and fixture-only.

## Open Implementation Questions

- Which frontend runtime will host the page.
- Which local secret-store mechanism is available on the target platform.
- Whether SQLite should live in the Python backend, desktop shell, or a local
service boundary.
- Whether backup archives should copy source DOCX files or store references by
default.

## Acceptance Criteria

- Future implementation work must preserve all durable decisions unless a later
explicit decision record supersedes them.
- Private manuscripts, generated audio, provider payloads, and secrets must not
enter version control.
30 changes: 30 additions & 0 deletions docs/audiobook/KB_INDEX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# OmniVoice Audiobook Knowledge Base

This knowledge base governs the DOCX-to-audiobook workflow for OmniVoice.

## Selected Baseline

Selected implementation baseline: **Alternative A - Offline Deterministic Local**.

Reason: the current OmniVoice distribution is explicitly hardened for local use:
offline Hugging Face/Transformers defaults, no Gradio share, localhost binding, and
no automatic model download. The first production path must preserve that contract.

## Alternatives

| Alternative | Network | Strength | Risk |
| --- | --- | --- | --- |
| A. Offline deterministic local | None | Maximum privacy and repeatability | Less semantic cleanup |
| B. Offline local LLM optional | None after local model is present | Better structure for messy fiction | Must prove model/cache is local |
| C. OpenRouter structured processing | Explicit external API | Better semantic structuring and tool calling | Sends approved chunks to provider |

## Files

- `offline-security-model.md`: how offline mode is proven.
- `docx-ingestion.md`: DOCX extraction and chapter detection rules.
- `audiobook-json-schema.md`: audiobook plan contract.
- `audiobook-standards.md`: pacing, pauses, segment, and QC standards.
- `technical-books-profile.md`: defaults for technical books.
- `fiction-profile.md`: defaults for novels and dialogue-heavy books.
- `qc-mastering.md`: audio handoff and quality gates.
- `openrouter-structured-processing.md`: opt-in external provider path.
54 changes: 54 additions & 0 deletions docs/audiobook/audiobook-json-schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Audiobook JSON Contract

The audiobook plan is the stable handoff between DOCX ingestion, narration
generation, cache, assembly, and QC.

## Top-Level Shape

```json
{
"project": {
"title": "string",
"author": "string",
"language": "pt-BR",
"genre": "technical",
"source_docx_hash": "sha256",
"created_at": "ISO-8601"
},
"voice_profile": {
"mode": "design",
"default_voice": "narrator",
"speed": 0.92,
"style": "technical_clear",
"pronunciation_notes": []
},
"chapters": [],
"qc_targets": {},
"settings": {}
}
```

## Segment Shape

```json
{
"id": "seg_001_000001",
"text": "Narration text.",
"text_hash": "sha256",
"speaker": "narrator",
"pause_after_ms": 750,
"speed": 0.92,
"tone": "neutral",
"chapter_id": "ch_001",
"status": "pending",
"source_paragraph_index": null
}
```

## Rules

- Segment IDs must be deterministic by chapter and order.
- `text_hash` is SHA-256 of the segment text.
- `source_docx_hash` is SHA-256 of the original DOCX bytes.
- Provider-specific metadata belongs under `settings`, never inside raw text.
- Real manuscripts and generated audio stay out of Git.
36 changes: 36 additions & 0 deletions docs/audiobook/audiobook-standards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Audiobook Standards

These defaults are internal production standards for OmniVoice audiobook tooling.

## Segmentation

- Target segment size: 120 to 900 characters.
- Split by sentence first, then punctuation if a sentence is too long.
- Preserve author meaning and quoted text.
- Do not remove technical terms, legal text, or dialogue markers without approval.

## Pacing

| Context | Target WPM | Notes |
| --- | ---: | --- |
| Technical book | 135-155 | More pauses around lists, code, formulas, definitions |
| Fiction | 145-170 | More variation for dialogue and scene changes |

## Pauses

| Boundary | Default |
| --- | ---: |
| Comma | 220-300 ms |
| Sentence | 520-750 ms |
| Ellipsis | 800-1100 ms |
| Paragraph | 950-1400 ms |
| Chapter | 1800-2500 ms |

## QC Targets

- Sample rate target: 44100 Hz unless model output requires another rate.
- Peak target: no samples above -3 dBFS after mastering.
- Initial loudness target: -20 LUFS with 2 LU tolerance.
- No zero-byte audio files.
- No missing chunks.
- No hidden clipping or failed joins.
28 changes: 28 additions & 0 deletions docs/audiobook/docx-ingestion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# DOCX Ingestion

The local ingestion path reads `.docx` files with the Python standard library:
ZIP extraction plus WordprocessingML parsing from `word/document.xml`.

## Extracted Fields

- paragraph index;
- paragraph text;
- paragraph style when present;
- source file SHA-256.

## Chapter Detection

A paragraph is treated as a chapter heading when:

- Word style resembles `Heading`, `Title`, or `Titulo`; or
- the text is short, alphabetic, and does not end like a normal sentence.

Ambiguous structure should remain visible in the generated plan instead of being
silently rewritten.

## Non-Goals

- No editorial rewriting.
- No external LLM call.
- No provider upload.
- No destructive manuscript cleanup.
49 changes: 49 additions & 0 deletions docs/audiobook/ffmpeg-mastering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# FFmpeg Mastering

OmniVoice uses FFmpeg as an optional local mastering engine.

## Commands

Concatenate segments and normalize stream shape:

```powershell
ffmpeg -n -f concat -safe 0 -i concat.txt -ar 44100 -ac 1 -c:a pcm_s16le chapter_raw.wav
```

Remaster a chapter or full book:

```powershell
ffmpeg -n -i chapter_raw.wav -af "silenceremove=start_periods=1:start_duration=0.2:start_threshold=-50dB,atempo=1.0,loudnorm=I=-20:TP=-3:LRA=11,alimiter=limit=0.707946" chapter_master.wav
```

Inspect metadata:

```powershell
ffprobe -v error -show_format -show_streams -of json chapter_master.wav
```

Create a QC report from a generated checkpoint:

```powershell
omnivoice-audiobook-qc --plan checkpoint.json --output qc_report.json
```

## Defaults

- Target loudness: `-20 LUFS`
- True peak: `-3 dB`
- Loudness range: `11`
- Stream normalization: mono, 44.1 kHz, PCM WAV
- Remaster output: forced to mono, 44.1 kHz by default
- `dynaudnorm` and `acompressor`: opt-in
- `silenceremove`: edge cleanup only by default
- Existing outputs are preserved by default. Use CLI `--overwrite` only when replacing an output is intentional.

## Safety

Generated chunks are never overwritten during mastering. Concatenated and
remastered outputs are separate files.

If `ffmpeg` or `ffprobe` is missing, the tool fails with a clear local error.

Do not claim audiobook readiness unless the QC report has `gate_status=pass`.
20 changes: 20 additions & 0 deletions docs/audiobook/fiction-profile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Fiction Profile

Use this profile for novels, short stories, memoir-like prose, and dialogue-heavy
books.

## Defaults

- Genre: `fiction`
- Voice style: `fiction_narrative`
- Target WPM: 158
- Tone: narrative
- Speed: 0.94
- Preset: `Natural`

## Handling Rules

- Preserve dialogue punctuation.
- Keep scene breaks visible as section or chapter pauses.
- Track recurring character names in pronunciation notes.
- Do not rewrite style, jokes, dialect, or quoted speech without approval.
46 changes: 46 additions & 0 deletions docs/audiobook/large-docx-500-pages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Large DOCX Files up to 500 Pages

The pipeline is designed for resumable work, not one giant request.

## Units

- DOCX: local source of truth.
- Chunk: provider planning unit, default target 1,800 words.
- Segment: TTS generation unit, usually 400-900 characters.
- Chapter: review and assembly unit.
- Full book: final optional merge.

## Modes

- Manual: user generates one segment or block at a time.
- Continuous: generate next pending segment until paused or failed.
- Chapter: generate and assemble a single chapter.
- Full book: assemble all completed chapters into one output file.

## Resume

`AudiobookGenerationJob` tracks segment state and checkpoint helpers persist the
plan as JSON. Pending and failed segments remain resumable without regenerating
completed audio.

Useful commands:

```powershell
omnivoice-audiobook-workflow status --plan audiobook_plan.json
omnivoice-audiobook-workflow next --plan audiobook_plan.json
omnivoice-audiobook-workflow mark-generated --plan audiobook_plan.json --segment-id seg_001_000001 --audio-path audio/seg.wav --output checkpoint.json
omnivoice-audiobook-workflow mark-failed --plan checkpoint.json --segment-id seg_001_000002 --error "provider failed" --output checkpoint.json
```

`next` redacts manuscript text by default. Add `--include-text` only for local
operator handoff to a TTS renderer.

## Expected Scale

A 500-page manuscript can produce thousands of segments. The system should be
operated through chunk/chapter progress rather than a single monolithic job.

The harness includes a synthetic 500-paragraph scale fixture to assert bounded
chunk size, deterministic chunk IDs, ordered paragraph ranges, short continuity
summaries, and provider payloads that contain only the selected chunk rather
than the whole manuscript.
42 changes: 42 additions & 0 deletions docs/audiobook/offline-security-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Offline Security Model

OmniVoice audiobook mode defaults to local-only execution.

## Required Guarantees

- No automatic model downloads.
- No provider calls in offline mode.
- Gradio must stay bound to `127.0.0.1`.
- `--share` remains blocked.
- Manuscripts, generated audio, JSON plans, caches, and provider payloads must not
be committed.
- Any online provider path must be explicitly selected by the user.

## Runtime Defaults

The offline runtime must keep:

- `HF_HUB_OFFLINE=1`
- `TRANSFORMERS_OFFLINE=1`
- `HF_DATASETS_OFFLINE=1`
- `GRADIO_ANALYTICS_ENABLED=False`
- `DISABLE_TELEMETRY=1`
- `DO_NOT_TRACK=1`

## Evidence Gates

- Static search for network libraries and provider calls in audiobook code.
- Runtime offline audit through `omnivoice.audiobook.offline_audit`.
- Tests that fail if `network_access_allowed()` stops returning `False`.
- Docker or batch jobs may use `network_mode: none` when running full offline
conversion and rendering.

## OpenRouter Exception

The OpenRouter path is not offline. It is a separate online mode and must require:

- explicit user consent;
- visible model/config selection;
- chunk-level preview;
- no full manuscript logging;
- no silent fallback from offline mode to provider mode.
Loading