{% extends "base.html" %} {% from "_model_management.html" import model_management %} {% block content %}

{{ project.name }}

{{ project.source_path }} · Status: {{ project.status }}

{% set steps = [ ("upload", "Upload", "Parse manuscript"), ("scan", "Scan", "Review markers"), ("discover", "Discover", "Find speakers"), ("voices", "Voices", "Generate samples"), ("segment", "Segment", "Split utterances"), ("generate", "Generate", "Build audiobook"), ("export", "Export", "M4B + MP3") ] %} {% set current_step = pipeline_status.step if pipeline_status else "upload" %} {% set step_order = ["upload", "scan", "discover", "voices", "segment", "generate", "export"] %} {% set current_idx = step_order.index(current_step) if current_step in step_order else 0 %} {% for step_id, step_name, step_desc in steps %} {% set idx = loop.index0 %}
{{ idx + 1 }}
{{ step_name }}
{{ step_desc }}
{% if idx == current_idx and pipeline_status and pipeline_status.state == 'running' %}
{% endif %}
{% if not loop.last %}
{% endif %} {% endfor %}
{{ model_management(qwen_health=qwen_health, lm_status=lm_status, lm_models=lm_models) }}

Pipeline Activity

Live status of background tasks — chapter builds, speaker creation, audio generation.

{% if pipeline_activity and pipeline_activity.idle %}
Idle — no background tasks running
{% elif pipeline_activity %} {% for task in pipeline_activity.tasks if task.state != 'idle' %}
{{ task.name }} {{ task.state }}
{{ task.detail }}
{% if task.progress > 0 and task.state == 'active' %}
{% endif %}
{% if task.progress > 0 %} {{ task.progress }}% {% endif %}
{% endfor %} {% else %}
Loading…
{% endif %}
{% if chapter_count > 0 %}

Full Pipeline

Runs all steps automatically: Discover → Voices → Segment → Generate → Export

{% endif %}
{% if not project.source_path %}

Step 1: Upload Manuscript

Upload a Word document (.docx), EPUB, or text file.

