{% extends "base.html" %} {% block title %}Prepare · {{ pending.original_filename }}{% endblock %} {% block content %}
1 Upload 2 Speakers 3 Queue
Prepare audiobook

Review the detected chapters, tune the speaker roster, and optionally override the voice per chapter before sending the job to the queue.

{% set analysis = pending.speaker_analysis or {} %} {% set analysis_speakers = analysis.get('speakers', {}) %} {% set show_analysis_prompt = pending.speaker_mode == 'multi' and not pending.analysis_requested %} {% set has_metadata = pending.metadata_tags %} {% set roster = pending.speakers or {} %} {% set speaker_configs = options.speaker_configs or [] %} {% set applied_languages = pending.speaker_voice_languages or analysis.get('config_languages', []) or [] %} {% set recommended_template = options.speaker_pronunciation_sentence or "This is {{name}} speaking." %}
Source
{{ pending.original_filename }}
Language
{{ options.languages.get(pending.language, pending.language|upper) }}
Default voice
{% if pending.voice_profile %}Profile · {{ pending.voice_profile }}{% else %}{{ pending.voice }}{% endif %}
Total chapters
{{ pending.chapters|length }}
Characters
{{ '{:,}'.format(pending.total_characters|default(0)) }}
Chapter intro delay
{{ '%.1f'|format(pending.chapter_intro_delay) }} seconds
Chunk granularity
{{ pending.chunk_level|replace('_', ' ')|title }}
Speaker mode
{{ pending.speaker_mode|replace('_', ' ')|title }}
Speaker analysis threshold
{{ pending.speaker_analysis_threshold }} {{ 'mention' if pending.speaker_analysis_threshold == 1 else 'mentions' }}
EPUB 3 package
{% if pending.generate_epub3 %}Enabled{% else %}Disabled{% endif %}
{% if applied_languages %}
Config languages
{{ applied_languages | map('upper') | join(', ') }}
{% endif %}
{% if analysis_speakers or show_analysis_prompt or has_metadata %}
{% if analysis_speakers %} {% set ordered_ids = analysis.get('ordered_speakers', []) %}

Detected speakers

{% if ordered_ids %}
    {% for sid in ordered_ids %} {% set speaker = analysis_speakers.get(sid) %} {% if speaker %}
  • {{ speaker.label }} {% if speaker.gender and speaker.gender != 'unknown' %} · {{ speaker.gender|title }} {% endif %} · {{ speaker.count }} lines · confidence {{ speaker.confidence|title }}
  • {% endif %} {% endfor %}
{% else %}

No additional speakers met the threshold yet. All dialogue will use the narrator voice.

{% endif %}
{% elif show_analysis_prompt %}

Detected speakers

Press Analyze speakers after selecting chapters to discover recurring voices.

{% endif %} {% if has_metadata %} {% endif %}
{% endif %}
{% if error %}
{{ error }}
{% endif %} {% if notice %}
{{ notice }}
{% endif %}

Speaker configuration

Reuse saved presets to keep character voices consistent between projects.

{% if roster %}

Speaker settings

Set pronunciations, lock specific voices, or limit the randomizer by language and gender.

    {% for speaker_id, speaker in roster.items() %} {% set spoken_name = speaker.pronunciation or speaker.label %} {% set preview_text = recommended_template | replace("{{name}}", spoken_name) %} {% set selected_voice = speaker.resolved_voice or speaker.voice %} {% set allowed_langs = speaker.config_languages or speaker.languages or [] %} {% set seen = namespace(values=[]) %}
  • {{ speaker.label }}
    {% if speaker.gender and speaker.gender != 'unknown' %} {{ speaker.gender|title }} {% else %} Gender unknown {% endif %} {% if speaker.get('analysis_count') %} {{ speaker.analysis_count }} lines · {{ speaker.analysis_confidence|default('low')|title }} confidence {% endif %}
    {% if speaker.recommended_voices %}
    Suggested: {% for voice_id in speaker.recommended_voices[:6] %} {% set voice_meta = options.voice_catalog_map.get(voice_id) or {} %} {% endfor %}
    {% endif %}
  • {% endfor %}
{% endif %}
{% for chapter in pending.chapters %} {% set is_enabled = chapter.enabled is not defined or chapter.enabled %} {% set selected_option = '__default' %} {% if chapter.voice_profile %} {% set selected_option = 'profile:' ~ chapter.voice_profile %} {% elif chapter.voice %} {% set selected_option = 'voice:' ~ chapter.voice %} {% elif chapter.voice_formula %} {% set selected_option = 'formula' %} {% endif %}
{{ '{:,}'.format(chapter.characters) }} characters
Preview text
{{ chapter.text[:2000] }}{% if chapter.text|length > 2000 %}…{% endif %}
{% endfor %}

Paragraphs work well for long-form narration; sentences give finer subtitle sync.

Only speakers that appear at least this many times will keep unique voices in multi-speaker mode.

Set to 0 to disable the pause after speaking each chapter title.

{% endblock %} {% block scripts %} {{ super() }} {% endblock %}