Delete templates directory
No files matched your search
@@ -1,833 +0,0 @@
|
||||
import { doExtrasFetch, getApiUrl, modules } from '../../extensions.js';
|
||||
import { saveTtsProviderSettings } from './index.js';
|
||||
|
||||
export { AllTalkTtsProvider };
|
||||
|
||||
class AllTalkTtsProvider {
|
||||
//########//
|
||||
// Config //
|
||||
//########//
|
||||
|
||||
settings = {};
|
||||
constructor() {
|
||||
// Initialize with default settings if they are not already set
|
||||
this.settings = {
|
||||
provider_endpoint: this.settings.provider_endpoint || 'http://localhost:7851',
|
||||
language: this.settings.language || 'en',
|
||||
voiceMap: this.settings.voiceMap || {},
|
||||
at_generation_method: this.settings.at_generation_method || 'standard_generation',
|
||||
narrator_enabled: this.settings.narrator_enabled || 'false',
|
||||
at_narrator_text_not_inside: this.settings.at_narrator_text_not_inside || 'narrator',
|
||||
narrator_voice_gen: this.settings.narrator_voice_gen || 'female_01.wav',
|
||||
finetuned_model: this.settings.finetuned_model || 'false'
|
||||
};
|
||||
// Separate property for dynamically updated settings from the server
|
||||
this.dynamicSettings = {
|
||||
modelsAvailable: [],
|
||||
currentModel: '',
|
||||
deepspeed_available: false,
|
||||
deepSpeedEnabled: false,
|
||||
lowVramEnabled: false,
|
||||
};
|
||||
}
|
||||
ready = false;
|
||||
voices = [];
|
||||
separator = '. ';
|
||||
audioElement = document.createElement('audio');
|
||||
|
||||
languageLabels = {
|
||||
'Arabic': 'ar',
|
||||
'Brazilian Portuguese': 'pt',
|
||||
'Chinese': 'zh-cn',
|
||||
'Czech': 'cs',
|
||||
'Dutch': 'nl',
|
||||
'English': 'en',
|
||||
'French': 'fr',
|
||||
'German': 'de',
|
||||
'Italian': 'it',
|
||||
'Polish': 'pl',
|
||||
'Russian': 'ru',
|
||||
'Spanish': 'es',
|
||||
'Turkish': 'tr',
|
||||
'Japanese': 'ja',
|
||||
'Korean': 'ko',
|
||||
'Hungarian': 'hu',
|
||||
'Hindi': 'hi',
|
||||
};
|
||||
|
||||
get settingsHtml() {
|
||||
let html = `<div class="at-settings-separator">AllTalk Settings</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_generation_method">AllTalk TTS Generation Method</label>
|
||||
<select id="at_generation_method">
|
||||
<option value="standard_generation">Standard Audio Generation (AT Narrator - Optional)</option>
|
||||
<option value="streaming_enabled">Streaming Audio Generation (AT Narrator - Disabled)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_narrator_enabled">AT Narrator</label>
|
||||
<select id="at_narrator_enabled">
|
||||
<option value="true">Enabled</option>
|
||||
<option value="false">Disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="at-settings-option">
|
||||
<label for="at_narrator_text_not_inside">Text Not Inside * or " is</label>
|
||||
<select id="at_narrator_text_not_inside">
|
||||
<option value="narrator">Narrator</option>
|
||||
<option value="character">Character</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-settings-row">
|
||||
<div class="at-settings-option">
|
||||
<label for="narrator_voice">Narrator Voice</label>
|
||||
<select id="narrator_voice">`;
|
||||
if (this.voices) {
|
||||
for (let voice of this.voices) {
|
||||
html += `<option value="${voice.voice_id}">${voice.name}</option>`;
|
||||
}
|
||||
}
|
||||
html += `</select>
|
||||
</div>
|
||||
<div class="at-settings-option">
|
||||
<label for="language_options">Language</label>
|
||||
<select id="language_options">`;
|
||||
for (let language in this.languageLabels) {
|
||||
html += `<option value="${this.languageLabels[language]}" ${this.languageLabels[language] === this.settings?.language ? 'selected="selected"' : ''}>${language}</option>`;
|
||||
}
|
||||
html += `</select>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-model-endpoint-row">
|
||||
<div class="at-model-option">
|
||||
<label for="switch_model">Switch Model</label>
|
||||
<select id="switch_model">
|
||||
<option value="api_tts">API TTS</option>
|
||||
<option value="api_local">API Local</option>
|
||||
<option value="xttsv2_local">XTTSv2 Local</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="at-endpoint-option">
|
||||
<label for="at_server">AllTalk Endpoint:</label>
|
||||
<input id="at_server" type="text" class="text_pole" maxlength="80" value="${this.settings.provider_endpoint}"/>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-model-endpoint-row">
|
||||
<div class="at-settings-option">
|
||||
<label for="low_vram">Low VRAM</label>
|
||||
<input id="low_vram" type="checkbox"/>
|
||||
</div>
|
||||
<div class="at-settings-option">
|
||||
<label for="deepspeed">DeepSpeed</label>
|
||||
<input id="deepspeed" type="checkbox"/>
|
||||
</div>
|
||||
<div class="at-settings-option status-option">
|
||||
<span>Status: <span id="status_info">Ready</span></span>
|
||||
</div>
|
||||
<div class="at-settings-option empty-option">
|
||||
<!-- This div remains empty for spacing -->
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
||||
html += `<div class="at-website-row">
|
||||
<div class="at-website-option">
|
||||
<span>AllTalk <a target="_blank" href="${this.settings.provider_endpoint}">Config & Docs</a>.</span>
|
||||
</div>
|
||||
|
||||
<div class="at-website-option">
|
||||
<span>AllTalk <a target="_blank" href="https://github.com/erew123/alltalk_tts/">Website</a>.</span>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
html += `<div class="at-website-row">
|
||||
<div class="at-website-option">
|
||||
<span><strong>Text-generation-webui</strong> users - Uncheck <strong>Enable TTS</strong> in Text-generation-webui.</span>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
//#################//
|
||||
// Startup ST & AT //
|
||||
//#################//
|
||||
|
||||
async loadSettings(settings) {
|
||||
updateStatus('Offline');
|
||||
|
||||
if (Object.keys(settings).length === 0) {
|
||||
console.info('Using default AllTalk TTS Provider settings');
|
||||
} else {
|
||||
// Populate settings with provided values, ignoring server-provided settings
|
||||
for (const key in settings) {
|
||||
if (key in this.settings) {
|
||||
this.settings[key] = settings[key];
|
||||
} else {
|
||||
console.debug(`Ignoring non-user-configurable setting: ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update UI elements to reflect the loaded settings
|
||||
$('#at_server').val(this.settings.provider_endpoint);
|
||||
$('#language_options').val(this.settings.language);
|
||||
//$('#voicemap').val(this.settings.voiceMap);
|
||||
$('#at_generation_method').val(this.settings.at_generation_method);
|
||||
$('#at_narrator_enabled').val(this.settings.narrator_enabled);
|
||||
$('#at_narrator_text_not_inside').val(this.settings.at_narrator_text_not_inside);
|
||||
$('#narrator_voice').val(this.settings.narrator_voice_gen);
|
||||
|
||||
console.debug('AllTalkTTS: Settings loaded');
|
||||
try {
|
||||
// Check if TTS provider is ready
|
||||
await this.checkReady();
|
||||
await this.updateSettingsFromServer(); // Fetch dynamic settings from the TTS server
|
||||
await this.fetchTtsVoiceObjects(); // Fetch voices only if service is ready
|
||||
this.updateNarratorVoicesDropdown();
|
||||
this.updateLanguageDropdown();
|
||||
this.setupEventListeners();
|
||||
this.applySettingsToHTML();
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("Error loading settings:", error);
|
||||
updateStatus('Offline');
|
||||
}
|
||||
}
|
||||
|
||||
applySettingsToHTML() {
|
||||
// Apply loaded settings or use defaults
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
const atNarratorSelect = document.getElementById('at_narrator_enabled');
|
||||
const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
|
||||
const generationMethodSelect = document.getElementById('at_generation_method');
|
||||
this.settings.narrator_voice = this.settings.narrator_voice_gen;
|
||||
// Apply settings to Narrator Voice dropdown
|
||||
if (narratorVoiceSelect && this.settings.narrator_voice) {
|
||||
narratorVoiceSelect.value = this.settings.narrator_voice.replace('.wav', '');
|
||||
}
|
||||
// Apply settings to AT Narrator Enabled dropdown
|
||||
if (atNarratorSelect) {
|
||||
// Sync the state with the checkbox in index.js
|
||||
const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); // Access the checkbox from index.js
|
||||
const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); // Access the checkbox from index.js
|
||||
const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); // Access the checkbox from index.js
|
||||
// Sync the state with the checkbox in index.js
|
||||
if (this.settings.narrator_enabled) {
|
||||
ttsPassAsterisksCheckbox.checked = false;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
if (!this.settings.narrator_enabled) {
|
||||
ttsPassAsterisksCheckbox.checked = true;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
// Uncheck and set tts_narrate_quoted to false if narrator is enabled
|
||||
if (this.settings.narrator_enabledd) {
|
||||
ttsNarrateQuotedCheckbox.checked = true;
|
||||
ttsNarrateDialoguesCheckbox.checked = true;
|
||||
// Trigger click events instead of change events
|
||||
$('#tts_narrate_quoted').click();
|
||||
$('#tts_narrate_quoted').trigger('change');
|
||||
$('#tts_narrate_dialogues').click();
|
||||
$('#tts_narrate_dialogues').trigger('change');
|
||||
}
|
||||
atNarratorSelect.value = this.settings.narrator_enabled.toString();
|
||||
this.settings.narrator_enabled = this.settings.narrator_enabled.toString();
|
||||
}
|
||||
// Apply settings to the Language dropdown
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect && this.settings.language) {
|
||||
languageSelect.value = this.settings.language;
|
||||
}
|
||||
// Apply settings to Text Not Inside dropdown
|
||||
if (textNotInsideSelect && this.settings.text_not_inside) {
|
||||
textNotInsideSelect.value = this.settings.text_not_inside;
|
||||
this.settings.at_narrator_text_not_inside = this.settings.text_not_inside;
|
||||
}
|
||||
// Apply settings to Generation Method dropdown
|
||||
if (generationMethodSelect && this.settings.at_generation_method) {
|
||||
generationMethodSelect.value = this.settings.at_generation_method;
|
||||
}
|
||||
// Additional logic to disable/enable dropdowns based on the selected generation method
|
||||
const isStreamingEnabled = this.settings.at_generation_method === 'streaming_enabled';
|
||||
if (isStreamingEnabled) {
|
||||
// Disable certain dropdowns when streaming is enabled
|
||||
if (atNarratorSelect) atNarratorSelect.disabled = true;
|
||||
if (textNotInsideSelect) textNotInsideSelect.disabled = true;
|
||||
if (narratorVoiceSelect) narratorVoiceSelect.disabled = true;
|
||||
} else {
|
||||
// Enable dropdowns for standard generation
|
||||
if (atNarratorSelect) atNarratorSelect.disabled = false;
|
||||
if (textNotInsideSelect) textNotInsideSelect.disabled = !this.settings.narrator_enabled;
|
||||
if (narratorVoiceSelect) narratorVoiceSelect.disabled = !this.settings.narrator_enabled;
|
||||
}
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (this.settings.finetuned_model === 'true') {
|
||||
const ftOption = document.createElement('option');
|
||||
ftOption.value = 'XTTSv2 FT';
|
||||
ftOption.textContent = 'XTTSv2 FT';
|
||||
modelSelect.appendChild(ftOption);
|
||||
}
|
||||
}
|
||||
|
||||
//##############################//
|
||||
// Check AT Server is Available //
|
||||
//##############################//
|
||||
|
||||
async checkReady() {
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/ready`);
|
||||
// Check if the HTTP request was successful
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error Response: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
const statusText = await response.text();
|
||||
// Check if the response is 'Ready'
|
||||
if (statusText === 'Ready') {
|
||||
this.ready = true; // Set the ready flag to true
|
||||
console.log('TTS service is ready.');
|
||||
} else {
|
||||
this.ready = false;
|
||||
console.log('TTS service is not ready.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking TTS service readiness:', error);
|
||||
this.ready = false; // Ensure ready flag is set to false in case of error
|
||||
}
|
||||
}
|
||||
|
||||
//######################//
|
||||
// Get Available Voices //
|
||||
//######################//
|
||||
|
||||
async fetchTtsVoiceObjects() {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/voices`);
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
const voices = data.voices.map(filename => {
|
||||
const voiceName = filename.replace('.wav', '');
|
||||
return {
|
||||
name: voiceName,
|
||||
voice_id: voiceName,
|
||||
preview_url: null, // Preview URL will be dynamically generated
|
||||
lang: 'en' // Default language
|
||||
};
|
||||
});
|
||||
this.voices = voices; // Assign to the class property
|
||||
return voices; // Also return this list
|
||||
}
|
||||
|
||||
//##########################################//
|
||||
// Get Current AT Server Config & Update ST //
|
||||
//##########################################//
|
||||
|
||||
async updateSettingsFromServer() {
|
||||
try {
|
||||
// Fetch current settings
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/currentsettings`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch current settings: ${response.statusText}`);
|
||||
}
|
||||
const currentSettings = await response.json();
|
||||
// Update internal settings
|
||||
this.settings.modelsAvailable = currentSettings.models_available;
|
||||
this.settings.currentModel = currentSettings.current_model_loaded;
|
||||
this.settings.deepspeed_available = currentSettings.deepspeed_available;
|
||||
this.settings.deepSpeedEnabled = currentSettings.deepspeed_status;
|
||||
this.settings.lowVramEnabled = currentSettings.low_vram_status;
|
||||
this.settings.finetuned_model = currentSettings.finetuned_model
|
||||
// Update HTML elements
|
||||
this.updateModelDropdown();
|
||||
this.updateCheckboxes();
|
||||
} catch (error) {
|
||||
console.error(`Error updating settings from server: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
//###################################################//
|
||||
// Get Current AT Server Config & Update ST (Models) //
|
||||
//###################################################//
|
||||
|
||||
updateModelDropdown() {
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (modelSelect) {
|
||||
modelSelect.innerHTML = ''; // Clear existing options
|
||||
this.settings.modelsAvailable.forEach(model => {
|
||||
const option = document.createElement('option');
|
||||
option.value = model.model_name;
|
||||
option.textContent = model.model_name; // Use model_name instead of name
|
||||
option.selected = model.model_name === this.settings.currentModel;
|
||||
modelSelect.appendChild(option);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//#######################################################//
|
||||
// Get Current AT Server Config & Update ST (DS and LVR) //
|
||||
//#######################################################//
|
||||
|
||||
updateCheckboxes() {
|
||||
const deepspeedCheckbox = document.getElementById('deepspeed');
|
||||
const lowVramCheckbox = document.getElementById('low_vram');
|
||||
if (lowVramCheckbox) lowVramCheckbox.checked = this.settings.lowVramEnabled;
|
||||
if (deepspeedCheckbox) {
|
||||
deepspeedCheckbox.checked = this.settings.deepSpeedEnabled;
|
||||
deepspeedCheckbox.disabled = !this.settings.deepspeed_available; // Disable checkbox if deepspeed is not available
|
||||
}
|
||||
}
|
||||
|
||||
//###############################################################//
|
||||
// Get Current AT Server Config & Update ST (AT Narrator Voices) //
|
||||
//###############################################################//
|
||||
|
||||
updateNarratorVoicesDropdown() {
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
if (narratorVoiceSelect && this.voices) {
|
||||
// Clear existing options
|
||||
narratorVoiceSelect.innerHTML = '';
|
||||
// Add new options
|
||||
for (let voice of this.voices) {
|
||||
const option = document.createElement('option');
|
||||
option.value = voice.voice_id;
|
||||
option.textContent = voice.name;
|
||||
narratorVoiceSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//######################################################//
|
||||
// Get Current AT Server Config & Update ST (Languages) //
|
||||
//######################################################//
|
||||
|
||||
updateLanguageDropdown() {
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect) {
|
||||
// Ensure default language is set
|
||||
this.settings.language = this.settings.language;
|
||||
|
||||
languageSelect.innerHTML = '';
|
||||
for (let language in this.languageLabels) {
|
||||
const option = document.createElement('option');
|
||||
option.value = this.languageLabels[language];
|
||||
option.textContent = language;
|
||||
if (this.languageLabels[language] === this.settings.language) {
|
||||
option.selected = true;
|
||||
}
|
||||
languageSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//########################################//
|
||||
// Start AT TTS extenstion page listeners //
|
||||
//########################################//
|
||||
|
||||
setupEventListeners() {
|
||||
|
||||
let debounceTimeout;
|
||||
const debounceDelay = 500; // Milliseconds
|
||||
|
||||
// Define the event handler function
|
||||
const onModelSelectChange = async (event) => {
|
||||
console.log("Model select change event triggered"); // Debugging statement
|
||||
const selectedModel = event.target.value;
|
||||
console.log(`Selected model: ${selectedModel}`); // Debugging statement
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/reload?tts_method=${encodeURIComponent(selectedModel)}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
|
||||
// Handle response or error
|
||||
};
|
||||
|
||||
const debouncedModelSelectChange = (event) => {
|
||||
clearTimeout(debounceTimeout);
|
||||
debounceTimeout = setTimeout(() => {
|
||||
onModelSelectChange(event);
|
||||
}, debounceDelay);
|
||||
};
|
||||
|
||||
// Switch Model Listener
|
||||
const modelSelect = document.getElementById('switch_model');
|
||||
if (modelSelect) {
|
||||
// Remove the event listener if it was previously added
|
||||
modelSelect.removeEventListener('change', debouncedModelSelectChange);
|
||||
// Add the debounced event listener
|
||||
modelSelect.addEventListener('change', debouncedModelSelectChange);
|
||||
}
|
||||
|
||||
// DeepSpeed Listener
|
||||
const deepspeedCheckbox = document.getElementById('deepspeed');
|
||||
if (deepspeedCheckbox) {
|
||||
deepspeedCheckbox.addEventListener('change', async (event) => {
|
||||
const deepSpeedValue = event.target.checked ? 'True' : 'False';
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/deepspeed?new_deepspeed_value=${deepSpeedValue}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Low VRAM Listener
|
||||
const lowVramCheckbox = document.getElementById('low_vram');
|
||||
if (lowVramCheckbox) {
|
||||
lowVramCheckbox.addEventListener('change', async (event) => {
|
||||
const lowVramValue = event.target.checked ? 'True' : 'False';
|
||||
// Set status to Processing
|
||||
updateStatus('Processing');
|
||||
try {
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/lowvramsetting?new_low_vram_value=${lowVramValue}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP Error: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("POST response data:", data); // Debugging statement
|
||||
// Set status to Ready if successful
|
||||
updateStatus('Ready');
|
||||
} catch (error) {
|
||||
console.error("POST request error:", error); // Debugging statement
|
||||
// Set status to Error in case of failure
|
||||
updateStatus('Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Narrator Voice Dropdown Listener
|
||||
const narratorVoiceSelect = document.getElementById('narrator_voice');
|
||||
if (narratorVoiceSelect) {
|
||||
narratorVoiceSelect.addEventListener('change', (event) => {
|
||||
this.settings.narrator_voice_gen = `${event.target.value}.wav`;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
const textNotInsideSelect = document.getElementById('at_narrator_text_not_inside');
|
||||
if (textNotInsideSelect) {
|
||||
textNotInsideSelect.addEventListener('change', (event) => {
|
||||
this.settings.text_not_inside = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// AT Narrator Dropdown Listener
|
||||
const atNarratorSelect = document.getElementById('at_narrator_enabled');
|
||||
const ttsPassAsterisksCheckbox = document.getElementById('tts_pass_asterisks'); // Access the checkbox from index.js
|
||||
const ttsNarrateQuotedCheckbox = document.getElementById('tts_narrate_quoted'); // Access the checkbox from index.js
|
||||
const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues'); // Access the checkbox from index.js
|
||||
|
||||
if (atNarratorSelect && textNotInsideSelect && narratorVoiceSelect) {
|
||||
atNarratorSelect.addEventListener('change', (event) => {
|
||||
const isNarratorEnabled = event.target.value === 'true';
|
||||
this.settings.narrator_enabled = isNarratorEnabled; // Update the setting here
|
||||
textNotInsideSelect.disabled = !isNarratorEnabled;
|
||||
narratorVoiceSelect.disabled = !isNarratorEnabled;
|
||||
|
||||
// Sync the state with the checkbox in index.js
|
||||
if (isNarratorEnabled) {
|
||||
ttsPassAsterisksCheckbox.checked = false;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
if (!isNarratorEnabled) {
|
||||
ttsPassAsterisksCheckbox.checked = true;
|
||||
$('#tts_pass_asterisks').click(); // Simulate a click event
|
||||
$('#tts_pass_asterisks').trigger('change');
|
||||
}
|
||||
// Uncheck and set tts_narrate_quoted to false if narrator is enabled
|
||||
if (isNarratorEnabled) {
|
||||
ttsNarrateQuotedCheckbox.checked = true;
|
||||
ttsNarrateDialoguesCheckbox.checked = true;
|
||||
// Trigger click events instead of change events
|
||||
$('#tts_narrate_quoted').click();
|
||||
$('#tts_narrate_quoted').trigger('change');
|
||||
$('#tts_narrate_dialogues').click();
|
||||
$('#tts_narrate_dialogues').trigger('change');
|
||||
}
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Event Listener for AT Generation Method Dropdown
|
||||
const atGenerationMethodSelect = document.getElementById('at_generation_method');
|
||||
const atNarratorEnabledSelect = document.getElementById('at_narrator_enabled');
|
||||
if (atGenerationMethodSelect) {
|
||||
atGenerationMethodSelect.addEventListener('change', (event) => {
|
||||
const selectedMethod = event.target.value;
|
||||
|
||||
if (selectedMethod === 'streaming_enabled') {
|
||||
// Disable and unselect AT Narrator
|
||||
atNarratorEnabledSelect.disabled = true;
|
||||
atNarratorEnabledSelect.value = 'false';
|
||||
textNotInsideSelect.disabled = true;
|
||||
narratorVoiceSelect.disabled = true;
|
||||
} else if (selectedMethod === 'standard_generation') {
|
||||
// Enable AT Narrator
|
||||
atNarratorEnabledSelect.disabled = false;
|
||||
}
|
||||
this.settings.at_generation_method = selectedMethod; // Update the setting here
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// Listener for Language Dropdown
|
||||
const languageSelect = document.getElementById('language_options');
|
||||
if (languageSelect) {
|
||||
languageSelect.addEventListener('change', (event) => {
|
||||
this.settings.language = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
// Listener for AllTalk Endpoint Input
|
||||
const atServerInput = document.getElementById('at_server');
|
||||
if (atServerInput) {
|
||||
atServerInput.addEventListener('input', (event) => {
|
||||
this.settings.provider_endpoint = event.target.value;
|
||||
this.onSettingsChange(); // Save the settings after change
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//#############################//
|
||||
// Store ST interface settings //
|
||||
//#############################//
|
||||
|
||||
onSettingsChange() {
|
||||
// Update settings based on the UI elements
|
||||
//this.settings.provider_endpoint = $('#at_server').val();
|
||||
this.settings.language = $('#language_options').val();
|
||||
//this.settings.voiceMap = $('#voicemap').val();
|
||||
this.settings.at_generation_method = $('#at_generation_method').val();
|
||||
this.settings.narrator_enabled = $('#at_narrator_enabled').val();
|
||||
this.settings.at_narrator_text_not_inside = $('#at_narrator_text_not_inside').val();
|
||||
this.settings.narrator_voice_gen = $('#narrator_voice').val();
|
||||
// Save the updated settings
|
||||
saveTtsProviderSettings();
|
||||
}
|
||||
|
||||
//#########################//
|
||||
// ST Handle Reload button //
|
||||
//#########################//
|
||||
|
||||
async onRefreshClick() {
|
||||
await this.checkReady(); // Check if the TTS provider is ready
|
||||
await this.loadSettings(this.settings); // Reload the settings
|
||||
// Additional actions as needed
|
||||
}
|
||||
|
||||
//##################//
|
||||
// Preview AT Voice //
|
||||
//##################//
|
||||
|
||||
async previewTtsVoice(voiceName) {
|
||||
try {
|
||||
// Prepare data for POST request
|
||||
const postData = new URLSearchParams();
|
||||
postData.append("voice", `${voiceName}.wav`);
|
||||
// Making the POST request
|
||||
const response = await fetch(`${this.settings.provider_endpoint}/api/previewvoice/`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: postData,
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`[previewTtsVoice] Error Response Text:`, errorText);
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
// Assuming the server returns a URL to the .wav file
|
||||
const data = await response.json();
|
||||
if (data.output_file_url) {
|
||||
// Use an audio element to play the .wav file
|
||||
const audioElement = new Audio(data.output_file_url);
|
||||
audioElement.play().catch(e => console.error("Error playing audio:", e));
|
||||
} else {
|
||||
console.warn("[previewTtsVoice] No output file URL received in the response");
|
||||
throw new Error("No output file URL received in the response");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("[previewTtsVoice] Exception caught during preview generation:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
//#####################//
|
||||
// Populate ST voices //
|
||||
//#####################//
|
||||
|
||||
async getVoice(voiceName, generatePreview = false) {
|
||||
// Ensure this.voices is populated
|
||||
if (this.voices.length === 0) {
|
||||
// Fetch voice objects logic
|
||||
}
|
||||
// Find the object where the name matches voiceName
|
||||
const match = this.voices.find(voice => voice.name === voiceName);
|
||||
if (!match) {
|
||||
// Error handling
|
||||
}
|
||||
// Generate preview URL only if requested
|
||||
if (!match.preview_url && generatePreview) {
|
||||
// Generate preview logic
|
||||
}
|
||||
return match; // Return the found voice object
|
||||
}
|
||||
|
||||
//##########################################//
|
||||
// Generate TTS Streaming or call Standard //
|
||||
//##########################################//
|
||||
|
||||
async generateTts(inputText, voiceId) {
|
||||
try {
|
||||
if (this.settings.at_generation_method === 'streaming_enabled') {
|
||||
// Construct the streaming URL
|
||||
const streamingUrl = `${this.settings.provider_endpoint}/api/tts-generate-streaming?text=${encodeURIComponent(inputText)}&voice=${encodeURIComponent(voiceId)}.wav&language=${encodeURIComponent(this.settings.language)}&output_file=stream_output.wav`;
|
||||
console.log("Streaming URL:", streamingUrl);
|
||||
|
||||
// Return the streaming URL directly
|
||||
return streamingUrl;
|
||||
} else {
|
||||
// For standard method
|
||||
const outputUrl = await this.fetchTtsGeneration(inputText, voiceId);
|
||||
const audioResponse = await fetch(outputUrl);
|
||||
if (!audioResponse.ok) {
|
||||
throw new Error(`HTTP ${audioResponse.status}: Failed to fetch audio data`);
|
||||
}
|
||||
return audioResponse; // Return the fetch response directly
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in generateTts:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//####################//
|
||||
// Generate Standard //
|
||||
//####################//
|
||||
|
||||
async fetchTtsGeneration(inputText, voiceId) {
|
||||
// Prepare the request payload
|
||||
const requestBody = new URLSearchParams({
|
||||
'text_input': inputText,
|
||||
'text_filtering': "standard",
|
||||
'character_voice_gen': voiceId + ".wav",
|
||||
'narrator_enabled': this.settings.narrator_enabled,
|
||||
'narrator_voice_gen': this.settings.narrator_voice_gen + ".wav",
|
||||
'text_not_inside': this.settings.at_narrator_text_not_inside,
|
||||
'language': this.settings.language,
|
||||
'output_file_name': "st_output",
|
||||
'output_file_timestamp': "true",
|
||||
'autoplay': "false",
|
||||
'autoplay_volume': "0.8"
|
||||
}).toString();
|
||||
|
||||
try {
|
||||
const response = await doExtrasFetch(
|
||||
`${this.settings.provider_endpoint}/api/tts-generate`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Cache-Control': 'no-cache',
|
||||
},
|
||||
body: requestBody
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(`[fetchTtsGeneration] Error Response Text:`, errorText);
|
||||
// toastr.error(response.statusText, 'TTS Generation Failed');
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
const outputUrl = data.output_file_url;
|
||||
return outputUrl; // Return only the output_file_url
|
||||
} catch (error) {
|
||||
console.error("[fetchTtsGeneration] Exception caught:", error);
|
||||
throw error; // Rethrow the error for further handling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#########################//
|
||||
// Update Status Messages //
|
||||
//#########################//
|
||||
|
||||
function updateStatus(message) {
|
||||
const statusElement = document.getElementById('status_info');
|
||||
if (statusElement) {
|
||||
statusElement.textContent = message;
|
||||
switch (message) {
|
||||
case 'Offline':
|
||||
statusElement.style.color = 'red';
|
||||
break;
|
||||
case 'Ready':
|
||||
statusElement.style.color = 'lightgreen';
|
||||
break;
|
||||
case 'Processing':
|
||||
statusElement.style.color = 'blue';
|
||||
break;
|
||||
case 'Error':
|
||||
statusElement.style.color = 'red';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
#tts_media_control {
|
||||
/* order: 100; */
|
||||
/* width: 40px;
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
padding: 1px; */
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
/* transition: 0.3s;
|
||||
opacity: 0.7; */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* justify-content: center; */
|
||||
|
||||
}
|
||||
|
||||
#ttsExtensionMenuItem {
|
||||
transition: 0.3s;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#ttsExtensionMenuItem:hover {
|
||||
opacity: 1;
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
#tts_media_control:hover {
|
||||
opacity: 1;
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
.voice_preview {
|
||||
margin: 0.25rem 0.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.voice_preview .voice_name {
|
||||
text-align: left;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.voice_preview .voice_lang {
|
||||
width: 4rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.voice_preview .fa-play {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tts-button {
|
||||
margin: 0;
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: 0.3s;
|
||||
opacity: 0.7;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
.tts-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tts_block {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
column-gap: 5px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tts_custom_voices {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.novel_tts_hints {
|
||||
font-size: calc(0.9 * var(--mainFontSize));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.at-settings-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.at-settings-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.at-endpoint-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
margin-right: 25px;
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
.at-website-row {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.at-website-option {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.at-settings-separator {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 18x;
|
||||
font-weight: bold;
|
||||
border-top: 1px solid #e1e1e1; /* Grey line */
|
||||
border-bottom: 1px solid #e1e1e1; /* Grey line */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.at-status-message {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.at-model-endpoint-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.at-model-option, .endpoint-option {
|
||||
flex: 1;
|
||||
margin: 0 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.at-endpoint-option {
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
#at-status_info {
|
||||
color: lightgreen;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 476 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,260 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AllTalk Startup Settings</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
text-decoration: underline;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
form {
|
||||
max-width: 975px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 5px;
|
||||
/* Adjusted the gap to create more space */
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
grid-column: span 2;
|
||||
/* Span both columns */
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-top: 2px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
select,
|
||||
input,
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 3px;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 3px;
|
||||
box-sizing: border-box;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
grid-column: span 4;
|
||||
}
|
||||
|
||||
.warning {
|
||||
grid-column: span 4;
|
||||
/* Span all 4 columns */
|
||||
text-align: center;
|
||||
/* Center-align the text */
|
||||
color: red;
|
||||
/* Adjusted color for emphasis */
|
||||
font-weight: bold;
|
||||
/* Make the text bold */
|
||||
margin-top: 10px;
|
||||
/* Add some space between the button and the warning */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h3>AllTalk Startup Settings</h3><br>
|
||||
<form action="/update-settings" method="post">
|
||||
|
||||
<label for="activate" style="color: #33cc33;">Activate TTS:</label>
|
||||
<select id="activate" name="activate" required="">
|
||||
<option {% if data.activate %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.activate %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="autoplay" style="color: #33cc33;"> Autoplay TTS output:</label>
|
||||
<select id="autoplay" name="autoplay" required="">
|
||||
<option {% if data.autoplay %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.autoplay %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="show_text" style="color: #33cc33;"> Show Text on generation:</label>
|
||||
<select id="show_text" name="show_text" required="">
|
||||
<option {% if data.show_text %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.show_text %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="voice" style="color: #33cc33;"> Default voice:</label>
|
||||
<select id="voice" name="voice" required="">
|
||||
{% for file in wav_files %}
|
||||
<option value="{{ file }}" {% if data.voice==file %}selected{% endif %}>{{ file }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
|
||||
<label for="language" style="color: #33cc33;">Default Language:</label>
|
||||
<select id="language" name="language" required="">
|
||||
<option value="Arabic" {% if data.language=='Arabic' %}selected{% endif %}>Arabic</option>
|
||||
<option value="Chinese" {% if data.language=='Chinese' %}selected{% endif %}>Chinese</option>
|
||||
<option value="Czech" {% if data.language=='Czech' %}selected{% endif %}>Czech</option>
|
||||
<option value="Dutch" {% if data.language=='Dutch' %}selected{% endif %}>Dutch</option>
|
||||
<option value="English" {% if data.language=='English' %}selected{% endif %}>English</option>
|
||||
<option value="French" {% if data.language=='French' %}selected{% endif %}>French</option>
|
||||
<option value="German" {% if data.language=='German' %}selected{% endif %}>German</option>
|
||||
<option value="Hungarian" {% if data.language=='Hungarian' %}selected{% endif %}>Hungarian</option>
|
||||
<option value="Italian" {% if data.language=='Italian' %}selected{% endif %}>Italian</option>
|
||||
<option value="Japanese" {% if data.language=='Japanese' %}selected{% endif %}>Japanese</option>
|
||||
<option value="Korean" {% if data.language=='Korean' %}selected{% endif %}>Korean</option>
|
||||
<option value="Polish" {% if data.language=='Polish' %}selected{% endif %}>Polish</option>
|
||||
<option value="Portuguese" {% if data.language=='Portuguese' %}selected{% endif %}>Portuguese</option>
|
||||
<option value="Russian" {% if data.language=='Russian' %}selected{% endif %}>Russian</option>
|
||||
<option value="Spanish" {% if data.language=='Spanish' %}selected{% endif %}>Spanish</option>
|
||||
<option value="Turkish" {% if data.language=='Turkish' %}selected{% endif %}>Turkish</option>
|
||||
</select>
|
||||
|
||||
<label for="narrator_voice" style="color: #33cc33;"> Narrator voice:</label>
|
||||
<select id="narrator_voice" name="narrator_voice" required="">
|
||||
{% for file in wav_files %}
|
||||
<option value="{{ file }}" {% if data.narrator_voice==file %}selected{% endif %}>{{ file }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label for="remove_trailing_dots" style="color: #33cc33;"> Remove Trailing Dots:</label>
|
||||
<select id="remove_trailing_dots" name="remove_trailing_dots" required="">
|
||||
<option {% if data.remove_trailing_dots %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.remove_trailing_dots %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="narrator_enabled" style="color: #33cc33;"> Narrator enabled:</label>
|
||||
<select id="narrator_enabled" name="narrator_enabled" required="">
|
||||
<option {% if data.narrator_enabled %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.narrator_enabled %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="delete_output_wavs" style="color: #33cc33;">Del WAV's older than:</label>
|
||||
<select id="delete_output_wavs" name="delete_output_wavs" required="">
|
||||
<option value="Disabled" {% if data.delete_output_wavs=='Disabled' %}selected{% endif %}>Disabled</option>
|
||||
<option value="1 Day" {% if data.delete_output_wavs=='1 Day' %}selected{% endif %}>1 Day</option>
|
||||
<option value="2 Days" {% if data.delete_output_wavs=='2 Days' %}selected{% endif %}>2 Days</option>
|
||||
<option value="3 Days" {% if data.delete_output_wavs=='3 Days' %}selected{% endif %}>3 Days</option>
|
||||
<option value="4 Day" {% if data.delete_output_wavs=='4 Days' %}selected{% endif %}>4 Days</option>
|
||||
<option value="5 Day" {% if data.delete_output_wavs=='5 Days' %}selected{% endif %}>5 Days</option>
|
||||
<option value="6 Day" {% if data.delete_output_wavs=='6 Days' %}selected{% endif %}>6 Days</option>
|
||||
<option value="7 Days" {% if data.delete_output_wavs=='7 Days' %}selected{% endif %}>7 Days</option>
|
||||
<option value="14 Days" {% if data.delete_output_wavs=='14 Days' %}selected{% endif %}>14 Days</option>
|
||||
<option value="21 Days" {% if data.delete_output_wavs=='21 Days' %}selected{% endif %}>21 Days</option>
|
||||
<option value="28 Days" {% if data.delete_output_wavs=='28 Days' %}selected{% endif %}>28 Days</option>
|
||||
</select>
|
||||
|
||||
|
||||
<label for="low_vram" style="color: #33cc33;"> Low VRAM:</label>
|
||||
<select id="low_vram" name="low_vram" required="">
|
||||
<option {% if data.low_vram %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.low_vram %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="local_temperature" style="color: red;">Local Model temperature:</label>
|
||||
<select id="local_temperature" name="local_temperature" required="">
|
||||
{% for temp in range(0, 101, 5) %}
|
||||
<option value="{{ temp/100 }}" {% if data.local_temperature|float == temp/100 %}selected{% endif %}>{{ "{:.2f}".format(temp/100) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label for="local_repetition_penalty" style="color: red;"> Local Model repetition penalty:</label>
|
||||
<select id="local_repetition_penalty" name="local_repetition_penalty" required="">
|
||||
{% for repetition in range(10, 210, 10) %}
|
||||
<option value="{{ repetition/10 }}" {% if data.local_repetition_penalty|float == repetition/10 %}selected{% endif %}>{{ repetition/10 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label for="deepspeed_activate" style="color: red;">DeepSpeed Activate:</label>
|
||||
<select id="deepspeed_activate" name="deepspeed_activate" required="">
|
||||
<option {% if data.deepspeed_activate %}selected{% endif %} value="true">True</option>
|
||||
<option {% if not data.deepspeed_activate %}selected{% endif %} value="false">False</option>
|
||||
</select>
|
||||
|
||||
<label for="output_folder_wav" style="color: red;"> WAV Output Folder:</label>
|
||||
<input id="output_folder_wav" name="output_folder_wav" required="" type="text"
|
||||
value="{{ data.output_folder_wav }}" />
|
||||
|
||||
|
||||
<input type="hidden" id="tts_model_loaded" name="tts_model_loaded" value="{{ data.tts_model_loaded }}" />
|
||||
|
||||
<!-- Continue updating other dropdowns and inputs in a similar manner -->
|
||||
|
||||
<label for="tts_model_name" style="color: red;"> API TTS Model Name:</label>
|
||||
<input id="tts_model_name" name="tts_model_name" required="" type="text" value="{{ data.tts_model_name }}" />
|
||||
|
||||
<label for="model_version"
|
||||
style="color: red; font-size: 16px; line-height: 1; vertical-align: bottom; margin-bottom: 0;">
|
||||
API Local Model Folder:</label>
|
||||
<span style="font-size: 14px; vertical-align: bottom; margin-bottom: 0; margin-top: 2px;">{{
|
||||
modeldownload_model_path }}</span>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<label for="ip_address" style="color: red;"> IP Address:</label>
|
||||
<input id="ip_address" name="ip_address" required="" type="text" value="{{ data.ip_address }}" />
|
||||
|
||||
<label for="port_number" style="color: red;"> Port Number:</label>
|
||||
<input id="port_number" name="port_number" required="" type="text" value="{{ data.port_number }}" />
|
||||
|
||||
<div class="radio-group">
|
||||
<label for="tts_method_api_local" style="color: #33cc33;">Model: <span
|
||||
style="color: black; font-weight: normal;">API Local</span>:</label>
|
||||
<input id="tts_method_api_local_true" {% if data.tts_method_api_local %}checked{% endif %} name="tts_method"
|
||||
type="radio" value="api_local" />
|
||||
</div>
|
||||
|
||||
<div class="radio-group">
|
||||
<label for="tts_method_api_tts" style="color: #33cc33;"> Model: <span
|
||||
style="color: black; font-weight: normal;">API TTS</span>:</label>
|
||||
<input id="tts_method_api_tts_true" {% if data.tts_method_api_tts %}checked{% endif %} name="tts_method"
|
||||
type="radio" value="api_tts" />
|
||||
</div>
|
||||
|
||||
<div class="radio-group">
|
||||
<label for="tts_method_xtts_local" style="color: #33cc33;">Model: <span
|
||||
style="color: black; font-weight: normal;">XTTS Local</span>:</label>
|
||||
<input id="tts_method_xtts_local_true" {% if data.tts_method_xtts_local %}checked{% endif %}
|
||||
name="tts_method" type="radio" value="xtts_local" />
|
||||
</div>
|
||||
<button type="submit">Update Settings</button>
|
||||
</form>
|
||||
<p class="warning">WARNING: Changing RED items or setting DeepSpeed to True on a system without DeepSpeed installed,
|
||||
may cause errors.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
Before Width: | Height: | Size: 547 KiB |
|
Before Width: | Height: | Size: 156 KiB |
@@ -1,869 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
import textwrap
|
||||
from functools import cached_property
|
||||
|
||||
import pypinyin
|
||||
import torch
|
||||
from hangul_romanize import Transliter
|
||||
from hangul_romanize.rule import academic
|
||||
from num2words import num2words
|
||||
from spacy.lang.ar import Arabic
|
||||
from spacy.lang.en import English
|
||||
from spacy.lang.es import Spanish
|
||||
from spacy.lang.ja import Japanese
|
||||
from spacy.lang.zh import Chinese
|
||||
from tokenizers import Tokenizer
|
||||
|
||||
from TTS.tts.layers.xtts.zh_num2words import TextNorm as zh_num2words
|
||||
|
||||
|
||||
def get_spacy_lang(lang):
|
||||
if lang == "zh":
|
||||
return Chinese()
|
||||
elif lang == "ja":
|
||||
return Japanese()
|
||||
elif lang == "ar":
|
||||
return Arabic()
|
||||
elif lang == "es":
|
||||
return Spanish()
|
||||
else:
|
||||
# For most languages, Enlish does the job
|
||||
return English()
|
||||
|
||||
|
||||
def split_sentence(text, lang, text_split_length=250):
|
||||
"""Preprocess the input text"""
|
||||
text_splits = []
|
||||
if text_split_length is not None and len(text) >= text_split_length:
|
||||
text_splits.append("")
|
||||
nlp = get_spacy_lang(lang)
|
||||
nlp.add_pipe("sentencizer")
|
||||
doc = nlp(text)
|
||||
for sentence in doc.sents:
|
||||
if len(text_splits[-1]) + len(str(sentence)) <= text_split_length:
|
||||
# if the last sentence + the current sentence is less than the text_split_length
|
||||
# then add the current sentence to the last sentence
|
||||
text_splits[-1] += " " + str(sentence)
|
||||
text_splits[-1] = text_splits[-1].lstrip()
|
||||
elif len(str(sentence)) > text_split_length:
|
||||
# if the current sentence is greater than the text_split_length
|
||||
for line in textwrap.wrap(
|
||||
str(sentence),
|
||||
width=text_split_length,
|
||||
drop_whitespace=True,
|
||||
break_on_hyphens=False,
|
||||
tabsize=1,
|
||||
):
|
||||
text_splits.append(str(line))
|
||||
else:
|
||||
text_splits.append(str(sentence))
|
||||
|
||||
if len(text_splits) > 1:
|
||||
if text_splits[0] == "":
|
||||
del text_splits[0]
|
||||
else:
|
||||
text_splits = [text.lstrip()]
|
||||
|
||||
return text_splits
|
||||
|
||||
|
||||
_whitespace_re = re.compile(r"\s+")
|
||||
|
||||
# List of (regular expression, replacement) pairs for abbreviations:
|
||||
_abbreviations = {
|
||||
"en": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("mrs", "misess"),
|
||||
("mr", "mister"),
|
||||
("dr", "doctor"),
|
||||
("st", "saint"),
|
||||
("co", "company"),
|
||||
("jr", "junior"),
|
||||
("maj", "major"),
|
||||
("gen", "general"),
|
||||
("drs", "doctors"),
|
||||
("rev", "reverend"),
|
||||
("lt", "lieutenant"),
|
||||
("hon", "honorable"),
|
||||
("sgt", "sergeant"),
|
||||
("capt", "captain"),
|
||||
("esq", "esquire"),
|
||||
("ltd", "limited"),
|
||||
("col", "colonel"),
|
||||
("ft", "fort"),
|
||||
]
|
||||
],
|
||||
"es": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("sra", "señora"),
|
||||
("sr", "señor"),
|
||||
("dr", "doctor"),
|
||||
("dra", "doctora"),
|
||||
("st", "santo"),
|
||||
("co", "compañía"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitada"),
|
||||
]
|
||||
],
|
||||
"fr": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("mme", "madame"),
|
||||
("mr", "monsieur"),
|
||||
("dr", "docteur"),
|
||||
("st", "saint"),
|
||||
("co", "compagnie"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitée"),
|
||||
]
|
||||
],
|
||||
"de": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("fr", "frau"),
|
||||
("dr", "doktor"),
|
||||
("st", "sankt"),
|
||||
("co", "firma"),
|
||||
("jr", "junior"),
|
||||
]
|
||||
],
|
||||
"pt": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("sra", "senhora"),
|
||||
("sr", "senhor"),
|
||||
("dr", "doutor"),
|
||||
("dra", "doutora"),
|
||||
("st", "santo"),
|
||||
("co", "companhia"),
|
||||
("jr", "júnior"),
|
||||
("ltd", "limitada"),
|
||||
]
|
||||
],
|
||||
"it": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# ("sig.ra", "signora"),
|
||||
("sig", "signore"),
|
||||
("dr", "dottore"),
|
||||
("st", "santo"),
|
||||
("co", "compagnia"),
|
||||
("jr", "junior"),
|
||||
("ltd", "limitata"),
|
||||
]
|
||||
],
|
||||
"pl": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("p", "pani"),
|
||||
("m", "pan"),
|
||||
("dr", "doktor"),
|
||||
("sw", "święty"),
|
||||
("jr", "junior"),
|
||||
]
|
||||
],
|
||||
"ar": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# There are not many common abbreviations in Arabic as in English.
|
||||
]
|
||||
],
|
||||
"zh": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# Chinese doesn't typically use abbreviations in the same way as Latin-based scripts.
|
||||
]
|
||||
],
|
||||
"cs": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dr", "doktor"), # doctor
|
||||
("ing", "inženýr"), # engineer
|
||||
("p", "pan"), # Could also map to pani for woman but no easy way to do it
|
||||
# Other abbreviations would be specialized and not as common.
|
||||
]
|
||||
],
|
||||
"ru": [
|
||||
(re.compile("\\b%s\\b" % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("г-жа", "госпожа"), # Mrs.
|
||||
("г-н", "господин"), # Mr.
|
||||
("д-р", "доктор"), # doctor
|
||||
# Other abbreviations are less common or specialized.
|
||||
]
|
||||
],
|
||||
"nl": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dhr", "de heer"), # Mr.
|
||||
("mevr", "mevrouw"), # Mrs.
|
||||
("dr", "dokter"), # doctor
|
||||
("jhr", "jonkheer"), # young lord or nobleman
|
||||
# Dutch uses more abbreviations, but these are the most common ones.
|
||||
]
|
||||
],
|
||||
"tr": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("b", "bay"), # Mr.
|
||||
("byk", "büyük"), # büyük
|
||||
("dr", "doktor"), # doctor
|
||||
# Add other Turkish abbreviations here if needed.
|
||||
]
|
||||
],
|
||||
"hu": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("dr", "doktor"), # doctor
|
||||
("b", "bácsi"), # Mr.
|
||||
("nőv", "nővér"), # nurse
|
||||
# Add other Hungarian abbreviations here if needed.
|
||||
]
|
||||
],
|
||||
"ko": [
|
||||
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
# Korean doesn't typically use abbreviations in the same way as Latin-based scripts.
|
||||
]
|
||||
],
|
||||
"ja": [
|
||||
(re.compile("\\b%s\\b" % x[0]), x[1])
|
||||
for x in [
|
||||
("氏", "さん"), # Mr.
|
||||
("夫人", "おんなのひと"), # Mrs.
|
||||
("博士", "はかせ"), # Doctor or PhD
|
||||
("株", "株式会社"), # Corporation
|
||||
("有", "有限会社"), # Limited company
|
||||
("大学", "だいがく"), # University
|
||||
("先生", "せんせい"), # Teacher/Professor/Master
|
||||
("君", "くん") # Used at the end of boys' names to express familiarity or affection.
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def expand_abbreviations_multilingual(text, lang="en"):
|
||||
for regex, replacement in _abbreviations[lang]:
|
||||
text = re.sub(regex, replacement, text)
|
||||
return text
|
||||
|
||||
|
||||
_symbols_multilingual = {
|
||||
"en": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " and "),
|
||||
("@", " at "),
|
||||
("%", " percent "),
|
||||
("#", " hash "),
|
||||
("$", " dollar "),
|
||||
("£", " pound "),
|
||||
("°", " degree "),
|
||||
]
|
||||
],
|
||||
"es": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " y "),
|
||||
("@", " arroba "),
|
||||
("%", " por ciento "),
|
||||
("#", " numeral "),
|
||||
("$", " dolar "),
|
||||
("£", " libra "),
|
||||
("°", " grados "),
|
||||
]
|
||||
],
|
||||
"fr": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " et "),
|
||||
("@", " arobase "),
|
||||
("%", " pour cent "),
|
||||
("#", " dièse "),
|
||||
("$", " dollar "),
|
||||
("£", " livre "),
|
||||
("°", " degrés "),
|
||||
]
|
||||
],
|
||||
"de": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " und "),
|
||||
("@", " at "),
|
||||
("%", " prozent "),
|
||||
("#", " raute "),
|
||||
("$", " dollar "),
|
||||
("£", " pfund "),
|
||||
("°", " grad "),
|
||||
]
|
||||
],
|
||||
"pt": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " e "),
|
||||
("@", " arroba "),
|
||||
("%", " por cento "),
|
||||
("#", " cardinal "),
|
||||
("$", " dólar "),
|
||||
("£", " libra "),
|
||||
("°", " graus "),
|
||||
]
|
||||
],
|
||||
"it": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " e "),
|
||||
("@", " chiocciola "),
|
||||
("%", " per cento "),
|
||||
("#", " cancelletto "),
|
||||
("$", " dollaro "),
|
||||
("£", " sterlina "),
|
||||
("°", " gradi "),
|
||||
]
|
||||
],
|
||||
"pl": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " i "),
|
||||
("@", " małpa "),
|
||||
("%", " procent "),
|
||||
("#", " krzyżyk "),
|
||||
("$", " dolar "),
|
||||
("£", " funt "),
|
||||
("°", " stopnie "),
|
||||
]
|
||||
],
|
||||
"ar": [
|
||||
# Arabic
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " و "),
|
||||
("@", " على "),
|
||||
("%", " في المئة "),
|
||||
("#", " رقم "),
|
||||
("$", " دولار "),
|
||||
("£", " جنيه "),
|
||||
("°", " درجة "),
|
||||
]
|
||||
],
|
||||
"zh": [
|
||||
# Chinese
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " 和 "),
|
||||
("@", " 在 "),
|
||||
("%", " 百分之 "),
|
||||
("#", " 号 "),
|
||||
("$", " 美元 "),
|
||||
("£", " 英镑 "),
|
||||
("°", " 度 "),
|
||||
]
|
||||
],
|
||||
"cs": [
|
||||
# Czech
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " a "),
|
||||
("@", " na "),
|
||||
("%", " procento "),
|
||||
("#", " křížek "),
|
||||
("$", " dolar "),
|
||||
("£", " libra "),
|
||||
("°", " stupně "),
|
||||
]
|
||||
],
|
||||
"ru": [
|
||||
# Russian
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " и "),
|
||||
("@", " собака "),
|
||||
("%", " процентов "),
|
||||
("#", " номер "),
|
||||
("$", " доллар "),
|
||||
("£", " фунт "),
|
||||
("°", " градус "),
|
||||
]
|
||||
],
|
||||
"nl": [
|
||||
# Dutch
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " en "),
|
||||
("@", " bij "),
|
||||
("%", " procent "),
|
||||
("#", " hekje "),
|
||||
("$", " dollar "),
|
||||
("£", " pond "),
|
||||
("°", " graden "),
|
||||
]
|
||||
],
|
||||
"tr": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " ve "),
|
||||
("@", " at "),
|
||||
("%", " yüzde "),
|
||||
("#", " diyez "),
|
||||
("$", " dolar "),
|
||||
("£", " sterlin "),
|
||||
("°", " derece "),
|
||||
]
|
||||
],
|
||||
"hu": [
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " és "),
|
||||
("@", " kukac "),
|
||||
("%", " százalék "),
|
||||
("#", " kettőskereszt "),
|
||||
("$", " dollár "),
|
||||
("£", " font "),
|
||||
("°", " fok "),
|
||||
]
|
||||
],
|
||||
"ko": [
|
||||
# Korean
|
||||
(re.compile(r"%s" % re.escape(x[0]), re.IGNORECASE), x[1])
|
||||
for x in [
|
||||
("&", " 그리고 "),
|
||||
("@", " 에 "),
|
||||
("%", " 퍼센트 "),
|
||||
("#", " 번호 "),
|
||||
("$", " 달러 "),
|
||||
("£", " 파운드 "),
|
||||
("°", " 도 "),
|
||||
]
|
||||
],
|
||||
"ja": [
|
||||
(re.compile(r"%s" % re.escape(x[0])), x[1])
|
||||
for x in [
|
||||
("&", " と "),
|
||||
("@", " アットマーク "),
|
||||
("%", " パーセント "),
|
||||
("#", " ナンバー "),
|
||||
("$", " ドル "),
|
||||
("£", " ポンド "),
|
||||
("°", " 度"),
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def expand_symbols_multilingual(text, lang="en"):
|
||||
for regex, replacement in _symbols_multilingual[lang]:
|
||||
text = re.sub(regex, replacement, text)
|
||||
text = text.replace(" ", " ") # Ensure there are no double spaces
|
||||
return text.strip()
|
||||
|
||||
|
||||
_ordinal_re = {
|
||||
"en": re.compile(r"([0-9]+)(st|nd|rd|th)"),
|
||||
"es": re.compile(r"([0-9]+)(º|ª|er|o|a|os|as)"),
|
||||
"fr": re.compile(r"([0-9]+)(º|ª|er|re|e|ème)"),
|
||||
"de": re.compile(r"([0-9]+)(st|nd|rd|th|º|ª|\.(?=\s|$))"),
|
||||
"pt": re.compile(r"([0-9]+)(º|ª|o|a|os|as)"),
|
||||
"it": re.compile(r"([0-9]+)(º|°|ª|o|a|i|e)"),
|
||||
"pl": re.compile(r"([0-9]+)(º|ª|st|nd|rd|th)"),
|
||||
"ar": re.compile(r"([0-9]+)(ون|ين|ث|ر|ى)"),
|
||||
"cs": re.compile(r"([0-9]+)\.(?=\s|$)"), # In Czech, a dot is often used after the number to indicate ordinals.
|
||||
"ru": re.compile(r"([0-9]+)(-й|-я|-е|-ое|-ье|-го)"),
|
||||
"nl": re.compile(r"([0-9]+)(de|ste|e)"),
|
||||
"tr": re.compile(r"([0-9]+)(\.|inci|nci|uncu|üncü|\.)"),
|
||||
"hu": re.compile(r"([0-9]+)(\.|adik|edik|odik|edik|ödik|ödike|ik)"),
|
||||
"ko": re.compile(r"([0-9]+)(번째|번|차|째)"),
|
||||
"ja": re.compile(r"([0-9]+)(番|回|つ|目|等|位)")
|
||||
}
|
||||
_number_re = re.compile(r"[0-9]+")
|
||||
_currency_re = {
|
||||
"USD": re.compile(r"((\$[0-9\.\,]*[0-9]+)|([0-9\.\,]*[0-9]+\$))"),
|
||||
"GBP": re.compile(r"((£[0-9\.\,]*[0-9]+)|([0-9\.\,]*[0-9]+£))"),
|
||||
"EUR": re.compile(r"(([0-9\.\,]*[0-9]+€)|((€[0-9\.\,]*[0-9]+)))"),
|
||||
}
|
||||
|
||||
_comma_number_re = re.compile(r"\b\d{1,3}(,\d{3})*(\.\d+)?\b")
|
||||
_dot_number_re = re.compile(r"\b\d{1,3}(.\d{3})*(\,\d+)?\b")
|
||||
_decimal_number_re = re.compile(r"([0-9]+[.,][0-9]+)")
|
||||
|
||||
|
||||
def _remove_commas(m):
|
||||
text = m.group(0)
|
||||
if "," in text:
|
||||
text = text.replace(",", "")
|
||||
return text
|
||||
|
||||
|
||||
def _remove_dots(m):
|
||||
text = m.group(0)
|
||||
if "." in text:
|
||||
text = text.replace(".", "")
|
||||
return text
|
||||
|
||||
|
||||
def _expand_decimal_point(m, lang="en"):
|
||||
amount = m.group(1).replace(",", ".")
|
||||
return num2words(float(amount), lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def _expand_currency(m, lang="en", currency="USD"):
|
||||
amount = float((re.sub(r"[^\d.]", "", m.group(0).replace(",", "."))))
|
||||
full_amount = num2words(amount, to="currency", currency=currency, lang=lang if lang != "cs" else "cz")
|
||||
|
||||
and_equivalents = {
|
||||
"en": ", ",
|
||||
"es": " con ",
|
||||
"fr": " et ",
|
||||
"de": " und ",
|
||||
"pt": " e ",
|
||||
"it": " e ",
|
||||
"pl": ", ",
|
||||
"cs": ", ",
|
||||
"ru": ", ",
|
||||
"nl": ", ",
|
||||
"ar": ", ",
|
||||
"tr": ", ",
|
||||
"hu": ", ",
|
||||
"ko": ", ",
|
||||
}
|
||||
|
||||
if amount.is_integer():
|
||||
last_and = full_amount.rfind(and_equivalents[lang])
|
||||
if last_and != -1:
|
||||
full_amount = full_amount[:last_and]
|
||||
|
||||
return full_amount
|
||||
|
||||
|
||||
def _expand_ordinal(m, lang="en"):
|
||||
return num2words(int(m.group(1)), ordinal=True, lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def _expand_number(m, lang="en"):
|
||||
return num2words(int(m.group(0)), lang=lang if lang != "cs" else "cz")
|
||||
|
||||
|
||||
def expand_numbers_multilingual(text, lang="en"):
|
||||
if lang == "zh":
|
||||
text = zh_num2words()(text)
|
||||
else:
|
||||
if lang in ["en", "ru"]:
|
||||
text = re.sub(_comma_number_re, _remove_commas, text)
|
||||
else:
|
||||
text = re.sub(_dot_number_re, _remove_dots, text)
|
||||
try:
|
||||
text = re.sub(_currency_re["GBP"], lambda m: _expand_currency(m, lang, "GBP"), text)
|
||||
text = re.sub(_currency_re["USD"], lambda m: _expand_currency(m, lang, "USD"), text)
|
||||
text = re.sub(_currency_re["EUR"], lambda m: _expand_currency(m, lang, "EUR"), text)
|
||||
except:
|
||||
pass
|
||||
if lang != "tr":
|
||||
text = re.sub(_decimal_number_re, lambda m: _expand_decimal_point(m, lang), text)
|
||||
text = re.sub(_ordinal_re[lang], lambda m: _expand_ordinal(m, lang), text)
|
||||
text = re.sub(_number_re, lambda m: _expand_number(m, lang), text)
|
||||
return text
|
||||
|
||||
|
||||
def lowercase(text):
|
||||
return text.lower()
|
||||
|
||||
|
||||
def collapse_whitespace(text):
|
||||
return re.sub(_whitespace_re, " ", text)
|
||||
|
||||
|
||||
def multilingual_cleaners(text, lang):
|
||||
text = text.replace('"', "")
|
||||
if lang == "tr":
|
||||
text = text.replace("İ", "i")
|
||||
text = text.replace("Ö", "ö")
|
||||
text = text.replace("Ü", "ü")
|
||||
text = lowercase(text)
|
||||
text = expand_numbers_multilingual(text, lang)
|
||||
text = expand_abbreviations_multilingual(text, lang)
|
||||
text = expand_symbols_multilingual(text, lang=lang)
|
||||
text = collapse_whitespace(text)
|
||||
return text
|
||||
|
||||
|
||||
def basic_cleaners(text):
|
||||
"""Basic pipeline that lowercases and collapses whitespace without transliteration."""
|
||||
text = lowercase(text)
|
||||
text = collapse_whitespace(text)
|
||||
return text
|
||||
|
||||
|
||||
def chinese_transliterate(text):
|
||||
return "".join(
|
||||
[p[0] for p in pypinyin.pinyin(text, style=pypinyin.Style.TONE3, heteronym=False, neutral_tone_with_five=True)]
|
||||
)
|
||||
|
||||
|
||||
def japanese_cleaners(text, katsu):
|
||||
text = katsu.romaji(text)
|
||||
text = lowercase(text)
|
||||
return text
|
||||
|
||||
|
||||
def korean_transliterate(text):
|
||||
r = Transliter(academic)
|
||||
return r.translit(text)
|
||||
|
||||
|
||||
DEFAULT_VOCAB_FILE = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../data/tokenizer.json")
|
||||
|
||||
|
||||
class VoiceBpeTokenizer:
|
||||
def __init__(self, vocab_file=None):
|
||||
self.tokenizer = None
|
||||
if vocab_file is not None:
|
||||
self.tokenizer = Tokenizer.from_file(vocab_file)
|
||||
self.char_limits = {
|
||||
"en": 250,
|
||||
"de": 253,
|
||||
"fr": 273,
|
||||
"es": 239,
|
||||
"it": 213,
|
||||
"pt": 203,
|
||||
"pl": 224,
|
||||
"zh": 82,
|
||||
"ar": 166,
|
||||
"cs": 186,
|
||||
"ru": 182,
|
||||
"nl": 251,
|
||||
"tr": 226,
|
||||
"ja": 71,
|
||||
"hu": 224,
|
||||
"ko": 95,
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def katsu(self):
|
||||
import cutlet
|
||||
|
||||
return cutlet.Cutlet()
|
||||
|
||||
def check_input_length(self, txt, lang):
|
||||
lang = lang.split("-")[0] # remove the region
|
||||
limit = self.char_limits.get(lang, 250)
|
||||
if len(txt) > limit:
|
||||
print(
|
||||
f"[!] Warning: The text length exceeds the character limit of {limit} for language '{lang}', this might cause truncated audio."
|
||||
)
|
||||
|
||||
def preprocess_text(self, txt, lang):
|
||||
if lang in {"ar", "cs", "de", "en", "es", "fr", "hu", "it", "nl", "pl", "pt", "ru", "tr", "zh", "ko"}:
|
||||
txt = multilingual_cleaners(txt, lang)
|
||||
if lang == "zh":
|
||||
txt = chinese_transliterate(txt)
|
||||
if lang == "ko":
|
||||
txt = korean_transliterate(txt)
|
||||
elif lang == "ja":
|
||||
txt = japanese_cleaners(txt, self.katsu)
|
||||
elif lang == "hi":
|
||||
# @manmay will implement this
|
||||
txt = basic_cleaners(txt)
|
||||
else:
|
||||
raise NotImplementedError(f"Language '{lang}' is not supported.")
|
||||
return txt
|
||||
|
||||
def encode(self, txt, lang):
|
||||
lang = lang.split("-")[0] # remove the region
|
||||
self.check_input_length(txt, lang)
|
||||
txt = self.preprocess_text(txt, lang)
|
||||
lang = "zh-cn" if lang == "zh" else lang
|
||||
txt = f"[{lang}]{txt}"
|
||||
txt = txt.replace(" ", "[SPACE]")
|
||||
return self.tokenizer.encode(txt).ids
|
||||
|
||||
def decode(self, seq):
|
||||
if isinstance(seq, torch.Tensor):
|
||||
seq = seq.cpu().numpy()
|
||||
txt = self.tokenizer.decode(seq, skip_special_tokens=False).replace(" ", "")
|
||||
txt = txt.replace("[SPACE]", " ")
|
||||
txt = txt.replace("[STOP]", "")
|
||||
txt = txt.replace("[UNK]", "")
|
||||
return txt
|
||||
|
||||
def __len__(self):
|
||||
return self.tokenizer.get_vocab_size()
|
||||
|
||||
def get_number_tokens(self):
|
||||
return max(self.tokenizer.get_vocab().values()) + 1
|
||||
|
||||
|
||||
def test_expand_numbers_multilingual():
|
||||
test_cases = [
|
||||
# English
|
||||
("In 12.5 seconds.", "In twelve point five seconds.", "en"),
|
||||
("There were 50 soldiers.", "There were fifty soldiers.", "en"),
|
||||
("This is a 1st test", "This is a first test", "en"),
|
||||
("That will be $20 sir.", "That will be twenty dollars sir.", "en"),
|
||||
("That will be 20€ sir.", "That will be twenty euro sir.", "en"),
|
||||
("That will be 20.15€ sir.", "That will be twenty euro, fifteen cents sir.", "en"),
|
||||
("That's 100,000.5.", "That's one hundred thousand point five.", "en"),
|
||||
# French
|
||||
("En 12,5 secondes.", "En douze virgule cinq secondes.", "fr"),
|
||||
("Il y avait 50 soldats.", "Il y avait cinquante soldats.", "fr"),
|
||||
("Ceci est un 1er test", "Ceci est un premier test", "fr"),
|
||||
("Cela vous fera $20 monsieur.", "Cela vous fera vingt dollars monsieur.", "fr"),
|
||||
("Cela vous fera 20€ monsieur.", "Cela vous fera vingt euros monsieur.", "fr"),
|
||||
("Cela vous fera 20,15€ monsieur.", "Cela vous fera vingt euros et quinze centimes monsieur.", "fr"),
|
||||
("Ce sera 100.000,5.", "Ce sera cent mille virgule cinq.", "fr"),
|
||||
# German
|
||||
("In 12,5 Sekunden.", "In zwölf Komma fünf Sekunden.", "de"),
|
||||
("Es gab 50 Soldaten.", "Es gab fünfzig Soldaten.", "de"),
|
||||
("Dies ist ein 1. Test", "Dies ist ein erste Test", "de"), # Issue with gender
|
||||
("Das macht $20 Herr.", "Das macht zwanzig Dollar Herr.", "de"),
|
||||
("Das macht 20€ Herr.", "Das macht zwanzig Euro Herr.", "de"),
|
||||
("Das macht 20,15€ Herr.", "Das macht zwanzig Euro und fünfzehn Cent Herr.", "de"),
|
||||
# Spanish
|
||||
("En 12,5 segundos.", "En doce punto cinco segundos.", "es"),
|
||||
("Había 50 soldados.", "Había cincuenta soldados.", "es"),
|
||||
("Este es un 1er test", "Este es un primero test", "es"),
|
||||
("Eso le costará $20 señor.", "Eso le costará veinte dólares señor.", "es"),
|
||||
("Eso le costará 20€ señor.", "Eso le costará veinte euros señor.", "es"),
|
||||
("Eso le costará 20,15€ señor.", "Eso le costará veinte euros con quince céntimos señor.", "es"),
|
||||
# Italian
|
||||
("In 12,5 secondi.", "In dodici virgola cinque secondi.", "it"),
|
||||
("C'erano 50 soldati.", "C'erano cinquanta soldati.", "it"),
|
||||
("Questo è un 1° test", "Questo è un primo test", "it"),
|
||||
("Ti costerà $20 signore.", "Ti costerà venti dollari signore.", "it"),
|
||||
("Ti costerà 20€ signore.", "Ti costerà venti euro signore.", "it"),
|
||||
("Ti costerà 20,15€ signore.", "Ti costerà venti euro e quindici centesimi signore.", "it"),
|
||||
# Portuguese
|
||||
("Em 12,5 segundos.", "Em doze vírgula cinco segundos.", "pt"),
|
||||
("Havia 50 soldados.", "Havia cinquenta soldados.", "pt"),
|
||||
("Este é um 1º teste", "Este é um primeiro teste", "pt"),
|
||||
("Isso custará $20 senhor.", "Isso custará vinte dólares senhor.", "pt"),
|
||||
("Isso custará 20€ senhor.", "Isso custará vinte euros senhor.", "pt"),
|
||||
(
|
||||
"Isso custará 20,15€ senhor.",
|
||||
"Isso custará vinte euros e quinze cêntimos senhor.",
|
||||
"pt",
|
||||
), # "cêntimos" should be "centavos" num2words issue
|
||||
# Polish
|
||||
("W 12,5 sekundy.", "W dwanaście przecinek pięć sekundy.", "pl"),
|
||||
("Było 50 żołnierzy.", "Było pięćdziesiąt żołnierzy.", "pl"),
|
||||
("To będzie kosztować 20€ panie.", "To będzie kosztować dwadzieścia euro panie.", "pl"),
|
||||
("To będzie kosztować 20,15€ panie.", "To będzie kosztować dwadzieścia euro, piętnaście centów panie.", "pl"),
|
||||
# Arabic
|
||||
("في الـ 12,5 ثانية.", "في الـ اثنا عشر , خمسون ثانية.", "ar"),
|
||||
("كان هناك 50 جنديًا.", "كان هناك خمسون جنديًا.", "ar"),
|
||||
# ("ستكون النتيجة $20 يا سيد.", 'ستكون النتيجة عشرون دولار يا سيد.', 'ar'), # $ and € are mising from num2words
|
||||
# ("ستكون النتيجة 20€ يا سيد.", 'ستكون النتيجة عشرون يورو يا سيد.', 'ar'),
|
||||
# Czech
|
||||
("Za 12,5 vteřiny.", "Za dvanáct celá pět vteřiny.", "cs"),
|
||||
("Bylo tam 50 vojáků.", "Bylo tam padesát vojáků.", "cs"),
|
||||
("To bude stát 20€ pane.", "To bude stát dvacet euro pane.", "cs"),
|
||||
("To bude 20.15€ pane.", "To bude dvacet euro, patnáct centů pane.", "cs"),
|
||||
# Russian
|
||||
("Через 12.5 секунды.", "Через двенадцать запятая пять секунды.", "ru"),
|
||||
("Там было 50 солдат.", "Там было пятьдесят солдат.", "ru"),
|
||||
("Это будет 20.15€ сэр.", "Это будет двадцать евро, пятнадцать центов сэр.", "ru"),
|
||||
("Это будет стоить 20€ господин.", "Это будет стоить двадцать евро господин.", "ru"),
|
||||
# Dutch
|
||||
("In 12,5 seconden.", "In twaalf komma vijf seconden.", "nl"),
|
||||
("Er waren 50 soldaten.", "Er waren vijftig soldaten.", "nl"),
|
||||
("Dat wordt dan $20 meneer.", "Dat wordt dan twintig dollar meneer.", "nl"),
|
||||
("Dat wordt dan 20€ meneer.", "Dat wordt dan twintig euro meneer.", "nl"),
|
||||
# Chinese (Simplified)
|
||||
("在12.5秒内", "在十二点五秒内", "zh"),
|
||||
("有50名士兵", "有五十名士兵", "zh"),
|
||||
# ("那将是$20先生", '那将是二十美元先生', 'zh'), currency doesn't work
|
||||
# ("那将是20€先生", '那将是二十欧元先生', 'zh'),
|
||||
# Turkish
|
||||
# ("12,5 saniye içinde.", 'On iki virgül beş saniye içinde.', 'tr'), # decimal doesn't work for TR
|
||||
("50 asker vardı.", "elli asker vardı.", "tr"),
|
||||
("Bu 1. test", "Bu birinci test", "tr"),
|
||||
# ("Bu 100.000,5.", 'Bu yüz bin virgül beş.', 'tr'),
|
||||
# Hungarian
|
||||
("12,5 másodperc alatt.", "tizenkettő egész öt tized másodperc alatt.", "hu"),
|
||||
("50 katona volt.", "ötven katona volt.", "hu"),
|
||||
("Ez az 1. teszt", "Ez az első teszt", "hu"),
|
||||
# Korean
|
||||
("12.5 초 안에.", "십이 점 다섯 초 안에.", "ko"),
|
||||
("50 명의 병사가 있었다.", "오십 명의 병사가 있었다.", "ko"),
|
||||
("이것은 1 번째 테스트입니다", "이것은 첫 번째 테스트입니다", "ko"),
|
||||
]
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_numbers_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
def test_abbreviations_multilingual():
|
||||
test_cases = [
|
||||
# English
|
||||
("Hello Mr. Smith.", "Hello mister Smith.", "en"),
|
||||
("Dr. Jones is here.", "doctor Jones is here.", "en"),
|
||||
# Spanish
|
||||
("Hola Sr. Garcia.", "Hola señor Garcia.", "es"),
|
||||
("La Dra. Martinez es muy buena.", "La doctora Martinez es muy buena.", "es"),
|
||||
# French
|
||||
("Bonjour Mr. Dupond.", "Bonjour monsieur Dupond.", "fr"),
|
||||
("Mme. Moreau est absente aujourd'hui.", "madame Moreau est absente aujourd'hui.", "fr"),
|
||||
# German
|
||||
("Frau Dr. Müller ist sehr klug.", "Frau doktor Müller ist sehr klug.", "de"),
|
||||
# Portuguese
|
||||
("Olá Sr. Silva.", "Olá senhor Silva.", "pt"),
|
||||
("Dra. Costa, você está disponível?", "doutora Costa, você está disponível?", "pt"),
|
||||
# Italian
|
||||
("Buongiorno, Sig. Rossi.", "Buongiorno, signore Rossi.", "it"),
|
||||
# ("Sig.ra Bianchi, posso aiutarti?", 'signora Bianchi, posso aiutarti?', 'it'), # Issue with matching that pattern
|
||||
# Polish
|
||||
("Dzień dobry, P. Kowalski.", "Dzień dobry, pani Kowalski.", "pl"),
|
||||
("M. Nowak, czy mogę zadać pytanie?", "pan Nowak, czy mogę zadać pytanie?", "pl"),
|
||||
# Czech
|
||||
("P. Novák", "pan Novák", "cs"),
|
||||
("Dr. Vojtěch", "doktor Vojtěch", "cs"),
|
||||
# Dutch
|
||||
("Dhr. Jansen", "de heer Jansen", "nl"),
|
||||
("Mevr. de Vries", "mevrouw de Vries", "nl"),
|
||||
# Russian
|
||||
("Здравствуйте Г-н Иванов.", "Здравствуйте господин Иванов.", "ru"),
|
||||
("Д-р Смирнов здесь, чтобы увидеть вас.", "доктор Смирнов здесь, чтобы увидеть вас.", "ru"),
|
||||
# Turkish
|
||||
("Merhaba B. Yılmaz.", "Merhaba bay Yılmaz.", "tr"),
|
||||
("Dr. Ayşe burada.", "doktor Ayşe burada.", "tr"),
|
||||
# Hungarian
|
||||
("Dr. Szabó itt van.", "doktor Szabó itt van.", "hu"),
|
||||
]
|
||||
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_abbreviations_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
def test_symbols_multilingual():
|
||||
test_cases = [
|
||||
("I have 14% battery", "I have 14 percent battery", "en"),
|
||||
("Te veo @ la fiesta", "Te veo arroba la fiesta", "es"),
|
||||
("J'ai 14° de fièvre", "J'ai 14 degrés de fièvre", "fr"),
|
||||
("Die Rechnung beträgt £ 20", "Die Rechnung beträgt pfund 20", "de"),
|
||||
("O meu email é ana&joao@gmail.com", "O meu email é ana e joao arroba gmail.com", "pt"),
|
||||
("linguaggio di programmazione C#", "linguaggio di programmazione C cancelletto", "it"),
|
||||
("Moja temperatura to 36.6°", "Moja temperatura to 36.6 stopnie", "pl"),
|
||||
("Mám 14% baterie", "Mám 14 procento baterie", "cs"),
|
||||
("Těším se na tebe @ party", "Těším se na tebe na party", "cs"),
|
||||
("У меня 14% заряда", "У меня 14 процентов заряда", "ru"),
|
||||
("Я буду @ дома", "Я буду собака дома", "ru"),
|
||||
("Ik heb 14% batterij", "Ik heb 14 procent batterij", "nl"),
|
||||
("Ik zie je @ het feest", "Ik zie je bij het feest", "nl"),
|
||||
("لدي 14% في البطارية", "لدي 14 في المئة في البطارية", "ar"),
|
||||
("我的电量为 14%", "我的电量为 14 百分之", "zh"),
|
||||
("Pilim %14 dolu.", "Pilim yüzde 14 dolu.", "tr"),
|
||||
("Az akkumulátorom töltöttsége 14%", "Az akkumulátorom töltöttsége 14 százalék", "hu"),
|
||||
("배터리 잔량이 14%입니다.", "배터리 잔량이 14 퍼센트입니다.", "ko"),
|
||||
]
|
||||
|
||||
for a, b, lang in test_cases:
|
||||
out = expand_symbols_multilingual(a, lang=lang)
|
||||
assert out == b, f"'{out}' vs '{b}'"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_expand_numbers_multilingual()
|
||||
test_abbreviations_multilingual()
|
||||
test_symbols_multilingual()
|
||||
@@ -1,179 +0,0 @@
|
||||
export interface CrunkerConstructorOptions {
|
||||
/**
|
||||
* Sample rate for Crunker's internal audio context.
|
||||
*
|
||||
* @default 44100
|
||||
*/
|
||||
sampleRate: number;
|
||||
}
|
||||
export type CrunkerInputTypes = string | File | Blob;
|
||||
/**
|
||||
* An exported Crunker audio object.
|
||||
*/
|
||||
export interface ExportedCrunkerAudio {
|
||||
blob: Blob;
|
||||
url: string;
|
||||
element: HTMLAudioElement;
|
||||
}
|
||||
/**
|
||||
* Crunker is the simple way to merge, concatenate, play, export and download audio files using the Web Audio API.
|
||||
*/
|
||||
export default class Crunker {
|
||||
private readonly _sampleRate;
|
||||
private readonly _context;
|
||||
/**
|
||||
* Creates a new instance of Crunker with the provided options.
|
||||
*
|
||||
* If `sampleRate` is not defined, it will auto-select an appropriate sample rate
|
||||
* for the device being used.
|
||||
*/
|
||||
constructor({ sampleRate }?: Partial<CrunkerConstructorOptions>);
|
||||
/**
|
||||
* Creates Crunker's internal AudioContext.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _createContext;
|
||||
/**
|
||||
*
|
||||
* The internal AudioContext used by Crunker.
|
||||
*/
|
||||
get context(): AudioContext;
|
||||
/**
|
||||
* Asynchronously fetches multiple audio files and returns an array of AudioBuffers.
|
||||
*/
|
||||
fetchAudio(...filepaths: CrunkerInputTypes[]): Promise<AudioBuffer[]>;
|
||||
/**
|
||||
* Merges (layers) multiple AudioBuffers into a single AudioBuffer.
|
||||
*
|
||||
* **Visual representation:**
|
||||
*
|
||||
* 
|
||||
*/
|
||||
mergeAudio(buffers: AudioBuffer[]): AudioBuffer;
|
||||
/**
|
||||
* Concatenates multiple AudioBuffers into a single AudioBuffer.
|
||||
*
|
||||
* **Visual representation:**
|
||||
*
|
||||
* 
|
||||
*/
|
||||
concatAudio(buffers: AudioBuffer[]): AudioBuffer;
|
||||
/**
|
||||
* Pads a specified AudioBuffer with silence from a specified start time,
|
||||
* for a specified length of time.
|
||||
*
|
||||
* Accepts float values as well as whole integers.
|
||||
*
|
||||
* @param buffer AudioBuffer to pad
|
||||
* @param padStart Time to start padding (in seconds)
|
||||
* @param seconds Duration to pad for (in seconds)
|
||||
*/
|
||||
padAudio(buffer: AudioBuffer, padStart?: number, seconds?: number): AudioBuffer;
|
||||
/**
|
||||
* Slices an AudioBuffer from the specified start time to the end time, with optional fade in and out.
|
||||
*
|
||||
* @param buffer AudioBuffer to slice
|
||||
* @param start Start time (in seconds)
|
||||
* @param end End time (in seconds)
|
||||
* @param fadeIn Fade in duration (in seconds, default is 0)
|
||||
* @param fadeOut Fade out duration (in seconds, default is 0)
|
||||
*/
|
||||
sliceAudio(buffer: AudioBuffer, start: number, end: number, fadeIn?: number, fadeOut?: number): AudioBuffer;
|
||||
/**
|
||||
* Plays the provided AudioBuffer in an AudioBufferSourceNode.
|
||||
*/
|
||||
play(buffer: AudioBuffer): AudioBufferSourceNode;
|
||||
/**
|
||||
* Exports the specified AudioBuffer to a Blob, Object URI and HTMLAudioElement.
|
||||
*
|
||||
* Note that changing the MIME type does not change the actual file format. The
|
||||
* file format will **always** be a WAVE file due to how audio is stored in the
|
||||
* browser.
|
||||
*
|
||||
* @param buffer Buffer to export
|
||||
* @param type MIME type (default: `audio/wav`)
|
||||
*/
|
||||
export(buffer: AudioBuffer, type?: string): ExportedCrunkerAudio;
|
||||
/**
|
||||
* Downloads the provided Blob.
|
||||
*
|
||||
* @param blob Blob to download
|
||||
* @param filename An optional file name to use for the download (default: `crunker`)
|
||||
*/
|
||||
download(blob: Blob, filename?: string): HTMLAnchorElement;
|
||||
/**
|
||||
* Executes a callback if the browser does not support the Web Audio API.
|
||||
*
|
||||
* Returns the result of the callback, or `undefined` if the Web Audio API is supported.
|
||||
*
|
||||
* @param callback callback to run if the browser does not support the Web Audio API
|
||||
*/
|
||||
notSupported<T>(callback: () => T): T | undefined;
|
||||
/**
|
||||
* Closes Crunker's internal AudioContext.
|
||||
*/
|
||||
close(): this;
|
||||
/**
|
||||
* Returns the largest duration of the longest AudioBuffer.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _maxDuration;
|
||||
/**
|
||||
* Returns the largest number of channels in an array of AudioBuffers.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _maxNumberOfChannels;
|
||||
/**
|
||||
* Returns the sum of the lengths of an array of AudioBuffers.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _totalLength;
|
||||
/**
|
||||
* Returns whether the browser supports the Web Audio API.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _isSupported;
|
||||
/**
|
||||
* Writes the WAV headers for the specified Float32Array.
|
||||
*
|
||||
* Returns a DataView containing the WAV headers and file content.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _writeHeaders;
|
||||
/**
|
||||
* Converts a Float32Array to 16-bit PCM.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _floatTo16BitPCM;
|
||||
/**
|
||||
* Writes a string to a DataView at the specified offset.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _writeString;
|
||||
/**
|
||||
* Converts an AudioBuffer to a Float32Array.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _interleave;
|
||||
/**
|
||||
* Creates an HTMLAudioElement whose source is the specified Blob.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _renderAudioElement;
|
||||
/**
|
||||
* Creates an Object URL for the specified Blob.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
private _renderURL;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function r(e){return function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return a(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return a(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,(o=a.key,i=void 0,i=function(e,t){if("object"!==n(e)||null===e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var a=r.call(e,t||"default");if("object"!==n(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(o,"string"),"symbol"===n(i)?i:String(i)),a)}var o,i}e.d(t,{Z:()=>u});var u=function(){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.sampleRate;o(this,e),this._context=this._createContext(n),n||(n=this._context.sampleRate),this._sampleRate=n}var t,n,a;return t=e,n=[{key:"_createContext",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:44100;return window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext,new AudioContext({sampleRate:e})}},{key:"context",get:function(){return this._context}},{key:"fetchAudio",value:async function(){for(var e=this,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return await Promise.all(n.map((async function(t){var n;return n=t instanceof File||t instanceof Blob?await t.arrayBuffer():await fetch(t).then((function(e){return e.headers.has("Content-Type")&&!e.headers.get("Content-Type").includes("audio/")&&console.warn("Crunker: Attempted to fetch an audio file, but its MIME type is `".concat(e.headers.get("Content-Type").split(";")[0],"`. We'll try and continue anyway. (file: \"").concat(t,'")')),e.arrayBuffer()})),await e._context.decodeAudioData(n)})))}},{key:"mergeAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._sampleRate*this._maxDuration(e),this._sampleRate);return e.forEach((function(e){for(var n=0;n<e.numberOfChannels;n++){for(var r=t.getChannelData(n),a=e.getChannelData(n),o=e.getChannelData(n).length-1;o>=0;o--)r[o]+=a[o];t.getChannelData(n).set(r)}})),t}},{key:"concatAudio",value:function(e){var t=this._context.createBuffer(this._maxNumberOfChannels(e),this._totalLength(e),this._sampleRate),n=0;return e.forEach((function(e){for(var r=0;r<e.numberOfChannels;r++)t.getChannelData(r).set(e.getChannelData(r),n);n+=e.length})),t}},{key:"padAudio",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;if(0===n)return e;if(t<0)throw new Error('Crunker: Parameter "padStart" in padAudio must be positive');if(n<0)throw new Error('Crunker: Parameter "seconds" in padAudio must be positive');for(var r=this._context.createBuffer(e.numberOfChannels,Math.ceil(e.length+n*e.sampleRate),e.sampleRate),a=0;a<e.numberOfChannels;a++){var o=e.getChannelData(a);r.getChannelData(a).set(o.subarray(0,Math.ceil(t*e.sampleRate)+1),0),r.getChannelData(a).set(o.subarray(Math.ceil(t*e.sampleRate)+2,r.length+1),Math.ceil((t+n)*e.sampleRate))}return r}},{key:"sliceAudio",value:function(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0;if(t>=n)throw new Error('Crunker: "start" time should be less than "end" time in sliceAudio method');for(var o=Math.round((n-t)*this._sampleRate),i=Math.round(t*this._sampleRate),u=this._context.createBuffer(e.numberOfChannels,o,this._sampleRate),l=0;l<e.numberOfChannels;l++)for(var s=e.getChannelData(l),c=u.getChannelData(l),f=0;f<o;f++)c[f]=s[i+f],f<r*this._sampleRate&&(c[f]*=f/(r*this._sampleRate)),f>o-a*this._sampleRate&&(c[f]*=(o-f)/(a*this._sampleRate));return u}},{key:"play",value:function(e){var t=this._context.createBufferSource();return t.buffer=e,t.connect(this._context.destination),t.start(),Line truncated
|
||||
//# sourceMappingURL=crunker.esm.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"crunker.esm.js","mappings":"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 truncated
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,4 +0,0 @@
|
||||
/*! howler.js v2.2.4 | (c) 2013-2020, James Simpson of GoldFire Studios | MIT License | howlerjs.com */
|
||||
!function(){"use strict";var e=function(){this.init()};e.prototype={init:function(){var e=this||n;return e._counter=1e3,e._html5AudioPool=[],e.html5PoolSize=10,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent="canplaythrough",e._navigator="undefined"!=typeof window&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.autoUnlock=!0,e._setup(),e},volume:function(e){var o=this||n;if(e=parseFloat(e),o.ctx||_(),void 0!==e&&e>=0&&e<=1){if(o._volume=e,o._muted)return o;o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e,n.ctx.currentTime);for(var t=0;t<o._howls.length;t++)if(!o._howls[t]._webAudio)for(var r=o._howls[t]._getSoundIds(),a=0;a<r.length;a++){var u=o._howls[t]._soundById(r[a]);u&&u._node&&(u._node.volume=u._volume*e)}return o}return o._volume},mute:function(e){var o=this||n;o.ctx||_(),o._muted=e,o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e?0:o._volume,n.ctx.currentTime);for(var t=0;t<o._howls.length;t++)if(!o._howls[t]._webAudio)for(var r=o._howls[t]._getSoundIds(),a=0;a<r.length;a++){var u=o._howls[t]._soundById(r[a]);u&&u._node&&(u._node.muted=!!e||u._muted)}return o},stop:function(){for(var e=this||n,o=0;o<e._howls.length;o++)e._howls[o].stop();return e},unload:function(){for(var e=this||n,o=e._howls.length-1;o>=0;o--)e._howls[o].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,_()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,"")]},_setup:function(){var e=this||n;if(e.state=e.ctx?e.ctx.state||"suspended":"suspended",e._autoSuspend(),!e.usingWebAudio)if("undefined"!=typeof Audio)try{var o=new Audio;void 0===o.oncanplaythrough&&(e._canPlayEvent="canplay")}catch(n){e.noAudio=!0}else e.noAudio=!0;try{var o=new Audio;o.muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,o=null;try{o="undefined"!=typeof Audio?new Audio:null}catch(n){return e}if(!o||"function"!=typeof o.canPlayType)return e;var t=o.canPlayType("audio/mpeg;").replace(/^no$/,""),r=e._navigator?e._navigator.userAgent:"",a=r.match(/OPR\/(\d+)/g),u=a&&parseInt(a[0].split("/")[1],10)<33,d=-1!==r.indexOf("Safari")&&-1===r.indexOf("Chrome"),i=r.match(/Version\/(.*?) /),_=d&&i&&parseInt(i[1],10)<15;return e._codecs={mp3:!(u||!t&&!o.canPlayType("audio/mp3;").replace(/^no$/,"")),mpeg:!!t,opus:!!o.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!(o.canPlayType('audio/wav; codecs="1"')||o.canPlayType("audio/wav")).replace(/^no$/,""),aac:!!o.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!o.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(o.canPlayType("audio/x-m4a;")||o.canPlayType("audio/m4a;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),m4b:!!(o.canPlayType("audio/x-m4b;")||o.canPlayType("audio/m4b;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(o.canPlayType("audio/x-mp4;")||o.canPlayType("audio/mp4;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),webm:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),dolby:!!o.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(o.canPlayType("audio/x-flac;")||o.canPlayType("audio/flac;")).replace(/^no$/,"")},e},_unlockAudio:function(){var e=this||n;if(!e._audioUnlocked&&e.ctx){e._audioUnlocked=!1,e.autoUnlock=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var o=function(n){for(;e._html5AudioPool.length<e.html5PoolSize;)try{var t=new Audio;t._unlocked=!0,e._releaseHtml5Audio(t)}catch(n){e.noAudio=!0;break}for(var r=0;r<e._howls.length;r++)if(!e._howls[r]._webAudio)for(var a=e._howls[r]._getSoundIds(),u=0;u<a.length;u++){var d=e._howls[r]._soundById(a[u]);d&&d._node&&!d._node._unlocked&&(d._node._unlocked=!0,d._node.load())}e._autoResume();var i=e.ctx.createBufferSource();i.buffer=e._scratchBuffer,i.connect(e.ctx.destination),void 0===i.start?i.noteOn(0):i.start(0),"function"==typeof e.ctx.resume&&e.ctx.resume(),i.onended=function(){i.disconnect(0),e._audioUnlocked=!0,document.removeEventListener("touchstart",o,!0),document.removeEventListener("touchend",o,!0),document.removeEventListener("click",o,!0),document.removeEventListener("keydown",o,!0);for(var n=0;n<e._howls.length;n++)e._howls[n]._emit("unlock")}};return document.addEventListener("touchstart",o,!0),document.addEventListener("touchend",o,!0),document.addEventListener("click",o,!0),document.addEventListener("keydown",o,!0),e}},_obtainHtml5Audio:function(){var e=this||n;if(e._html5AudioPool.length)return e._html5AudioPool.pop();var o=(new Audio).play();return o&&"undefined"!=typeof Promise&&(o instanceof Promise||"function"==typeof o.then)&&o.catch(function(){console.warn("HTML5 Audio pool eLine truncated
|
||||
/*! Spatial Plugin */
|
||||
!function(){"use strict";HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){var n=this;if(!n.ctx||!n.ctx.listener)return n;for(var t=n._howls.length-1;t>=0;t--)n._howls[t].stereo(e);return n},HowlerGlobal.prototype.pos=function(e,n,t){var r=this;return r.ctx&&r.ctx.listener?(n="number"!=typeof n?r._pos[1]:n,t="number"!=typeof t?r._pos[2]:t,"number"!=typeof e?r._pos:(r._pos=[e,n,t],void 0!==r.ctx.listener.positionX?(r.ctx.listener.positionX.setTargetAtTime(r._pos[0],Howler.ctx.currentTime,.1),r.ctx.listener.positionY.setTargetAtTime(r._pos[1],Howler.ctx.currentTime,.1),r.ctx.listener.positionZ.setTargetAtTime(r._pos[2],Howler.ctx.currentTime,.1)):r.ctx.listener.setPosition(r._pos[0],r._pos[1],r._pos[2]),r)):r},HowlerGlobal.prototype.orientation=function(e,n,t,r,o,i){var a=this;if(!a.ctx||!a.ctx.listener)return a;var p=a._orientation;return n="number"!=typeof n?p[1]:n,t="number"!=typeof t?p[2]:t,r="number"!=typeof r?p[3]:r,o="number"!=typeof o?p[4]:o,i="number"!=typeof i?p[5]:i,"number"!=typeof e?p:(a._orientation=[e,n,t,r,o,i],void 0!==a.ctx.listener.forwardX?(a.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),a.ctx.listener.forwardY.setTargetAtTime(n,Howler.ctx.currentTime,.1),a.ctx.listener.forwardZ.setTargetAtTime(t,Howler.ctx.currentTime,.1),a.ctx.listener.upX.setTargetAtTime(r,Howler.ctx.currentTime,.1),a.ctx.listener.upY.setTargetAtTime(o,Howler.ctx.currentTime,.1),a.ctx.listener.upZ.setTargetAtTime(i,Howler.ctx.currentTime,.1)):a.ctx.listener.setOrientation(e,n,t,r,o,i),a)},Howl.prototype.init=function(e){return function(n){var t=this;return t._orientation=n.orientation||[1,0,0],t._stereo=n.stereo||null,t._pos=n.pos||null,t._pannerAttr={coneInnerAngle:void 0!==n.coneInnerAngle?n.coneInnerAngle:360,coneOuterAngle:void 0!==n.coneOuterAngle?n.coneOuterAngle:360,coneOuterGain:void 0!==n.coneOuterGain?n.coneOuterGain:0,distanceModel:void 0!==n.distanceModel?n.distanceModel:"inverse",maxDistance:void 0!==n.maxDistance?n.maxDistance:1e4,panningModel:void 0!==n.panningModel?n.panningModel:"HRTF",refDistance:void 0!==n.refDistance?n.refDistance:1,rolloffFactor:void 0!==n.rolloffFactor?n.rolloffFactor:1},t._onstereo=n.onstereo?[{fn:n.onstereo}]:[],t._onpos=n.onpos?[{fn:n.onpos}]:[],t._onorientation=n.onorientation?[{fn:n.onorientation}]:[],e.call(this,n)}}(Howl.prototype.init),Howl.prototype.stereo=function(n,t){var r=this;if(!r._webAudio)return r;if("loaded"!==r._state)return r._queue.push({event:"stereo",action:function(){r.stereo(n,t)}}),r;var o=void 0===Howler.ctx.createStereoPanner?"spatial":"stereo";if(void 0===t){if("number"!=typeof n)return r._stereo;r._stereo=n,r._pos=[n,0,0]}for(var i=r._getSoundIds(t),a=0;a<i.length;a++){var p=r._soundById(i[a]);if(p){if("number"!=typeof n)return p._stereo;p._stereo=n,p._pos=[n,0,0],p._node&&(p._pannerAttr.panningModel="equalpower",p._panner&&p._panner.pan||e(p,o),"spatial"===o?void 0!==p._panner.positionX?(p._panner.positionX.setValueAtTime(n,Howler.ctx.currentTime),p._panner.positionY.setValueAtTime(0,Howler.ctx.currentTime),p._panner.positionZ.setValueAtTime(0,Howler.ctx.currentTime)):p._panner.setPosition(n,0,0):p._panner.pan.setValueAtTime(n,Howler.ctx.currentTime)),r._emit("stereo",p._id)}}return r},Howl.prototype.pos=function(n,t,r,o){var i=this;if(!i._webAudio)return i;if("loaded"!==i._state)return i._queue.push({event:"pos",action:function(){i.pos(n,t,r,o)}}),i;if(t="number"!=typeof t?0:t,r="number"!=typeof r?-.5:r,void 0===o){if("number"!=typeof n)return i._pos;i._pos=[n,t,r]}for(var a=i._getSoundIds(o),p=0;p<a.length;p++){var s=i._soundById(a[p]);if(s){if("number"!=typeof n)return s._pos;s._pos=[n,t,r],s._node&&(s._panner&&!s._panner.pan||e(s,"spatial"),void 0!==s._panner.positionX?(s._panner.positionX.setValueAtTime(n,Howler.ctx.currentTime),s._panner.positionY.setValueAtTime(t,Howler.ctx.currentTime),s._panner.positionZ.setValueAtTime(r,Howler.ctx.currentTime)):s._panner.setPosition(n,t,r)),i._emit("pos",s._id)}}return i},Howl.prototype.orientation=function(n,t,r,o){var i=this;if(!i._webAudio)return i;if("loaded"!==i._state)return i._queue.push({event:"orientation",action:function(){i.orientation(n,t,r,o)}}),i;if(t="number"!=typeof t?i._orientation[1]:t,r="number"!=typeof r?i._orientation[2]:r,void 0===o){if("number"!=typeof n)return i._orientation;i._orientation=[n,t,r]}for(var a=i._getSoundIds(o),p=0;p<a.length;p++){var s=i._soundById(a[p]);if(s){if("number"!=typeof n)return s._orientation;s._orientation=[n,t,r],s._node&&(s._panner||(s._pos||(s._pos=i._pos||[0,0,-.5]),e(s,"spatial")),void 0!==s._panner.orientationX?(s._panner.orientationX.setValueAtTime(n,Howler.ctx.currentTime),s._panner.orientationY.setValueAtTime(t,Howler.ctx.currentTime),s._panner.orientationZ.setValueAtTime(r,Howler.ctx.currentTime)):s._panner.setOrientation(n,t,r)),i._emit("orientation",s._id)}}return i},Howl.prototype.pannerAttr=function(){var n,t,r,o=this,i=arguments;if(!o._webAudioLine truncated
|
||||
@@ -1,33 +0,0 @@
|
||||
USAGE NOTES
|
||||
Separate Execution: Run this script independently in its own command prompt or terminal window, separate from AllTalk's operational environment.
|
||||
|
||||
JSON File Requirement: After TTS generation, export your list as ttsList.json and ensure it is located in the same directory as ttsgencomp.py.
|
||||
|
||||
Iterative Process: Should you need to regenerate TTS for any flagged IDs, repeat the export and script execution process with your updated JSON list.
|
||||
|
||||
CUDA Dependency: Similar to AllTalk's finetuning, this script requires access to cublas64_11. Ensure your system meets the necessary requirements.
|
||||
https://github.com/erew123/alltalk_tts/tree/main?#-important-requirements-cuda-118
|
||||
|
||||
INSTRUCTIONS:
|
||||
1) Ensure your active the Python environment that AllTalk runs in & Ensure you have the CUDA dependency set up (link above)
|
||||
|
||||
2) Install the required packages using pip:
|
||||
|
||||
pip install faster-whisper fuzzywuzzy spacy levenshtein
|
||||
|
||||
3) Download the language model en_core_web_md for Spacy:
|
||||
|
||||
python -m spacy download en_core_web_md
|
||||
|
||||
4) Generate your TTS in the TTS Generator and export the ttsList.JSON to .../alltalk_tts/templates/ttsgencomp/
|
||||
|
||||
5) Ensure you're in the directory where ttsgencomp.py is located (Replace /path/to/ with the actual path to the .../alltalk_tts/templates/ttsgencomp/ directory):
|
||||
|
||||
cd /path/to/alltalk_tts/templates/ttsgencomp/
|
||||
|
||||
6) Run the script using Python:
|
||||
|
||||
python ttsgencomp.py
|
||||
|
||||
7) Follow any on screen instructions.
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
import json
|
||||
import requests
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
# version 0.1
|
||||
|
||||
# Set up argument parsing
|
||||
parser = argparse.ArgumentParser(description="Compare TTS output with the original text using detailed comparison.")
|
||||
parser.add_argument("--threshold", type=int, default=98, help="Similarity threshold for considering a match (default: 98)")
|
||||
args = parser.parse_args()
|
||||
|
||||
def disclaimer_text():
|
||||
print(f"\nDISCLAIMER:")
|
||||
print(f" \033[92mThis is a work in progress, aka a BETA test at best. It is not refined or production ready,")
|
||||
print(f" just a proof of concept and should therefore be viewed and used as such.")
|
||||
print(f"\n There is no support on this while its in BETA.\033[0m")
|
||||
print(f"\nDESCRIPTION: ")
|
||||
print(f" This script is designed to assist in identifying bad TTS generation ID's from the TTS Generator.\n")
|
||||
print(f" This will download the Whisper Large-v2 model (if not already downloaded), and use it to compare your text to")
|
||||
print(f" to the generated TTS. If it finds an issue, it will flag the ID number that has the issue. This does NOT 100%")
|
||||
print(f" ensure that all TTS generated is perfect, sounds good etc, but it should flag up glaring issues and help with")
|
||||
print(f" the process of identifying bad TTS generations.")
|
||||
print(f"\nNOTES ON USE: ")
|
||||
print(f" - Ensure AllTalk is running in its own command prompt/terminal.")
|
||||
print(f" - This script should be running in its own command prompt/terminal window in the same Python Environment that")
|
||||
print(f" AllTalk is running in.")
|
||||
print(f" - After generating your text in the TTS Generator, you need to `Export List to JSON` and save the file in the")
|
||||
print(f" same folder/directory this script is running from.")
|
||||
print(f" - You can use `--threshold` with a numerical value from 1 to 100 to set accuracy detection. For example it may")
|
||||
print(f" detect/transcribe `their` as `there`, which of course, both words sound the same. If you want 100% accuracy")
|
||||
print(f" you will set 100 as the threshold. You will more than likely want a number in the high 90's. Default is set")
|
||||
print(f" at 98, which gives a little flexibility.")
|
||||
print(f" - The JSON file must be named \033[93mttsList.json\033[0m")
|
||||
print(f" - When you have your ID list, go back into the TTS Generator, correct any lines and regenerate them. If you")
|
||||
print(f" want to re-test everthing again after re-generating, you will need to export your list again and re-run this")
|
||||
print(f" script again, against your newly exported JSON list.")
|
||||
print(f" - This requires access to \033[93mcublas64_11\033[0m, the same as Finetuning.")
|
||||
print(f" https://github.com/erew123/alltalk_tts/tree/main?#-important-requirements-cuda-118")
|
||||
return
|
||||
|
||||
try:
|
||||
from faster_whisper import WhisperModel
|
||||
import re
|
||||
import string
|
||||
import spacy
|
||||
import torch
|
||||
from fuzzywuzzy import fuzz
|
||||
except ImportError as e:
|
||||
disclaimer_text()
|
||||
print(f"\nERROR STARTING SCRIPT:")
|
||||
print(" An error occurred importing one or more required libraries.")
|
||||
print(" Please ensure you have \033[94mactivated your Python environment \033[0mand \033[94minstalled all requirements.\033[0m")
|
||||
print("\n \033[94mMissing library:\033[93m", str(e), "\033[0m")
|
||||
exit(1)
|
||||
|
||||
# Attempt to load the spaCy model
|
||||
try:
|
||||
# Load a medium-sized spaCy model, adjust to "en_core_web_md" or "en_core_web_lg" as needed
|
||||
nlp = spacy.load("en_core_web_md")
|
||||
except Exception as e:
|
||||
disclaimer_text()
|
||||
print(f"\nERROR STARTING SCRIPT:")
|
||||
print(" Failed to load the spaCy language model.")
|
||||
print(" Please ensure the spaCy language model is installed by running:")
|
||||
print(" \033[93mpython -m spacy download en_core_web_md\033[0m")
|
||||
exit(1)
|
||||
|
||||
def texts_are_similar(text1, text2, threshold=0.8):
|
||||
# Preliminary check for short texts
|
||||
if len(text1) < 10 or len(text2) < 10:
|
||||
ratio = fuzz.ratio(text1, text2) / 100.0 # Use FuzzyWuzzy for short texts
|
||||
return ratio > threshold
|
||||
|
||||
# Process the texts through the NLP model for longer texts
|
||||
doc1 = nlp(text1)
|
||||
doc2 = nlp(text2)
|
||||
|
||||
# Compute semantic similarity
|
||||
similarity = doc1.similarity(doc2)
|
||||
|
||||
return similarity >= threshold
|
||||
|
||||
def download_file(url, destination):
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
with open(destination, 'wb') as f:
|
||||
f.write(response.content)
|
||||
|
||||
def normalize_text(text):
|
||||
# Normalize or remove CRLF and other non-standard whitespaces
|
||||
text = text.replace("\r\n", " ").replace("\n", " ").replace("\r", " ")
|
||||
|
||||
# Convert to lowercase
|
||||
text = text.lower()
|
||||
|
||||
# Standardize and then remove quotation marks
|
||||
text = text.replace("“", '"').replace("”", '"').replace("‘", "'").replace("’", "'")
|
||||
text = text.translate(str.maketrans('', '', '"\''))
|
||||
|
||||
# Remove all other punctuation except hyphens to preserve compound words
|
||||
text = text.translate(str.maketrans('', '', string.punctuation.replace("-", "")))
|
||||
|
||||
# Collapse any sequence of whitespace (including spaces) into a single space
|
||||
text = re.sub(r'\s+', ' ', text)
|
||||
|
||||
return text.strip()
|
||||
|
||||
spoken_punctuation_mapping = {
|
||||
"dot": ".",
|
||||
"comma": ",",
|
||||
# Add more mappings as needed
|
||||
}
|
||||
|
||||
def contains_spoken_punctuation(transcribed_text):
|
||||
for spoken, punctuation in spoken_punctuation_mapping.items():
|
||||
if spoken in transcribed_text:
|
||||
return True
|
||||
return False
|
||||
|
||||
def detailed_comparison(original_text, transcribed_text, threshold=98):
|
||||
original_clean = normalize_text(original_text)
|
||||
transcribed_clean = normalize_text(transcribed_text)
|
||||
ratio = fuzz.ratio(original_clean, transcribed_clean)
|
||||
return ratio > threshold
|
||||
|
||||
def transcribe_and_compare(file_url, original_text, model, item_id, flagged_ids):
|
||||
audio_file = Path(file_url.split('/')[-1])
|
||||
download_file(file_url, audio_file)
|
||||
|
||||
segments, info = model.transcribe(str(audio_file), beam_size=5)
|
||||
transcribed_text = " ".join([segment.text for segment in segments])
|
||||
|
||||
# Normalize texts for comparison
|
||||
original_text_normalized = normalize_text(original_text)
|
||||
transcribed_text_normalized = normalize_text(transcribed_text)
|
||||
|
||||
# Enhanced comparison using detailed fuzzy matching
|
||||
is_detailed_match = detailed_comparison(original_text_normalized, transcribed_text_normalized, args.threshold)
|
||||
has_spoken_punctuation = contains_spoken_punctuation(transcribed_text_normalized) and not contains_spoken_punctuation(original_text_normalized)
|
||||
|
||||
# Adjust is_match based on detailed comparison and spoken punctuation check
|
||||
is_match = is_detailed_match and not has_spoken_punctuation
|
||||
|
||||
# Only log and flag IDs for review if there's a mismatch or detected issues
|
||||
if not is_match:
|
||||
#print(f"\033[93mMismatch Detected - ID:\033[0m {item_id}")
|
||||
print(f"\033[93mOriginal :\033[0m {original_text}")
|
||||
print(f"\033[91mTranscribed:\033[0m{transcribed_text}")
|
||||
if has_spoken_punctuation:
|
||||
print(f"Note: Potential incorrect spoken punctuation detected.")
|
||||
flagged_ids.append(item_id) # Track the ID for review
|
||||
|
||||
audio_file.unlink() # Remove the downloaded file after processing
|
||||
|
||||
def main():
|
||||
model_size = "large-v3"
|
||||
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||
disclaimer_text()
|
||||
model = WhisperModel(model_size, device=device, compute_type="float32")
|
||||
|
||||
flagged_ids = [] # Initialize the list to track IDs needing review
|
||||
|
||||
try:
|
||||
with open("ttsList.json", "r", encoding="utf-8") as f:
|
||||
tts_list = json.load(f)
|
||||
except FileNotFoundError:
|
||||
print(f"\nERROR STARTING SCRIPT:")
|
||||
print(" Error: \033[93mttsList.json\033[0m file not found.")
|
||||
print("\n Please ensure you follow these steps:")
|
||||
print(" - After generating your text in the TTS Generator, you need to `Export List to JSON` and save the file in the")
|
||||
print(" same folder/directory this script is running from.")
|
||||
print(" - The JSON file must be named \033[93mttsList.json\033[0m")
|
||||
exit(1)
|
||||
|
||||
print(f"\nPROCESSING LIST:\n")
|
||||
|
||||
for item in tts_list:
|
||||
print(f"Processing ID: {item['id']}")
|
||||
transcribe_and_compare(item['fileUrl'], item['text'], model, item['id'], flagged_ids)
|
||||
|
||||
# Print summary information at the end
|
||||
if flagged_ids:
|
||||
print(f"\n For ID's shown, in the TTS Generator, review and correct any lines by editing & regenerating them. If you")
|
||||
print(f" want to re-test everthing again after re-generating, you will need to export the JSON list again and re-run")
|
||||
print(f" the script again, against the newly exported JSON list.")
|
||||
print("\nSUMMARY: IDs needing review:", ', '.join(map(str, flagged_ids)))
|
||||
else:
|
||||
print("\nSUMMARY: No issues detected.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,2 +0,0 @@
|
||||
/*! For license information please see 1995fcd6d39cade7d871.js.LICENSE.txt */
|
||||
function _typeof(t){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_typeof(t)}function _regeneratorRuntime(){"use strict";_regeneratorRuntime=function(){return e};var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",u=i.toStringTag||"@@toStringTag";function l(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{l({},"")}catch(t){l=function(t,e,r){return t[e]=r}}function f(t,e,r,n){var i=e&&e.prototype instanceof m?e:m,a=Object.create(i.prototype),c=new G(n||[]);return o(a,"_invoke",{value:S(t,r,c)}),a}function s(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=f;var h="suspendedStart",p="suspendedYield",y="executing",d="completed",v={};function m(){}function g(){}function w(){}var x={};l(x,a,(function(){return this}));var E=Object.getPrototypeOf,b=E&&E(E(B([])));b&&b!==r&&n.call(b,a)&&(x=b);var T=w.prototype=m.prototype=Object.create(x);function _(t){["next","throw","return"].forEach((function(e){l(t,e,(function(t){return this._invoke(e,t)}))}))}function L(t,e){function r(o,i,a,c){var u=s(t[o],t,i);if("throw"!==u.type){var l=u.arg,f=l.value;return f&&"object"==_typeof(f)&&n.call(f,"__await")?e.resolve(f.__await).then((function(t){r("next",t,a,c)}),(function(t){r("throw",t,a,c)})):e.resolve(f).then((function(t){l.value=t,a(l)}),(function(t){return r("throw",t,a,c)}))}c(u.arg)}var i;o(this,"_invoke",{value:function(t,n){function o(){return new e((function(e,o){r(t,n,e,o)}))}return i=i?i.then(o,o):o()}})}function S(e,r,n){var o=h;return function(i,a){if(o===y)throw new Error("Generator is already running");if(o===d){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var u=I(c,n);if(u){if(u===v)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===h)throw o=d,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=y;var l=s(e,r,n);if("normal"===l.type){if(o=n.done?d:p,l.arg===v)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(o=d,n.method="throw",n.arg=l.arg)}}}function I(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator.return&&(r.method="return",r.arg=t,I(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),v;var i=s(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,v;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,v):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,v)}function O(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function j(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function G(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(O,this),this.reset(!0)}function B(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function r(){for(;++o<e.length;)if(n.call(e,o))return r.value=e[o],r.done=!1,r;return r.value=t,r.done=!0,r};return i.next=i}}throw new TypeError(_typeof(e)+" is not iterable")}return g.prototype=w,o(T,"constructor",{value:w,configurable:!0}),o(w,"constructor",{value:g,configurable:!0}),g.displayName=l(w,u,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===g||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,w):(t.__proto__=w,l(t,u,"GeneratorFunction")),t.prototype=Object.create(T),t},e.awrap=function(t){return{__await:t}},_(L.prototype),l(L.prototype,c,(function(){return this})),e.AsyncIterator=L,e.async=function(t,r,n,o,i){void 0===i&&(i=Promise);var a=new L(f(t,r,n,o),i);return e.isGeneratorFunction(r)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},_(T),l(T,u,"Generator"),l(T,a,(function(){return this})),l(T,"toString",(function(){return"[object Generator]"})),e.keys=function(t){var e=Object(t),r=[];for(var n in e)r.push(n);return r.reverse(),function t(){for(;r.length;){var n=r.pop();if(n in e)return t.value=n,t.done=!1,t}return t.done=!0,t}},e.values=B,G.prototype={constructor:G,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(j),!e)for(var r in this)"t"===r.charAt(0)&&n.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=t)},stop:function(){this.done=!0;var t=this.tryELine truncated
|
||||
@@ -1 +0,0 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
* See LICENSE in the project root for license information.
|
||||
*/
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ms-welcome__header {
|
||||
padding: 20px;
|
||||
padding-bottom: 30px;
|
||||
padding-top: 100px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ms-welcome__main {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-flex: 1 0 0;
|
||||
flex: 1 0 0;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.ms-welcome__main > h2 {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ms-welcome__features {
|
||||
list-style-type: none;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.ms-welcome__features.ms-List .ms-ListItem {
|
||||
padding-bottom: 20px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.ms-welcome__action.ms-Button--hero {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.ms-Button.ms-Button--hero .ms-Button-label {
|
||||
color: #0078d7;
|
||||
}
|
||||
|
||||
.ms-Button.ms-Button--hero:hover .ms-Button-label,
|
||||
.ms-Button.ms-Button--hero:focus .ms-Button-label{
|
||||
color: #005a9e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 839 B |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 99 KiB |
@@ -1 +0,0 @@
|
||||
<!doctype html><html><head><meta charset="UTF-8"/><meta http-equiv="X-UA-Compatible" content="IE=Edge"/><script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script><script defer="defer" src="polyfill.js"></script><script defer="defer" src="commands.js"></script></head><body></body></html>
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(){var e={};e.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),Office.onReady((function(){})),("undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==e.g?e.g:void 0).action=function(e){var n={type:Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,message:"Performed action.",icon:"Icon.80x80",persistent:!0};Office.context.mailbox.item.notificationMessages.replaceAsync("action",n),e.completed()}}();
|
||||
//# sourceMappingURL=commands.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"commands.js","mappings":"YACA,IAAIA,EAAsB,CAAC,ECD3BA,EAAoBC,EAAI,WACvB,GAA0B,iBAAfC,WAAyB,OAAOA,WAC3C,IACC,OAAOC,MAAQ,IAAIC,SAAS,cAAb,EAChB,CAAE,MAAOC,GACR,GAAsB,iBAAXC,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCOxBC,OAAOC,SAAQ,WACb,KAuBuB,oBAATC,KACVA,KACkB,oBAAXH,OACPA,YACkB,IAAXI,EAAAA,EACPA,EAAAA,OACAC,GAMJC,OA5BF,SAAgBC,GACd,IAAMC,EAAU,CACdC,KAAMR,OAAOS,aAAaC,4BAA4BC,qBACtDJ,QAAS,oBACTK,KAAM,aACNC,YAAY,GAIdb,OAAOc,QAAQC,QAAQC,KAAKC,qBAAqBC,aAAa,SAAUX,GAGxED,EAAMa,WACR,C","sources":["webpack://office-addin-taskpane-js/webpack/bootstrap","webpack://office-addin-taskpane-js/webpack/runtime/global","webpack://office-addin-taskpane-js/./src/commands/commands.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","/*\n * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n * See LICENSE in the project root for license information.\n */\n\n/* global global, Office, self, window */\n\nOffice.onReady(() => {\n // If needed, Office.js is ready to be called\n});\n\n/**\n * Shows a notification when the add-in command is executed.\n * @param event {Office.AddinCommands.Event}\n */\nfunction action(event) {\n const message = {\n type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,\n message: \"Performed action.\",\n icon: \"Icon.80x80\",\n persistent: true,\n };\n\n // Show a notification message\n Office.context.mailbox.item.notificationMessages.replaceAsync(\"action\", message);\n\n // Be sure to indicate when the add-in command function is complete\n event.completed();\n}\n\nfunction getGlobal() {\n return typeof self !== \"undefined\"\n ? self\n : typeof window !== \"undefined\"\n ? window\n : typeof global !== \"undefined\"\n ? global\n : undefined;\n}\n\nconst g = getGlobal();\n\n// The add-in command functions need to be available in global scope\ng.action = action;\n"],"names":["__webpack_require__","g","globalThis","this","Function","e","window","Office","onReady","self","global","undefined","action","event","message","type","MailboxEnums","ItemNotificationMessageType","InformationalMessage","icon","persistent","context","mailbox","item","notificationMessages","replaceAsync","completed"],"sourceRoot":""}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp">
|
||||
<Id>68b6ad53-4f72-42a8-a971-a9643c2f409a</Id>
|
||||
<Version>1.0.0.0</Version>
|
||||
<ProviderName>AllTalk</ProviderName>
|
||||
<DefaultLocale>en-US</DefaultLocale>
|
||||
<DisplayName DefaultValue="AllTalk TTS"/>
|
||||
<Description DefaultValue="Enhance your document creation with AllTalk TTS's advanced text-to-voice functionality. Requires connection to AllTalk server."/>
|
||||
<IconUrl DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-32.png"/>
|
||||
<HighResolutionIconUrl DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-64.png"/>
|
||||
<SupportUrl DefaultValue="https://github.com/erew123/alltalk_tts/issues"/>
|
||||
<AppDomains>
|
||||
<AppDomain>https://www.contoso.com</AppDomain>
|
||||
</AppDomains>
|
||||
<Hosts>
|
||||
<Host Name="Document"/>
|
||||
</Hosts>
|
||||
<DefaultSettings>
|
||||
<SourceLocation DefaultValue="http://127.0.0.1:7851/api/word_addin/taskpane.html"/>
|
||||
</DefaultSettings>
|
||||
<Permissions>ReadWriteDocument</Permissions>
|
||||
<VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
|
||||
<Hosts>
|
||||
<Host xsi:type="Document">
|
||||
<DesktopFormFactor>
|
||||
<!-- You can add GetStarted information here if needed -->
|
||||
<FunctionFile resid="Commands.Url"/>
|
||||
<ExtensionPoint xsi:type="PrimaryCommandSurface">
|
||||
<OfficeTab id="TabHome">
|
||||
<Group id="AllTalkGroup">
|
||||
<Label resid="AllTalkGroup.Label"/>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Control xsi:type="Button" id="AllTalkTaskpaneButton">
|
||||
<Label resid="AllTalkTaskpaneButton.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="AllTalkTaskpaneButton.Label"/>
|
||||
<Description resid="AllTalkTaskpaneButton.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<TaskpaneId>ButtonId1</TaskpaneId>
|
||||
<SourceLocation resid="Taskpane.Url"/>
|
||||
</Action>
|
||||
</Control>
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
</DesktopFormFactor>
|
||||
</Host>
|
||||
</Hosts>
|
||||
<Resources>
|
||||
<bt:Images>
|
||||
<bt:Image id="Icon.16x16" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-16.png"/>
|
||||
<bt:Image id="Icon.32x32" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-32.png"/>
|
||||
<bt:Image id="Icon.80x80" DefaultValue="http://127.0.0.1:7851/api/word_addin/assets/icon-80.png"/>
|
||||
</bt:Images>
|
||||
<bt:Urls>
|
||||
<!-- Ensure that these URLs are pointing to valid locations -->
|
||||
<bt:Url id="Commands.Url" DefaultValue="http://127.0.0.1:7851/api/word_addin/commands.html"/>
|
||||
<bt:Url id="Taskpane.Url" DefaultValue="http://127.0.0.1:7851/api/word_addin/taskpane.html"/>
|
||||
</bt:Urls>
|
||||
<bt:ShortStrings>
|
||||
<bt:String id="AllTalkGroup.Label" DefaultValue="AllTalk Controls"/>
|
||||
<bt:String id="AllTalkTaskpaneButton.Label" DefaultValue="Open AllTalk"/>
|
||||
</bt:ShortStrings>
|
||||
<bt:LongStrings>
|
||||
<bt:String id="AllTalkTaskpaneButton.Tooltip" DefaultValue="Open the AllTalk task pane to start using the add-in."/>
|
||||
</bt:LongStrings>
|
||||
</Resources>
|
||||
</VersionOverrides>
|
||||
</OfficeApp>
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(){var t={35666:function(t){var r=function(t){"use strict";var r,e=Object.prototype,n=e.hasOwnProperty,i=Object.defineProperty||function(t,r,e){t[r]=e.value},o="function"==typeof Symbol?Symbol:{},u=o.iterator||"@@iterator",a=o.asyncIterator||"@@asyncIterator",c=o.toStringTag||"@@toStringTag";function s(t,r,e){return Object.defineProperty(t,r,{value:e,enumerable:!0,configurable:!0,writable:!0}),t[r]}try{s({},"")}catch(t){s=function(t,r,e){return t[r]=e}}function f(t,r,e,n){var o=r&&r.prototype instanceof y?r:y,u=Object.create(o.prototype),a=new j(n||[]);return i(u,"_invoke",{value:R(t,e,a)}),u}function l(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}t.wrap=f;var h="suspendedStart",p="suspendedYield",v="executing",g="completed",d={};function y(){}function m(){}function b(){}var x={};s(x,u,(function(){return this}));var w=Object.getPrototypeOf,E=w&&w(w(P([])));E&&E!==e&&n.call(E,u)&&(x=E);var S=b.prototype=y.prototype=Object.create(x);function A(t){["next","throw","return"].forEach((function(r){s(t,r,(function(t){return this._invoke(r,t)}))}))}function O(t,r){function e(i,o,u,a){var c=l(t[i],t,o);if("throw"!==c.type){var s=c.arg,f=s.value;return f&&"object"==typeof f&&n.call(f,"__await")?r.resolve(f.__await).then((function(t){e("next",t,u,a)}),(function(t){e("throw",t,u,a)})):r.resolve(f).then((function(t){s.value=t,u(s)}),(function(t){return e("throw",t,u,a)}))}a(c.arg)}var o;i(this,"_invoke",{value:function(t,n){function i(){return new r((function(r,i){e(t,n,r,i)}))}return o=o?o.then(i,i):i()}})}function R(t,r,e){var n=h;return function(i,o){if(n===v)throw new Error("Generator is already running");if(n===g){if("throw"===i)throw o;return k()}for(e.method=i,e.arg=o;;){var u=e.delegate;if(u){var a=T(u,e);if(a){if(a===d)continue;return a}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if(n===h)throw n=g,e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n=v;var c=l(t,r,e);if("normal"===c.type){if(n=e.done?g:p,c.arg===d)continue;return{value:c.arg,done:e.done}}"throw"===c.type&&(n=g,e.method="throw",e.arg=c.arg)}}}function T(t,e){var n=e.method,i=t.iterator[n];if(i===r)return e.delegate=null,"throw"===n&&t.iterator.return&&(e.method="return",e.arg=r,T(t,e),"throw"===e.method)||"return"!==n&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+n+"' method")),d;var o=l(i,t.iterator,e.arg);if("throw"===o.type)return e.method="throw",e.arg=o.arg,e.delegate=null,d;var u=o.arg;return u?u.done?(e[t.resultName]=u.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=r),e.delegate=null,d):u:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,d)}function I(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function M(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function j(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(I,this),this.reset(!0)}function P(t){if(t){var e=t[u];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var i=-1,o=function e(){for(;++i<t.length;)if(n.call(t,i))return e.value=t[i],e.done=!1,e;return e.value=r,e.done=!0,e};return o.next=o}}return{next:k}}function k(){return{value:r,done:!0}}return m.prototype=b,i(S,"constructor",{value:b,configurable:!0}),i(b,"constructor",{value:m,configurable:!0}),m.displayName=s(b,c,"GeneratorFunction"),t.isGeneratorFunction=function(t){var r="function"==typeof t&&t.constructor;return!!r&&(r===m||"GeneratorFunction"===(r.displayName||r.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,b):(t.__proto__=b,s(t,c,"GeneratorFunction")),t.prototype=Object.create(S),t},t.awrap=function(t){return{__await:t}},A(O.prototype),s(O.prototype,a,(function(){return this})),t.AsyncIterator=O,t.async=function(r,e,n,i,o){void 0===o&&(o=Promise);var u=new O(f(r,e,n,i),o);return t.isGeneratorFunction(e)?u:u.next().then((function(t){return t.done?t.value:u.next()}))},A(S),s(S,c,"Generator"),s(S,u,(function(){return this})),s(S,"toString",(function(){return"[object Generator]"})),t.keys=function(t){var r=Object(t),e=[];for(var n in r)e.push(n);return e.reverse(),function t(){for(;e.length;){var n=e.pop();if(n in r)return t.value=n,t.done=!1,t}return t.done=!0,t}},t.values=P,j.prototype={constructor:j,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=r,this.done=!1,this.delegate=null,this.method="next",this.arg=r,this.tryEntries.forEach(M),!t)for(var e in this)"t"===e.charAt(0)&&n.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=r)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function i(n,i){return a.type="throw",a.arg=t,e.next=n,i&&(e.method="next",e.arg=r),!!i}for(var o=this.tryEntries.length-1;o>=0;--o){var u=this.tryEntries[o],aLine truncated
|
||||
//# sourceMappingURL=polyfill.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"polyfill.js","mappings":"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 truncated
|
||||
@@ -1,106 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>AllTalk TTS Add-in</title>
|
||||
<script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
|
||||
<link rel="stylesheet"
|
||||
href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/11.0.0/css/fabric.min.css" />
|
||||
<link href="1fda685b81e1123773f6.css" rel="stylesheet" />
|
||||
<style>
|
||||
label {
|
||||
font-weight: 700;
|
||||
display: block;
|
||||
margin-top: 10px
|
||||
}
|
||||
|
||||
select {
|
||||
width: 100%;
|
||||
padding: 5px
|
||||
}
|
||||
|
||||
.nice-button {
|
||||
background-color: #0078d4;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: background-color .3s ease
|
||||
}
|
||||
|
||||
.nice-button:hover {
|
||||
background-color: #005a9e
|
||||
}
|
||||
|
||||
#audioSource {
|
||||
width: 300px;
|
||||
height: 50px
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 10px
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: flex-end
|
||||
}
|
||||
|
||||
.input-group>.input-container {
|
||||
flex: 1
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%
|
||||
}
|
||||
</style>
|
||||
<script defer="defer" src="polyfill.js"></script>
|
||||
<script defer="defer" src="taskpane.js"></script>
|
||||
</head>
|
||||
|
||||
<body class="ms-font-m ms-welcome ms-Fabric">
|
||||
<header class="ms-welcome__header ms-bgColor-neutralLighter"><img width="90" height="90"
|
||||
src="http://127.0.0.1:7851/api/word_addin/assets/logo-filled.png" alt="AllTalk TTS" title="AllTalk TTS" />
|
||||
<h1 class="ms-font-su">AllTalk TTS</h1>
|
||||
</header>
|
||||
<main class="ms-welcome__main"><textarea id="text" rows="4" placeholder="Enter text here"
|
||||
style="display:none"></textarea> <label for="voice">Voice:</label> <select id="voice" name="voice"
|
||||
required></select> <label for="language">Language:</label> <select id="language" name="language"
|
||||
value="English" required>
|
||||
<option value="en" selected="selected">English</option>
|
||||
<option value="ar">Arabic</option>
|
||||
<option value="zh-cn">Chinese</option>
|
||||
<option value="cs">Czech</option>
|
||||
<option value="nl">Dutch</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
<option value="hu">Hungarian</option>
|
||||
<option value="it">Italian</option>
|
||||
<option value="ja">Japanese</option>
|
||||
<option value="ko">Korean</option>
|
||||
<option value="pl">Polish</option>
|
||||
<option value="pt">Portuguese</option>
|
||||
<option value="ru">Russian</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="tr">Turkish</option>
|
||||
</select><br><audio id="audioSource" controls autoplay></audio><br><button id="sendTextButton"
|
||||
class="nice-button">Send Text to TTS</button><br><br><br><br>
|
||||
<div class="input-group">
|
||||
<div class="input-container"><label for="serverIP">Server IP:</label> <input id="serverIP" name="serverIP"
|
||||
value="127.0.0.1" required></div>
|
||||
<div class="input-container"><label for="portNumber">Port Number:</label> <input type="number"
|
||||
id="portNumber" name="portNumber" value="7851" required></div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="1995fcd6d39cade7d871.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,3 +0,0 @@
|
||||
/*! For license information please see taskpane.js.LICENSE.txt */
|
||||
!function(){var t={27091:function(t){"use strict";t.exports=function(t,e){return e||(e={}),t?(t=String(t.__esModule?t.default:t),e.hash&&(t+=e.hash),e.maybeNeedQuotes&&/[\t\n\f\r "'=<>`]/.test(t)?'"'.concat(t,'"'):t):t}},44944:function(t,e,r){"use strict";t.exports=r.p+"assets/logo-filled.png"},36076:function(t,e,r){"use strict";t.exports=r.p+"1995fcd6d39cade7d871.js"},60806:function(t,e,r){"use strict";t.exports=r.p+"1fda685b81e1123773f6.css"}},e={};function r(n){var o=e[n];if(void 0!==o)return o.exports;var i=e[n]={exports:{}};return t[n](i,i.exports,r),i.exports}r.m=t,r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,{a:e}),e},r.d=function(t,e){for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},function(){var t;r.g.importScripts&&(t=r.g.location+"");var e=r.g.document;if(!t&&e&&(e.currentScript&&(t=e.currentScript.src),!t)){var n=e.getElementsByTagName("script");if(n.length)for(var o=n.length-1;o>-1&&!t;)t=n[o--].src}if(!t)throw new Error("Automatic publicPath is not supported in this browser");t=t.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r.p=t}(),r.b=document.baseURI||self.location.href,function(){function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}function e(){"use strict";e=function(){return n};var r,n={},o=Object.prototype,i=o.hasOwnProperty,c=Object.defineProperty||function(t,e,r){t[e]=r.value},a="function"==typeof Symbol?Symbol:{},u=a.iterator||"@@iterator",f=a.asyncIterator||"@@asyncIterator",s=a.toStringTag||"@@toStringTag";function l(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{l({},"")}catch(r){l=function(t,e,r){return t[e]=r}}function h(t,e,r,n){var o=e&&e.prototype instanceof w?e:w,i=Object.create(o.prototype),a=new k(n||[]);return c(i,"_invoke",{value:I(t,r,a)}),i}function p(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}n.wrap=h;var y="suspendedStart",v="suspendedYield",d="executing",m="completed",g={};function w(){}function b(){}function x(){}var E={};l(E,u,(function(){return this}));var L=Object.getPrototypeOf,_=L&&L(L(T([])));_&&_!==o&&i.call(_,u)&&(E=_);var j=x.prototype=w.prototype=Object.create(E);function O(t){["next","throw","return"].forEach((function(e){l(t,e,(function(t){return this._invoke(e,t)}))}))}function S(e,r){function n(o,c,a,u){var f=p(e[o],e,c);if("throw"!==f.type){var s=f.arg,l=s.value;return l&&"object"==t(l)&&i.call(l,"__await")?r.resolve(l.__await).then((function(t){n("next",t,a,u)}),(function(t){n("throw",t,a,u)})):r.resolve(l).then((function(t){s.value=t,a(s)}),(function(t){return n("throw",t,a,u)}))}u(f.arg)}var o;c(this,"_invoke",{value:function(t,e){function i(){return new r((function(r,o){n(t,e,r,o)}))}return o=o?o.then(i,i):i()}})}function I(t,e,n){var o=y;return function(i,c){if(o===d)throw new Error("Generator is already running");if(o===m){if("throw"===i)throw c;return{value:r,done:!0}}for(n.method=i,n.arg=c;;){var a=n.delegate;if(a){var u=P(a,n);if(u){if(u===g)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===y)throw o=m,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=d;var f=p(t,e,n);if("normal"===f.type){if(o=n.done?m:v,f.arg===g)continue;return{value:f.arg,done:n.done}}"throw"===f.type&&(o=m,n.method="throw",n.arg=f.arg)}}}function P(t,e){var n=e.method,o=t.iterator[n];if(o===r)return e.delegate=null,"throw"===n&&t.iterator.return&&(e.method="return",e.arg=r,P(t,e),"throw"===e.method)||"return"!==n&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+n+"' method")),g;var i=p(o,t.iterator,e.arg);if("throw"===i.type)return e.method="throw",e.arg=i.arg,e.delegate=null,g;var c=i.arg;return c?c.done?(e[t.resultName]=c.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=r),e.delegate=null,g):c:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,g)}function B(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function N(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function k(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(B,this),this.reset(!0)}function T(e){if(e||""===e){var n=e[u];if(n)return n.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,c=function t(){for(;++o<e.length;)if(i.call(e,o))return t.value=e[o],t.done=!1,t;return t.value=r,t.done=!0,t};return c.next=c}}throw new TLine truncated
|
||||
//# sourceMappingURL=taskpane.js.map
|
||||
@@ -1 +0,0 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"taskpane.js","mappings":"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 truncated
|
||||