Updates to reduce browser load
Pagination of files list. No Playback option Better clearing of played back audio from memory
This commit is contained in:
1 parent
a22830f700
commit
ff4b9d9e99
1 file changed
+344
-67
@@ -175,27 +175,32 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.progress-overlay {
|
.progress-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
background: rgba(255, 255, 255, 0.9);
|
background: rgba(255, 255, 255, 0.9);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column; /* Stack items vertically */
|
flex-direction: column;
|
||||||
align-items: center; /* Center items horizontally within the container */
|
/* Stack items vertically */
|
||||||
justify-content: center; /* Center items vertically within the container */
|
align-items: center;
|
||||||
z-index: 10;
|
/* Center items horizontally within the container */
|
||||||
}
|
justify-content: center;
|
||||||
|
/* Center items vertically within the container */
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure the text is wrapped in a container with a class, e.g., .progress-text */
|
/* Ensure the text is wrapped in a container with a class, e.g., .progress-text */
|
||||||
.progress-text {
|
.progress-text {
|
||||||
text-align: right; /* Center the text horizontally */
|
text-align: right;
|
||||||
margin-top: 10px; /* Add space between the spinner and the text */
|
/* Center the text horizontally */
|
||||||
}
|
margin-top: 10px;
|
||||||
|
/* Add space between the spinner and the text */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#progressIndicator {
|
#progressIndicator {
|
||||||
/* Adjust this if you want to position the spinning disk differently */
|
/* Adjust this if you want to position the spinning disk differently */
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
@@ -413,6 +418,78 @@
|
|||||||
margin-left: 45px;
|
margin-left: 45px;
|
||||||
/* Adjust the value as needed */
|
/* Adjust the value as needed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pagination Buttons Styling */
|
||||||
|
.pagination-btn {
|
||||||
|
padding: 5px 10px;
|
||||||
|
/* Adjust padding to reduce height */
|
||||||
|
font-size: 0.8em;
|
||||||
|
/* Adjust font size for smaller buttons */
|
||||||
|
line-height: 1;
|
||||||
|
/* Adjust line height to match the smaller size */
|
||||||
|
margin: 2px;
|
||||||
|
/* Optional: adjust spacing between buttons */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smaller input field for jump-to-page */
|
||||||
|
.pagination-input {
|
||||||
|
height: 20px;
|
||||||
|
/* Adjust height for smaller input field */
|
||||||
|
padding: 2px 5px;
|
||||||
|
/* Adjust padding for smaller input field */
|
||||||
|
font-size: 0.8em;
|
||||||
|
/* Adjust font size for smaller input field */
|
||||||
|
line-height: 1;
|
||||||
|
/* Adjust line height to match the smaller size */
|
||||||
|
vertical-align: middle;
|
||||||
|
/* Align with buttons if necessary */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply the styles to your pagination controls */
|
||||||
|
#paginationControls button {
|
||||||
|
/* Apply the button styling */
|
||||||
|
height: auto;
|
||||||
|
/* Let padding control the height */
|
||||||
|
min-height: 20px;
|
||||||
|
/* Set a minimum height if needed */
|
||||||
|
}
|
||||||
|
|
||||||
|
#paginationControls input[type="number"] {
|
||||||
|
/* Apply the input styling */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smaller input field for jump-to-page */
|
||||||
|
.pagination-input {
|
||||||
|
height: 2px;
|
||||||
|
/* Reduce the height */
|
||||||
|
padding: 0px 0px;
|
||||||
|
/* Reduce the padding to decrease overall height */
|
||||||
|
font-size: 0.8em;
|
||||||
|
/* Optionally reduce the font size */
|
||||||
|
margin-bottom: 13px;
|
||||||
|
margin-top: 2px;
|
||||||
|
border: 0px solid #ccc;
|
||||||
|
/* Adjust border styling if needed */
|
||||||
|
line-height: normal;
|
||||||
|
/* Adjust line height to match the new size */
|
||||||
|
vertical-align: top;
|
||||||
|
/* Align vertically with buttons */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply the styles to your pagination controls */
|
||||||
|
#paginationControls1 button {
|
||||||
|
/* Apply the button styling */
|
||||||
|
height: auto;
|
||||||
|
/* Let padding control the height */
|
||||||
|
min-height: 20px;
|
||||||
|
/* Set a minimum height if needed */
|
||||||
|
margin-top: 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
#paginationControls1 input[type="number"] {
|
||||||
|
/* Apply the input styling */
|
||||||
|
margin-top: 15px
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
@@ -469,6 +546,7 @@
|
|||||||
<select id="playMode" name="playMode" class="fixed-size-dropdown">
|
<select id="playMode" name="playMode" class="fixed-size-dropdown">
|
||||||
<option value="local" selected>In Browser</option>
|
<option value="local" selected>In Browser</option>
|
||||||
<option value="remote">On Server</option>
|
<option value="remote">On Server</option>
|
||||||
|
<option value="none">No Playback</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -524,9 +602,23 @@
|
|||||||
<button onclick="exportToJSON()" style="margin-right: 10px;">Export List as JSON</button>
|
<button onclick="exportToJSON()" style="margin-right: 10px;">Export List as JSON</button>
|
||||||
<button onclick="importFromJSON()" style="margin-right: 10px;">Import JSON to list</button>
|
<button onclick="importFromJSON()" style="margin-right: 10px;">Import JSON to list</button>
|
||||||
<button onclick="exportMP3()" style="margin-right: 10px;">Export to Wav</button>
|
<button onclick="exportMP3()" style="margin-right: 10px;">Export to Wav</button>
|
||||||
|
<div id="paginationControls">
|
||||||
|
<button id="prevPage" class="pagination-btn">Previous</button>
|
||||||
|
<span id="pageIndicator">Page 1 of X</span>
|
||||||
|
<button id="nextPage" class="pagination-btn">Next</button>
|
||||||
|
<input type="number" id="jumpToPage" class="pagination-input" min="1" placeholder="Jump to Page">
|
||||||
|
<button id="jumpButton" class="pagination-btn">Go</button>
|
||||||
|
</div>
|
||||||
<div id="ttsListDisplay" class="tts-list-display">
|
<div id="ttsListDisplay" class="tts-list-display">
|
||||||
<!-- Dynamically populated TTS details will go here -->
|
<!-- Dynamically populated TTS details will go here -->
|
||||||
</div>
|
</div>
|
||||||
|
<div id="paginationControls1">
|
||||||
|
<button id="prevPage1" class="pagination-btn">Previous</button>
|
||||||
|
<span id="pageIndicator1">Page 1 of X</span>
|
||||||
|
<button id="nextPage1" class="pagination-btn">Next</button>
|
||||||
|
<input type="number" id="jumpToPage1" class="pagination-input" min="1" placeholder="Jump to Page">
|
||||||
|
<button id="jumpButton1" class="pagination-btn">Go</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -537,35 +629,35 @@
|
|||||||
import Crunker from './crunker.esm.js';
|
import Crunker from './crunker.esm.js';
|
||||||
|
|
||||||
async function exportMP3() {
|
async function exportMP3() {
|
||||||
const crunker = new Crunker();
|
const crunker = new Crunker();
|
||||||
const fileUrls = ttsList.map(item => item.fileUrl);
|
const fileUrls = ttsList.map(item => item.fileUrl);
|
||||||
const progressIndicator = document.getElementById('progressIndicator');
|
const progressIndicator = document.getElementById('progressIndicator');
|
||||||
const progressText = document.getElementById('progressText');
|
const progressText = document.getElementById('progressText');
|
||||||
|
|
||||||
// Show progress indicator and update text
|
// Show progress indicator and update text
|
||||||
if (progressIndicator && progressText) {
|
if (progressIndicator && progressText) {
|
||||||
progressText.textContent = 'Export';
|
progressText.textContent = 'Export';
|
||||||
progressText.style.color = 'black'; // Set the text color to black
|
progressText.style.color = 'black'; // Set the text color to black
|
||||||
progressIndicator.style.display = 'block';
|
progressIndicator.style.display = 'block';
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const audioBuffers = await crunker.fetchAudio(...fileUrls);
|
|
||||||
const combined = crunker.concatAudio(audioBuffers);
|
|
||||||
const output = crunker.export(combined, "audio/wav");
|
|
||||||
crunker.download(output.blob, "combined_audio"); // This will download the file as 'combined_audio.mp3'
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error combining files:', error);
|
|
||||||
if (progressText) {
|
|
||||||
progressText.textContent = 'Error during export!';
|
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
// Hide progress indicator after completion or error
|
try {
|
||||||
if (progressIndicator) {
|
const audioBuffers = await crunker.fetchAudio(...fileUrls);
|
||||||
progressIndicator.style.display = 'none';
|
const combined = crunker.concatAudio(audioBuffers);
|
||||||
|
const output = crunker.export(combined, "audio/wav");
|
||||||
|
crunker.download(output.blob, "combined_audio"); // This will download the file as 'combined_audio.mp3'
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error combining files:', error);
|
||||||
|
if (progressText) {
|
||||||
|
progressText.textContent = 'Error during export!';
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
// Hide progress indicator after completion or error
|
||||||
|
if (progressIndicator) {
|
||||||
|
progressIndicator.style.display = 'none';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Attach exportMP3 to the window object to make it globally accessible
|
// Attach exportMP3 to the window object to make it globally accessible
|
||||||
window.exportMP3 = exportMP3;
|
window.exportMP3 = exportMP3;
|
||||||
@@ -582,7 +674,7 @@
|
|||||||
let audioQueue = [];
|
let audioQueue = [];
|
||||||
let currentlyPlayingIndex = 0;
|
let currentlyPlayingIndex = 0;
|
||||||
let isPlaying = false;
|
let isPlaying = false;
|
||||||
let playModeValue = 'local';
|
let playModeValue = localStorage.getItem('playMode') || 'local';
|
||||||
let currentSound = null;
|
let currentSound = null;
|
||||||
let preloadThreshold = 2; // Number of files to preload before starting playback
|
let preloadThreshold = 2; // Number of files to preload before starting playback
|
||||||
let isStreamInitialized = false;
|
let isStreamInitialized = false;
|
||||||
@@ -591,6 +683,9 @@
|
|||||||
const howlInstances = {};
|
const howlInstances = {};
|
||||||
let listPlaying = false;
|
let listPlaying = false;
|
||||||
let listPlayIndex = 0;
|
let listPlayIndex = 0;
|
||||||
|
let currentPage = 1;
|
||||||
|
let itemsPerPage = 100; // Adjust as needed
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
//////// Progress Indicator ////////
|
//////// Progress Indicator ////////
|
||||||
@@ -602,7 +697,7 @@
|
|||||||
|
|
||||||
if (progressIndicator && generationProgress) {
|
if (progressIndicator && generationProgress) {
|
||||||
let message = '';
|
let message = '';
|
||||||
console.log("PlayType is:", playType);
|
//console.log("PlayType is:", playType);
|
||||||
if (playType === 'stream') {
|
if (playType === 'stream') {
|
||||||
// When streaming, display a different message
|
// When streaming, display a different message
|
||||||
message = '<span class="highlight-count">      Streaming...</span>';
|
message = '<span class="highlight-count">      Streaming...</span>';
|
||||||
@@ -650,6 +745,7 @@
|
|||||||
const volume = parseFloat(document.getElementById("volume").value);
|
const volume = parseFloat(document.getElementById("volume").value);
|
||||||
const chunkSize = parseInt(document.getElementById("chunkSize").value);
|
const chunkSize = parseInt(document.getElementById("chunkSize").value);
|
||||||
const playType = document.getElementById('playType').value; // Play type (chunk or stream)
|
const playType = document.getElementById('playType').value; // Play type (chunk or stream)
|
||||||
|
playModeValue = document.getElementById('playMode').value;
|
||||||
|
|
||||||
let cleanedText = textInput.replace(/ \- | \– /g, ' ');
|
let cleanedText = textInput.replace(/ \- | \– /g, ' ');
|
||||||
cleanedText = cleanedText.replace(/%/g, " percent");
|
cleanedText = cleanedText.replace(/%/g, " percent");
|
||||||
@@ -685,9 +781,14 @@
|
|||||||
if (stopTTSGeneration) break;
|
if (stopTTSGeneration) break;
|
||||||
showProgress(i + 1, totalChunks, playType);
|
showProgress(i + 1, totalChunks, playType);
|
||||||
if (playModeValue === 'local') {
|
if (playModeValue === 'local') {
|
||||||
|
// Generate the chunk and play it locally
|
||||||
await generateAndCache(chunks[i], language, characterVoice, volume);
|
await generateAndCache(chunks[i], language, characterVoice, volume);
|
||||||
} else {
|
} else if (playModeValue === 'remote') {
|
||||||
|
// Generate the chunk and play it remotely
|
||||||
await generateAndPlayRemote(chunks[i], language, characterVoice, volume);
|
await generateAndPlayRemote(chunks[i], language, characterVoice, volume);
|
||||||
|
} else if (playModeValue === 'none') {
|
||||||
|
// Generate the chunk but do not play it
|
||||||
|
await generateWithoutPlayback(chunks[i], language, characterVoice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -735,6 +836,7 @@
|
|||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (result.output_file_url) {
|
if (result.output_file_url) {
|
||||||
|
//console.log('TTS Generation Result:', result);
|
||||||
// If an ID was passed in, we're regenerating an existing item
|
// If an ID was passed in, we're regenerating an existing item
|
||||||
if (id !== null) {
|
if (id !== null) {
|
||||||
let itemIndex = ttsList.findIndex(item => item.id === id);
|
let itemIndex = ttsList.findIndex(item => item.id === id);
|
||||||
@@ -748,6 +850,15 @@
|
|||||||
// No ID was passed in, so we add a new item to the list
|
// No ID was passed in, so we add a new item to the list
|
||||||
addToTTSList(result.output_file_url, chunk, characterVoice, language);
|
addToTTSList(result.output_file_url, chunk, characterVoice, language);
|
||||||
}
|
}
|
||||||
|
const newPage = Math.ceil(ttsList.length / itemsPerPage);
|
||||||
|
//console.log('New Page Calculated:', newPage);
|
||||||
|
if (currentPage !== newPage) {
|
||||||
|
currentPage = newPage; // Move to the new page where the item was added
|
||||||
|
//console.log('Updating Current Page to:', currentPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh the list display to reflect the new pagination state
|
||||||
|
updateUIList();
|
||||||
|
|
||||||
// Update the audio queue and UI
|
// Update the audio queue and UI
|
||||||
const sound = new Howl({
|
const sound = new Howl({
|
||||||
@@ -769,6 +880,56 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function generateWithoutPlayback(chunk, language, characterVoice, id = null) {
|
||||||
|
// Perform the generation process as usual but do not play the audio
|
||||||
|
try {
|
||||||
|
const data = new URLSearchParams({
|
||||||
|
text_input: chunk.trim(),
|
||||||
|
text_filtering: "standard",
|
||||||
|
character_voice_gen: characterVoice,
|
||||||
|
narrator_enabled: "false",
|
||||||
|
narrator_voice_gen: characterVoice,
|
||||||
|
text_not_inside: "character",
|
||||||
|
language: language,
|
||||||
|
output_file_name: "TTS",
|
||||||
|
output_file_timestamp: "true",
|
||||||
|
autoplay: "false",
|
||||||
|
autoplay_volume: "0.1"
|
||||||
|
});
|
||||||
|
const response = await fetch("http://127.0.0.1:7851/api/tts-generate", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
body: data,
|
||||||
|
});
|
||||||
|
const result = await response.json();
|
||||||
|
if (result.output_file_url) {
|
||||||
|
// If an ID was passed in, we're regenerating an existing item
|
||||||
|
if (id !== null) {
|
||||||
|
let itemIndex = ttsList.findIndex(item => item.id === id);
|
||||||
|
if (itemIndex !== -1) {
|
||||||
|
ttsList[itemIndex].fileUrl = result.output_file_url;
|
||||||
|
// Other properties can be updated as needed, e.g., in case the language or voice has changed
|
||||||
|
ttsList[itemIndex].language = language;
|
||||||
|
ttsList[itemIndex].characterVoice = characterVoice;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No ID was passed in, so we add a new item to the list
|
||||||
|
addToTTSList(result.output_file_url, chunk, characterVoice, language);
|
||||||
|
}
|
||||||
|
const newPage = Math.ceil(ttsList.length / itemsPerPage);
|
||||||
|
if (currentPage !== newPage) {
|
||||||
|
currentPage = newPage; // Move to the new page where the item was added
|
||||||
|
}
|
||||||
|
updateUIList();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in generateWithoutPlayback:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function addToTTSList(fileUrl, text, characterVoice, language) {
|
function addToTTSList(fileUrl, text, characterVoice, language) {
|
||||||
try {
|
try {
|
||||||
ttsList.push({
|
ttsList.push({
|
||||||
@@ -784,6 +945,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function regenerateTTS(id) {
|
async function regenerateTTS(id) {
|
||||||
// Find the details of the TTS to regenerate
|
// Find the details of the TTS to regenerate
|
||||||
const ttsDetails = ttsList.find(item => item.id === id);
|
const ttsDetails = ttsList.find(item => item.id === id);
|
||||||
@@ -804,7 +966,13 @@
|
|||||||
}
|
}
|
||||||
listDisplay.innerHTML = ''; // Clear the current list
|
listDisplay.innerHTML = ''; // Clear the current list
|
||||||
|
|
||||||
ttsList.forEach(item => {
|
// Determine the range of items to display for pagination
|
||||||
|
const start = (currentPage - 1) * itemsPerPage;
|
||||||
|
const end = start + itemsPerPage;
|
||||||
|
const paginatedItems = ttsList.slice(start, end);
|
||||||
|
|
||||||
|
// Add items to the display for the current page
|
||||||
|
paginatedItems.forEach(item => {
|
||||||
// Extract just the file name from the URL
|
// Extract just the file name from the URL
|
||||||
const wavFileName = item.fileUrl.split('/').pop();
|
const wavFileName = item.fileUrl.split('/').pop();
|
||||||
|
|
||||||
@@ -814,30 +982,36 @@
|
|||||||
const entryDiv = document.createElement('div');
|
const entryDiv = document.createElement('div');
|
||||||
entryDiv.id = `item-${item.id}`; // Assign an ID to the div for highlighting
|
entryDiv.id = `item-${item.id}`; // Assign an ID to the div for highlighting
|
||||||
entryDiv.classList.add('ttsListItem'); // Add a class for styling
|
entryDiv.classList.add('ttsListItem'); // Add a class for styling
|
||||||
entryDiv.id = `item-${item.id}`; // Make sure this is unique and correct
|
|
||||||
|
|
||||||
// Update the Play/Stop button's onclick to call a function that handles playing and highlighting
|
// Update the Play/Stop button's onclick to call a function that handles playing and highlighting
|
||||||
entryDiv.innerHTML = `
|
entryDiv.innerHTML = `
|
||||||
<button onclick="regenerateTTS(${item.id})">Regenerate</button>
|
<button onclick="regenerateTTS(${item.id})">Regenerate</button>
|
||||||
<button onclick="playSound('${item.fileUrl}', ${item.id})">Play/Stop</button>
|
<button onclick="playSound('${item.fileUrl}', ${item.id})">Play/Stop</button>
|
||||||
<span class="label">ID:</span> <span class="value">${item.id}</span>
|
<span class="label">ID:</span> <span class="value">${item.id}</span>
|
||||||
<span class="label">Voice:</span> <span class="value">${item.characterVoice}</span>
|
<span class="label">Voice:</span> <span class="value">${item.characterVoice}</span>
|
||||||
<span class="label">Language:</span> <span class="value">${item.language}</span>
|
<span class="label">Language:</span> <span class="value">${item.language}</span>
|
||||||
<span class="label">Wav:</span> <span class="value">${wavFileName}</span>
|
<span class="label">Wav:</span> <span class="value">${wavFileName}</span>
|
||||||
<button id="edit-btn-${item.id}" class="edit-btn" onclick="editText(${item.id})">Edit</button>
|
<button id="edit-btn-${item.id}" class="edit-btn" onclick="editText(${item.id})">Edit</button>
|
||||||
<span class="item-field text-preview value" title="${item.text}" data-fulltext="${item.text}">${displayText}</span>
|
<span class="item-field text-preview value" title="${item.text}" data-fulltext="${item.text}">${displayText}</span>
|
||||||
`;
|
`;
|
||||||
listDisplay.appendChild(entryDiv);
|
listDisplay.appendChild(entryDiv);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update pagination controls
|
||||||
|
const lastPage = Math.ceil(ttsList.length / itemsPerPage);
|
||||||
|
document.getElementById('pageIndicator').innerText = `Page ${currentPage} of ${lastPage}`;
|
||||||
|
document.getElementById('pageIndicator1').innerText = `Page ${currentPage} of ${lastPage}`;
|
||||||
|
document.getElementById('prevPage').disabled = (currentPage === 1);
|
||||||
|
document.getElementById('nextPage').disabled = (currentPage === lastPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function generateAndPlayRemote(chunk, language, characterVoice, volume) {
|
async function generateAndPlayRemote(chunk, language, characterVoice, volume) {
|
||||||
try {
|
try {
|
||||||
if (stopTTSGeneration) {
|
if (stopTTSGeneration) {
|
||||||
console.log("TTS generation stopped.");
|
console.log("TTS generation stopped.");
|
||||||
return; // Early return if stop flag is set
|
return; // Early return if stop flag is set
|
||||||
}
|
}
|
||||||
console.log("generateAndPlayRemote:", chunk);
|
|
||||||
const data = new URLSearchParams({
|
const data = new URLSearchParams({
|
||||||
text_input: chunk.trim(),
|
text_input: chunk.trim(),
|
||||||
text_filtering: "standard",
|
text_filtering: "standard",
|
||||||
@@ -913,13 +1087,10 @@
|
|||||||
src: [fileUrl],
|
src: [fileUrl],
|
||||||
volume: parseFloat(document.getElementById("volume").value),
|
volume: parseFloat(document.getElementById("volume").value),
|
||||||
onplay: function () {
|
onplay: function () {
|
||||||
console.log('Playback started for', fileUrl);
|
|
||||||
},
|
},
|
||||||
onend: function () {
|
onend: function () {
|
||||||
console.log('Playback finished for', fileUrl);
|
|
||||||
},
|
},
|
||||||
onpause: function () {
|
onpause: function () {
|
||||||
console.log('Playback paused for', fileUrl);
|
|
||||||
},
|
},
|
||||||
onloaderror: function (e) {
|
onloaderror: function (e) {
|
||||||
console.error('Load error for', fileUrl, ':', e);
|
console.error('Load error for', fileUrl, ':', e);
|
||||||
@@ -1054,15 +1225,26 @@
|
|||||||
function playNextLocalChunk() {
|
function playNextLocalChunk() {
|
||||||
if (audioQueue.length > 0 && currentlyPlayingIndex < audioQueue.length) {
|
if (audioQueue.length > 0 && currentlyPlayingIndex < audioQueue.length) {
|
||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
audioQueue[currentlyPlayingIndex++].play();
|
let currentSound = audioQueue[currentlyPlayingIndex];
|
||||||
|
currentSound.play();
|
||||||
|
|
||||||
|
// Once a sound finishes playing, unload it
|
||||||
|
currentSound.on('end', () => {
|
||||||
|
currentSound.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
currentlyPlayingIndex++;
|
||||||
} else {
|
} else {
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function stopPlayback() {
|
function stopPlayback() {
|
||||||
Howler.stop();
|
Howler.stop();
|
||||||
audioQueue = [];
|
audioQueue = [];
|
||||||
|
// Unload each sound in the queue
|
||||||
|
audioQueue.forEach(sound => sound.unload());
|
||||||
currentlyPlayingIndex = 0;
|
currentlyPlayingIndex = 0;
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
}
|
}
|
||||||
@@ -1102,7 +1284,6 @@
|
|||||||
const startFromIdElement = document.getElementById('startFromId');
|
const startFromIdElement = document.getElementById('startFromId');
|
||||||
if (startFromIdElement) {
|
if (startFromIdElement) {
|
||||||
startFromIdElement.setAttribute('value', '1');
|
startFromIdElement.setAttribute('value', '1');
|
||||||
console.log('Start From ID set to 1');
|
|
||||||
}
|
}
|
||||||
// Other initializations...
|
// Other initializations...
|
||||||
});
|
});
|
||||||
@@ -1122,6 +1303,7 @@
|
|||||||
// and highlight the corresponding item
|
// and highlight the corresponding item
|
||||||
playListFromIndex(startIndex);
|
playListFromIndex(startIndex);
|
||||||
highlightPlaying(startIndex + 1); // Assuming the list items are 1-indexed
|
highlightPlaying(startIndex + 1); // Assuming the list items are 1-indexed
|
||||||
|
updateCurrentPage(startIndex + 1); // Update the current page based on the playing item
|
||||||
} else {
|
} else {
|
||||||
// If list is set to pause, pause the current item
|
// If list is set to pause, pause the current item
|
||||||
// and remove highlighting
|
// and remove highlighting
|
||||||
@@ -1154,6 +1336,26 @@
|
|||||||
if (currentItem) {
|
if (currentItem) {
|
||||||
currentItem.classList.add('highlight');
|
currentItem.classList.add('highlight');
|
||||||
}
|
}
|
||||||
|
updateCurrentPage(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function updateCurrentPage(itemIndex) {
|
||||||
|
// Calculate the page number based on the item index
|
||||||
|
// Note: Ensure that the itemIndex is 1-based; if it's 0-based, add 1.
|
||||||
|
const newPage = Math.ceil(itemIndex / itemsPerPage);
|
||||||
|
|
||||||
|
// Update the current page and UI if the new page is different from the current page
|
||||||
|
if (currentPage !== newPage) {
|
||||||
|
currentPage = newPage; // Set the new current page
|
||||||
|
updateUIList(); // Refresh the list display to show the correct page
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optionally, update the 'Jump to Page' input to reflect the current page
|
||||||
|
const jumpToPageInput = document.getElementById('jumpToPage');
|
||||||
|
if (jumpToPageInput) {
|
||||||
|
jumpToPageInput.value = currentPage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1191,6 +1393,7 @@
|
|||||||
console.log('Index is out of bounds, stopping playback.');
|
console.log('Index is out of bounds, stopping playback.');
|
||||||
// Clear any highlights if out of bounds
|
// Clear any highlights if out of bounds
|
||||||
highlightPlaying(null);
|
highlightPlaying(null);
|
||||||
|
updateUIList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1212,6 +1415,14 @@
|
|||||||
if (startFromIdElement) {
|
if (startFromIdElement) {
|
||||||
startFromIdElement.value = '1';
|
startFromIdElement.value = '1';
|
||||||
}
|
}
|
||||||
|
const pageIndicator = document.getElementById('pageIndicator');
|
||||||
|
if (pageIndicator) {
|
||||||
|
pageIndicator.textContent = 'Page 1 of 1';
|
||||||
|
}
|
||||||
|
const pageIndicator1 = document.getElementById('pageIndicator1');
|
||||||
|
if (pageIndicator1) {
|
||||||
|
pageIndicator1.textContent = 'Page 1 of 1';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function editText(id) {
|
function editText(id) {
|
||||||
@@ -1424,6 +1635,70 @@
|
|||||||
//////// General Dcoument Listeners ////////
|
//////// General Dcoument Listeners ////////
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Event listeners for pagination controls
|
||||||
|
document.getElementById('prevPage').addEventListener('click', () => {
|
||||||
|
if (currentPage > 1) {
|
||||||
|
currentPage--;
|
||||||
|
updateUIList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('nextPage').addEventListener('click', () => {
|
||||||
|
const lastPage = Math.ceil(ttsList.length / itemsPerPage);
|
||||||
|
if (currentPage < lastPage) {
|
||||||
|
currentPage++;
|
||||||
|
updateUIList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize the list on page load
|
||||||
|
document.addEventListener('DOMContentLoaded', updateUIList);
|
||||||
|
|
||||||
|
|
||||||
|
// For the 'Previous' button at the bottom
|
||||||
|
document.getElementById('prevPage1').addEventListener('click', () => {
|
||||||
|
if (currentPage > 1) {
|
||||||
|
currentPage--;
|
||||||
|
updateUIList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// For the 'Next' button at the bottom
|
||||||
|
document.getElementById('nextPage1').addEventListener('click', () => {
|
||||||
|
let lastPage = Math.ceil(ttsList.length / itemsPerPage);
|
||||||
|
if (currentPage < lastPage) {
|
||||||
|
currentPage++;
|
||||||
|
updateUIList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleJumpButtonClick(event) {
|
||||||
|
// Determine which set of controls to use based on the button that was clicked
|
||||||
|
const suffix = event.target.id === 'jumpButton' ? '' : '1';
|
||||||
|
const jumpToInput = document.getElementById(`jumpToPage${suffix}`);
|
||||||
|
const jumpToValue = jumpToInput.value.trim(); // Get the trimmed value
|
||||||
|
const jumpTo = parseInt(jumpToValue, 10); // Parse the value as an integer
|
||||||
|
|
||||||
|
if (!isNaN(jumpTo)) {
|
||||||
|
let lastPage = Math.ceil(ttsList.length / itemsPerPage);
|
||||||
|
|
||||||
|
if (jumpTo >= 1 && jumpTo <= lastPage) {
|
||||||
|
currentPage = jumpTo;
|
||||||
|
updateUIList();
|
||||||
|
} else {
|
||||||
|
alert(`Please enter a valid page number between 1 and ${lastPage}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert("Please enter a number to jump to.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the event listener for both jump buttons
|
||||||
|
document.getElementById('jumpButton').addEventListener('click', handleJumpButtonClick);
|
||||||
|
document.getElementById('jumpButton1').addEventListener('click', handleJumpButtonClick);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Event listener for changing play type
|
// Event listener for changing play type
|
||||||
document.getElementById('playType').addEventListener('change', function () {
|
document.getElementById('playType').addEventListener('change', function () {
|
||||||
isStreamingMode = this.value === 'stream';
|
isStreamingMode = this.value === 'stream';
|
||||||
@@ -1545,11 +1820,13 @@
|
|||||||
adjustPlaybackAndChunkSize(savedPlayType); // Adjust selectability on page load
|
adjustPlaybackAndChunkSize(savedPlayType); // Adjust selectability on page load
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize playback based on preference
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
const savedPlayMode = localStorage.getItem('playMode');
|
const savedPlayMode = localStorage.getItem('playMode');
|
||||||
if (savedPlayMode) {
|
if (savedPlayMode) {
|
||||||
document.getElementById('playMode').value = savedPlayMode;
|
document.getElementById('playMode').value = savedPlayMode;
|
||||||
}
|
}
|
||||||
|
playModeValue = savedPlayMode || 'local'; // Default to 'local' if nothing is saved
|
||||||
|
});
|
||||||
|
|
||||||
// Initialize chunk size based on preference
|
// Initialize chunk size based on preference
|
||||||
const savedChunkSize = localStorage.getItem('chunkSize');
|
const savedChunkSize = localStorage.getItem('chunkSize');
|
||||||
|
|||||||
Reference in new issue
Block a user