{% else %} {# Step 1: Upload - always show status #}
Step 1 Complete

Manuscript Uploaded

{{ chapter_count }} chapters loaded

{# Step 2: Scan - always show status #} {% if scan_results %}
Step 2 Complete

Scan Results

File
{{ scan_results.filename }}
Format
{{ scan_results.format|upper }}
Chapters
{{ chapter_count }}
Scenes
{{ scene_count }}
Marker Tags {% for marker in scan_results.all_markers %} {{ marker }}{% if marker in scan_results.found_markers %} ✓{% else %} missing{% endif %} {% endfor %}
{% endif %} {# Step 3: Discover Speakers #} {% if speakers_json_exists %}
Step 3 Complete

Speakers Discovered

Review Speakers

{{ speaker_count }} speakers found

{% elif chapter_count > 0 %}

Step 3: Discover Speakers

Run LLM analysis to identify characters and speakers from the manuscript.

{% else %}

Step 3: Discover Speakers

Requires chapters to be loaded. Upload a manuscript first.

{% endif %} {# Step 4: Voice Samples #} {% if speakers_json_exists and voice_count > 0 %}
Step 4 Complete

Voice Samples Generated

Review Voices

{{ voice_count }} voice references ready

{% elif speakers_json_exists %}

Step 4: Generate Voice Samples

Generate unique voice references for each speaker using VoiceDesign. This will temporarily unload LM Studio models.

{% else %}

Step 4: Generate Voice Samples

Requires speakers to be discovered first.

{% endif %} {# Step 5: Segment Utterances #} {% if utterance_count > 0 %}
Step 5 Complete

Utterances Segmented

Review Chapters

{{ utterance_count }} utterances across {{ chapter_count }} chapters

{% elif speakers_json_exists %}

Step 5: Segment Utterances

Split the manuscript into individual utterances with speaker attribution.

{% else %}

Step 5: Segment Utterances

Requires speakers to be discovered first.

{% endif %} {# Step 6: Generate Audiobook #} {% if utterance_count > 0 %}

Step 6: Generate Audiobook

Generate audio for all utterances using the assigned voices.

{% if pipeline_status.step.value == 'generate' and pipeline_status.state.value == 'running' %}
{% if pipeline_status.total_utterances > 0 %} {% set gen_pct = (pipeline_status.completed_utterances / pipeline_status.total_utterances * 100)|int %} {% else %} {% set gen_pct = pipeline_status.progress %} {% endif %}

{{ pipeline_status.detail }}{% if pipeline_status.total_utterances > 0 %} ({{ pipeline_status.completed_utterances }}/{{ pipeline_status.total_utterances }} utterances){% endif %}

{% if pipeline_status.chapters_completed %}
Completed chapters:
{% for ch_id in pipeline_status.chapters_completed %} Ch{{ ch_id }} {% endfor %}
{% endif %} {% elif pipeline_status.step.value == 'generate' and pipeline_status.state.value == 'failed' %}
Failed {{ pipeline_status.error or pipeline_status.detail }}
{% if pipeline_status.chapters_completed %}
Completed chapters (reviewable):
{% for ch_id in pipeline_status.chapters_completed %} Ch{{ ch_id }} {% endfor %}
{% endif %} {% else %} {% endif %} {# --- Step 6b: Build final full-book .m4b --- #}

Build Final Audiobook (.m4b)

Assembles the finished chapter audio into a single M4B with metadata, chapter markers, and cover art from the m4b Meta page, then runs a quality check. Warnings/errors are shown below.

{% set exp = pipeline_status if pipeline_status and pipeline_status.state.value in ('running','completed','failed') and pipeline_status.step.value == 'export' else None %}
{% if exp and exp.state.value == 'failed' %} Failed {% elif exp and exp.state.value == 'completed' %} Complete {% if m4b_download %} Download .m4b {% endif %} {% elif exp and exp.state.value == 'running' %} Building {% endif %}
{% if exp and exp.state.value == 'running' %}

{{ exp.detail }}

{% elif exp %}

{{ exp.detail }}

{% if exp.warnings %}
Warnings ({{ exp.warnings|length }}):
    {% for w in exp.warnings %}
  • {{ w }}
  • {% endfor %}
{% endif %} {% if exp.errors %}
Errors ({{ exp.errors|length }}):
    {% for e in exp.errors %}
  • {{ e }}
  • {% endfor %}
{% endif %} {% endif %} {# --- Step 6c: Build Author's Republic MP3 package --- #}

Build Final Audiobook (MP3)

Author's Republic-ready MP3 package, one file per chapter you edit: sample (no number), opening intro i, closing ii, and story chapters numbered 1–27 from Salvage. Files are 44.1 kHz mono, 192 kbit CBR with 2 s silence at each end. Uses only your chapter audio — no narration is synthesized.

{% set aard = ar_status or {'state': 'idle', 'detail': '', 'progress': 0, 'error': ''} %}
{% if aard.state == 'failed' %} Failed {% elif aard.state == 'completed' %} Complete {% elif aard.state == 'running' %} Building {% elif ar_manifest %} Built {% endif %}
{% if aard.state == 'running' %}

{{ aard.detail }}

{% elif ar_manifest %}

{{ ar_manifest.track_count }} tracks · {{ "%.1f"|format(ar_manifest.total_duration_s / 60) }} min audio · built {{ ar_manifest.built_at }} {% if ar_manifest.warnings %}· {{ ar_manifest.warnings|length }} warning(s){% endif %} {% if ar_manifest.accepted_deviations %} · {{ ar_manifest.accepted_deviations|length }} accepted deviation(s) {% endif %}

{# One ZIP with every track plus the manifest: a distributor wants a single artifact. #} Download all MP3s (.zip)
{% if ar_manifest.accepted_deviations %}
{{ ar_manifest.accepted_deviations|length }} track(s) below the RMS floor (accepted) {% for d in ar_manifest.accepted_deviations %} {% endfor %}
Track RMS dB Peak dB Crest dB Rule
{{ d.track }} {{ "%.2f"|format(d.measured_rms_db) }} {{ "%.2f"|format(d.measured_peak_db) }} {{ "%.2f"|format(d.crest_db) }} {{ d.rule }}
{% endif %}
{% for t in ar_manifest.tracks %} {% endfor %}
# Role Title / File Min MB RMS dB Peak dB Status
{{ t.number or "–" }} {{ t.role }} {{ t.name }} ({{ t.source }}) {{ "%.1f"|format(t.duration_s / 60) }} {{ "%.1f"|format(t.size_bytes / 1048576) }} {{ "%.1f"|format(t.rms_db) }} {{ "%.1f"|format(t.peak_db) }} {% if t.warning %}{{ t.warning[:60] }} {% else %}ok{% endif %} MP3
{% endif %}
{% else %}

Step 6: Generate Audiobook

Requires utterances to be segmented first.

{% endif %} {# Step 7: Export #} {% if export_files %}
Step 7 Complete

Audiobook Ready

Exported {{ export_files|length }} file(s)

{% for f in export_files %}
{{ f.name }} {{ f.size_mb }} MB Download
{% endfor %}
{% elif pipeline_status.step == "export" and pipeline_status.state == "completed" %}
Step 7 Complete

Export Complete

{{ pipeline_status.detail }}

{% else %}

Step 7: Export Audiobook

Requires audio generation to complete. Exports to M4B and MP3.

{% endif %} {% endif %}
{{ chapter_count }}
Chapters
{{ scene_count }}
Scenes
{{ speaker_count }}
Speakers
{{ voice_count }}
Voice Samples
{{ utterance_count }}
Utterances
{{ audio_count }}
Audio Generated
{% endblock %}