{% set designations = speaker_designations(request) %}
{% set _ap = active_project(request) %}
{# The active project is a per-browser cookie. Two browsers could sit on
different books and their speaker lists are completely unrelated, which
made "51 need checking here, 20 there" look like a bug. Name the book
on the page itself, next to the counts it qualifies. #}
Reviewing{{ _ap.name }}โ this list is only this book; another browser or tab may be on a different one
Speakers ({{ speakers|length }})
{% set _clear = designations.values()|selectattr('status', 'equalto', 'clear')|list|length %}
{% set _needs = designations.values()|selectattr('status', 'equalto', 'needs_review')|list|length %}
{% if designations %}
{{ _clear }} clear{{ _needs }} need checking
{% endif %}
โ {{ _needs }} speaker{{ 's' if _needs != 1 }} need{{ '' if _needs != 1 }} checking โ these were not auto-accepted as distinct speakers. For each one:
Hover the โ needs check badge on the row to see
why โ e.g. named only by a role, no dialogue attributed, or a likely duplicate.
If the speaker is correct as-is (a real character, name is fine) โ press
โ Approve on its row.
That records your decision and clears the badge immediately; the page does not reload.
If the speaker is wrong โ use Edit to correct it, or Merge
it into an existing speaker, then re-scan Name Tokens.
Hover a row's badge for the full reason list.Show the list
{% for _n in designations.values()|sort(attribute='confidence')|selectattr('status', 'equalto', 'needs_review')|list %}
{% for r in _n.reasons %}โข {{ r }}{% if not loop.last %}; {% endif %}{% endfor %}
{% endfor %}
{% endif %}
{% set fallback_count = speakers|selectattr('engine_fallback')|list|length %}
{% if not qwen_up %}
โ Qwen3-TTS server unreachable โ {{ qwen_url or 'no qwen URL configured' }}. Voice generation will fall back to Edge-TTS, which loses raspy/texture and may pick an arbitrary voice. Restart the Qwen server first for real Qwen3 voices.
{% elif fallback_count %}
โ {{ fallback_count }} voice{{ 's' if fallback_count != 1 }} were generated with Edge-TTS fallback โ those rows show a red badge. Regenerate them now with a running Qwen3-TTS server to get the intended voices.
{% endif %}
Speaker
Aliases (get these right first)
Demographics
Vocal Traits
Voice Sample
Actions
{% for speaker in speakers %}
{% set speaker_idx = loop.index0 %}
{% include "_speaker_row.html" %}
{% endfor %}
Alias:
This alias belongs to . What would you like to do?
Add Speakers to Library
Selected speakers (and their voice reference samples) will be saved to the shared library for reuse on other projects.