Added settings to allow control of exaggeration, cfg_weight, and temperature on each line.
This commit is contained in:
parent
26f1d98b46
commit
f9e952286d
|
@ -147,7 +147,7 @@ main {
|
|||
width: 110px;
|
||||
min-width: 90px;
|
||||
max-width: 130px;
|
||||
text-align: center;
|
||||
text-align: left;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ main {
|
|||
}
|
||||
|
||||
#dialog-items-table td.actions {
|
||||
text-align: center;
|
||||
text-align: left;
|
||||
min-width: 110px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -514,3 +514,159 @@ footer {
|
|||
outline: 2px solid var(--primary-blue);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
/* TTS Settings Modal */
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: var(--bg-white);
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--shadow-strong);
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px 24px 16px;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin: 0;
|
||||
color: var(--text-primary);
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
color: var(--text-secondary);
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.modal-close:hover {
|
||||
background-color: var(--bg-light);
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px 24px;
|
||||
}
|
||||
|
||||
.settings-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.settings-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.settings-group input[type="range"] {
|
||||
width: 100%;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.settings-group span {
|
||||
display: inline-block;
|
||||
min-width: 40px;
|
||||
font-weight: 500;
|
||||
color: var(--primary-blue);
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.settings-group small {
|
||||
display: block;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.875rem;
|
||||
margin-top: 4px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: flex-end;
|
||||
padding: 16px 24px 20px;
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.btn-primary, .btn-secondary {
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-blue);
|
||||
color: var(--text-white);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--primary-blue-dark);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--bg-light);
|
||||
color: var(--text-secondary);
|
||||
border: 1px solid var(--border-medium);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: var(--border-light);
|
||||
}
|
||||
|
||||
/* Settings button styling */
|
||||
.settings-line-btn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
background-color: var(--bg-light);
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
margin: 0 2px;
|
||||
transition: all 0.2s;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.settings-line-btn:hover {
|
||||
background-color: var(--primary-blue);
|
||||
color: var(--text-white);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.settings-line-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,40 @@
|
|||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- TTS Settings Modal -->
|
||||
<div id="tts-settings-modal" class="modal" style="display: none;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>TTS Settings</h3>
|
||||
<button class="modal-close" id="tts-modal-close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="settings-group">
|
||||
<label for="tts-exaggeration">Exaggeration:</label>
|
||||
<input type="range" id="tts-exaggeration" min="0" max="2" step="0.1" value="0.5">
|
||||
<span id="tts-exaggeration-value">0.5</span>
|
||||
<small>Controls expressiveness. Higher values = more exaggerated speech.</small>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label for="tts-cfg-weight">CFG Weight:</label>
|
||||
<input type="range" id="tts-cfg-weight" min="0" max="2" step="0.1" value="0.5">
|
||||
<span id="tts-cfg-weight-value">0.5</span>
|
||||
<small>Alignment with prompt. Higher values = more aligned with speaker characteristics.</small>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label for="tts-temperature">Temperature:</label>
|
||||
<input type="range" id="tts-temperature" min="0" max="2" step="0.1" value="0.8">
|
||||
<span id="tts-temperature-value">0.8</span>
|
||||
<small>Randomness. Lower values = more deterministic, higher = more varied.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="tts-settings-save" class="btn-primary">Save Settings</button>
|
||||
<button id="tts-settings-cancel" class="btn-secondary">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/api.js" type="module"></script>
|
||||
<script src="js/app.js" type="module" defer></script>
|
||||
</body>
|
||||
|
|
|
@ -111,12 +111,21 @@ let availableSpeakersCache = []; // To populate speaker dropdown
|
|||
|
||||
// Utility: ensure each dialog item has audioUrl, isGenerating, error
|
||||
function normalizeDialogItem(item) {
|
||||
return {
|
||||
const normalized = {
|
||||
...item,
|
||||
audioUrl: item.audioUrl || null,
|
||||
isGenerating: item.isGenerating || false,
|
||||
error: item.error || null
|
||||
};
|
||||
|
||||
// Add TTS settings for speech items with defaults
|
||||
if (item.type === 'speech') {
|
||||
normalized.exaggeration = item.exaggeration ?? 0.5;
|
||||
normalized.cfg_weight = item.cfg_weight ?? 0.5;
|
||||
normalized.temperature = item.temperature ?? 0.8;
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
async function initializeDialogEditor() {
|
||||
|
@ -332,6 +341,18 @@ async function initializeDialogEditor() {
|
|||
};
|
||||
actionsTd.appendChild(playBtn);
|
||||
|
||||
// --- NEW: Settings button for speech items ---
|
||||
if (item.type === 'speech') {
|
||||
const settingsBtn = document.createElement('button');
|
||||
settingsBtn.innerHTML = '⚙️';
|
||||
settingsBtn.title = 'TTS Settings';
|
||||
settingsBtn.className = 'settings-line-btn';
|
||||
settingsBtn.onclick = () => {
|
||||
showTTSSettingsModal(item, index);
|
||||
};
|
||||
actionsTd.appendChild(settingsBtn);
|
||||
}
|
||||
|
||||
// Show error if present
|
||||
if (item.error) {
|
||||
const errorSpan = document.createElement('span');
|
||||
|
@ -709,6 +730,88 @@ async function initializeDialogEditor() {
|
|||
|
||||
console.log('Dialog Editor Initialized');
|
||||
renderDialogItems(); // Initial render (empty)
|
||||
|
||||
// Add a function to show TTS settings modal
|
||||
function showTTSSettingsModal(item, index) {
|
||||
const modal = document.getElementById('tts-settings-modal');
|
||||
const exaggerationSlider = document.getElementById('tts-exaggeration');
|
||||
const exaggerationValue = document.getElementById('tts-exaggeration-value');
|
||||
const cfgWeightSlider = document.getElementById('tts-cfg-weight');
|
||||
const cfgWeightValue = document.getElementById('tts-cfg-weight-value');
|
||||
const temperatureSlider = document.getElementById('tts-temperature');
|
||||
const temperatureValue = document.getElementById('tts-temperature-value');
|
||||
const saveBtn = document.getElementById('tts-settings-save');
|
||||
const cancelBtn = document.getElementById('tts-settings-cancel');
|
||||
const closeBtn = document.getElementById('tts-modal-close');
|
||||
|
||||
// Set current values
|
||||
exaggerationSlider.value = item.exaggeration || 0.5;
|
||||
exaggerationValue.textContent = exaggerationSlider.value;
|
||||
cfgWeightSlider.value = item.cfg_weight || 0.5;
|
||||
cfgWeightValue.textContent = cfgWeightSlider.value;
|
||||
temperatureSlider.value = item.temperature || 0.8;
|
||||
temperatureValue.textContent = temperatureSlider.value;
|
||||
|
||||
// Update value displays when sliders change
|
||||
const updateValueDisplay = (slider, display) => {
|
||||
display.textContent = slider.value;
|
||||
};
|
||||
|
||||
exaggerationSlider.oninput = () => updateValueDisplay(exaggerationSlider, exaggerationValue);
|
||||
cfgWeightSlider.oninput = () => updateValueDisplay(cfgWeightSlider, cfgWeightValue);
|
||||
temperatureSlider.oninput = () => updateValueDisplay(temperatureSlider, temperatureValue);
|
||||
|
||||
// Show modal
|
||||
modal.style.display = 'flex';
|
||||
|
||||
// Save settings
|
||||
const saveSettings = () => {
|
||||
dialogItems[index].exaggeration = parseFloat(exaggerationSlider.value);
|
||||
dialogItems[index].cfg_weight = parseFloat(cfgWeightSlider.value);
|
||||
dialogItems[index].temperature = parseFloat(temperatureSlider.value);
|
||||
|
||||
// Clear any existing audio since settings changed
|
||||
dialogItems[index].audioUrl = null;
|
||||
|
||||
closeModal();
|
||||
renderDialogItems(); // Re-render to reflect changes
|
||||
console.log('TTS settings updated for item:', dialogItems[index]);
|
||||
};
|
||||
|
||||
// Close modal
|
||||
const closeModal = () => {
|
||||
modal.style.display = 'none';
|
||||
// Clean up event listeners
|
||||
exaggerationSlider.oninput = null;
|
||||
cfgWeightSlider.oninput = null;
|
||||
temperatureSlider.oninput = null;
|
||||
saveBtn.onclick = null;
|
||||
cancelBtn.onclick = null;
|
||||
closeBtn.onclick = null;
|
||||
modal.onclick = null;
|
||||
};
|
||||
|
||||
// Event listeners
|
||||
saveBtn.onclick = saveSettings;
|
||||
cancelBtn.onclick = closeModal;
|
||||
closeBtn.onclick = closeModal;
|
||||
|
||||
// Close modal when clicking outside
|
||||
modal.onclick = (e) => {
|
||||
if (e.target === modal) {
|
||||
closeModal();
|
||||
}
|
||||
};
|
||||
|
||||
// Close modal on Escape key
|
||||
const handleEscape = (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeModal();
|
||||
document.removeEventListener('keydown', handleEscape);
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', handleEscape);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Results Display --- //
|
||||
|
|
Loading…
Reference in New Issue