ttsfm / ttsfm-web /templates /playground.html
NitinBot001's picture
Upload 38 files
3ca5f72 verified
{% extends "base.html" %}
{% block title %}TTSFM {{ _('nav.playground') }} - {{ _('playground.title') }}{% endblock %}
{% block content %}
<!-- Clean Playground Header -->
<section class="py-5" style="background-color: white; border-bottom: 1px solid #e5e7eb;">
<div class="container">
<div class="row align-items-center">
<div class="col-lg-8">
<div class="fade-in">
<div class="badge bg-primary text-white mb-3 px-3 py-2">
<i class="fas fa-flask me-2"></i>Demo
</div>
<h1 class="display-4 fw-bold mb-3 text-dark">
<i class="fas fa-play-circle me-3 text-primary"></i>{{ _('playground.title') }}
</h1>
<p class="lead mb-4 text-muted">
{{ _('playground.subtitle') }}
</p>
</div>
</div>
<div class="col-lg-4 text-center">
<div class="playground-visual fade-in" style="animation-delay: 0.3s;">
<div class="playground-icon">
<i class="fas fa-waveform-lines text-primary"></i>
<div class="pulse-ring"></div>
<div class="pulse-ring pulse-ring-delay"></div>
</div>
</div>
</div>
</div>
</div>
</section>
<div class="container py-5 playground">
<div class="row">
<div class="col-lg-10 mx-auto">
<div class="card shadow-lg-custom border-0 fade-in">
<div class="card-header bg-gradient-primary text-white">
<h4 class="mb-0 d-flex align-items-center">
<i class="fas fa-microphone me-2"></i>
{{ _('playground.title') }}
</h4>
</div>
<div class="card-body p-4">
<form id="tts-form" onsubmit="return false;">
<!-- Enhanced Text Input -->
<div class="mb-4">
<label for="text-input" class="form-label fw-bold d-flex align-items-center">
<i class="fas fa-edit me-2 text-primary"></i>
{{ _('playground.text_input_label') }}
</label>
<div class="position-relative">
<textarea
class="form-control shadow-sm"
id="text-input"
rows="4"
placeholder="{{ _('playground.text_input_placeholder') }}"
required
>Hello! This is a test of the TTSFM text-to-speech system.</textarea>
<div class="position-absolute top-0 end-0 p-2">
<button type="button" class="btn btn-sm btn-outline-secondary" id="clear-text-btn" title="Clear text">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div class="form-text d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center gap-3">
<span class="text-muted">
<i class="fas fa-keyboard me-1"></i>
<span id="char-count">0</span> {{ _('playground.character_count') }}
</span>
<span id="length-status" class=""></span>
<span id="auto-combine-status" class="badge bg-success d-none">
<i class="fas fa-magic me-1"></i>{{ _('playground.max_length_warning') }}
</span>
<span class="text-muted small">
<i class="fas fa-lightbulb me-1"></i>
Tip: Use Ctrl+Enter to generate
</span>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-sm btn-outline-primary" id="validate-text-btn">
<i class="fas fa-check me-1"></i>{{ _('common.validate') if _('common.validate') != 'common.validate' else 'Validate' }}
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" id="random-text-btn">
<i class="fas fa-dice me-1"></i>{{ _('playground.random_text') }}
</button>
</div>
</div>
<div id="validation-result" class="mt-2 d-none"></div>
</div>
<div class="row">
<!-- Enhanced Voice Selection -->
<div class="col-md-6 mb-4">
<label for="voice-select" class="form-label fw-bold d-flex align-items-center">
<i class="fas fa-microphone me-2 text-primary"></i>
{{ _('playground.voice_label') }}
</label>
<select class="form-select shadow-sm" id="voice-select" required>
<option value="">{{ _('common.loading_voices') }}</option>
</select>
<div class="form-text">
<span>{{ _('common.choose_voice') }}</span>
</div>
</div>
<!-- Enhanced Format Selection -->
<div class="col-md-6 mb-4">
<label for="format-select" class="form-label fw-bold d-flex align-items-center">
<i class="fas fa-file-audio me-2 text-primary"></i>
{{ _('playground.format_label') }}
</label>
<select class="form-select shadow-sm" id="format-select" required>
<option value="">{{ _('common.loading_formats') }}</option>
</select>
<div class="form-text">
<span>{{ _('common.select_format') }}</span>
</div>
</div>
</div>
<!-- Advanced Options -->
<div class="row">
<div class="col-md-6 mb-4">
<label for="max-length-input" class="form-label fw-bold">
<i class="fas fa-ruler me-2"></i>{{ _('common.max_length') }}
</label>
<input
type="number"
class="form-control"
id="max-length-input"
value="4096"
min="100"
max="10000"
>
<div class="form-text">
{{ _('playground.max_length_description') }}
</div>
</div>
<div class="col-md-6 mb-4">
<label class="form-label fw-bold">
<i class="fas fa-cog me-2"></i>{{ _('common.options') }}
</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="validate-length-check" checked>
<label class="form-check-label" for="validate-length-check">
{{ _('playground.enable_length_validation') }}
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="auto-combine-check" checked>
<label class="form-check-label" for="auto-combine-check">
<span class="fw-bold text-primary">{{ _('playground.auto_combine_long_text') }}</span>
<i class="fas fa-info-circle ms-1" data-bs-toggle="tooltip"
title="{{ _('playground.auto_combine_tooltip') }}"></i>
</label>
<div class="form-text small">
<i class="fas fa-magic me-1"></i>
{{ _('playground.auto_combine_description') }}
</div>
</div>
</div>
</div>
<!-- Instructions (Optional) -->
<div class="mb-4">
<label for="instructions-input" class="form-label fw-bold">
<i class="fas fa-magic me-2"></i>{{ _('playground.instructions_label') }}
</label>
<input
type="text"
class="form-control"
id="instructions-input"
placeholder="{{ _('playground.instructions_placeholder') }}"
>
<div class="form-text">
{{ _('playground.instructions_description') }}
</div>
</div>
<!-- API Key (Optional) -->
<div class="mb-4" id="api-key-section">
<label for="api-key-input" class="form-label fw-bold">
<i class="fas fa-key me-2"></i>{{ _('playground.api_key_optional') }}
</label>
<div class="input-group">
<input
type="password"
class="form-control"
id="api-key-input"
placeholder="{{ _('playground.api_key_placeholder') }}"
>
<button class="btn btn-outline-secondary" type="button" id="toggle-api-key-visibility">
<i class="fas fa-eye" id="api-key-eye-icon"></i>
</button>
</div>
<div class="form-text">
<i class="fas fa-info-circle me-1"></i>
{{ _('playground.api_key_description') }}
</div>
</div>
<!-- Enhanced Generate Button -->
<div class="text-center mb-4">
<div class="d-grid gap-2 d-md-block">
<button type="submit" class="btn btn-primary btn-lg px-4 py-3" id="generate-btn">
<span class="btn-text">
<i class="fas fa-magic me-2"></i>{{ _('playground.generate_speech') }}
</span>
<span class="loading-spinner">
<i class="fas fa-spinner fa-spin me-2"></i>{{ _('playground.generating') }}
</span>
</button>
<button type="button" class="btn btn-outline-secondary btn-lg ms-md-3" id="reset-form-btn">
<i class="fas fa-redo me-2"></i>{{ _('common.reset') }}
</button>
</div>
</div>
</form>
<!-- Enhanced Audio Player -->
<div id="audio-result" class="d-none">
<div class="border-top pt-4 mt-4">
<div class="d-flex align-items-center justify-content-between mb-3">
<h5 class="mb-0 d-flex align-items-center">
<i class="fas fa-volume-up me-2 text-success"></i>
{{ _('playground.audio_player_title') }}
<span class="badge bg-success ms-2">
<i class="fas fa-check me-1"></i>Ready
</span>
</h5>
<div class="btn-group" role="group">
<button type="button" class="btn btn-sm btn-outline-primary" id="replay-btn" title="Replay audio">
<i class="fas fa-redo"></i>
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" id="share-btn" title="Share audio">
<i class="fas fa-share"></i>
</button>
</div>
</div>
<div class="audio-player-container bg-light rounded p-3 mb-3">
<audio controls class="audio-player w-100" id="audio-player" preload="metadata">
Your browser does not support the audio element.
</audio>
<div class="audio-controls mt-2 d-flex justify-content-between align-items-center">
<div class="audio-info">
<span id="audio-info" class="text-muted small"></span>
</div>
<div class="audio-actions">
<button type="button" class="btn btn-success btn-sm" id="download-btn">
<i class="fas fa-download me-1"></i>{{ _('playground.download_audio') }}
</button>
</div>
</div>
</div>
<div class="audio-stats row text-center">
<div class="col-md-3 col-6">
<div class="stat-item">
<i class="fas fa-clock text-primary"></i>
<div class="stat-value" id="audio-duration">--</div>
<div class="stat-label">{{ _('playground.duration') }}</div>
</div>
</div>
<div class="col-md-3 col-6">
<div class="stat-item">
<i class="fas fa-file text-info"></i>
<div class="stat-value" id="audio-size">--</div>
<div class="stat-label">{{ _('playground.file_size') }}</div>
</div>
</div>
<div class="col-md-3 col-6">
<div class="stat-item">
<i class="fas fa-microphone text-warning"></i>
<div class="stat-value" id="audio-voice">--</div>
<div class="stat-label">{{ _('playground.voice') }}</div>
</div>
</div>
<div class="col-md-3 col-6">
<div class="stat-item">
<i class="fas fa-music text-success"></i>
<div class="stat-value" id="audio-format">--</div>
<div class="stat-label">{{ _('playground.format') }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<!-- Socket.IO for WebSocket support -->
<script src="https://cdn.socket.io/4.6.0/socket.io.min.js"></script>
<!-- WebSocket TTS Client -->
<script src="{{ url_for('static', filename='js/websocket-tts.js') }}"></script>
<!-- Enhanced Playground JavaScript with WebSocket Support -->
<script src="{{ url_for('static', filename='js/playground-enhanced-fixed.js') }}"></script>
<script>
// Additional playground-specific functionality
console.log('TTSFM Enhanced Playground with WebSocket support loaded successfully!');
</script>
{% endblock %}