teddybear082 commited on
Commit ·
3cf437a
1
Parent(s): 3ccc35e
update to pocket-tts 1.03
Browse files-support cloning of .mp3 and .flac files
- frozen_requirements.txt +0 -0
- pocket_tts_openai_server.py +12 -8
- static/js/app.js +3 -3
- templates/index.html +3 -3
frozen_requirements.txt
CHANGED
|
Binary files a/frozen_requirements.txt and b/frozen_requirements.txt differ
|
|
|
pocket_tts_openai_server.py
CHANGED
|
@@ -133,16 +133,20 @@ def list_voices():
|
|
| 133 |
|
| 134 |
# 2. Scan Directory if configured
|
| 135 |
if VOICES_DIR and os.path.isdir(VOICES_DIR):
|
| 136 |
-
#
|
| 137 |
-
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
name = os.path.basename(f)
|
| 140 |
# ID is the full path so the server can access it, or just filename if we handle resolution
|
| 141 |
-
#
|
| 142 |
-
# Using filename is nicer for UI, but 'voice' parameter needs to be resolvable.
|
| 143 |
-
# get_voice_state logic handles checking VOICES_DIR.
|
| 144 |
voices.append({
|
| 145 |
-
"id": name,
|
| 146 |
"name": f"Local: {name}"
|
| 147 |
})
|
| 148 |
|
|
@@ -252,7 +256,7 @@ def main():
|
|
| 252 |
parser.add_argument("--host", type=str, default="0.0.0.0", help="Host to run server")
|
| 253 |
parser.add_argument("--port", type=int, default=5002, help="Port to run server")
|
| 254 |
parser.add_argument("--stream", action="store_true", help="Enable streaming by default")
|
| 255 |
-
parser.add_argument("--voices_dir", type=str, default=None, help="Directory containing local voice .wav files")
|
| 256 |
|
| 257 |
args = parser.parse_args()
|
| 258 |
|
|
|
|
| 133 |
|
| 134 |
# 2. Scan Directory if configured
|
| 135 |
if VOICES_DIR and os.path.isdir(VOICES_DIR):
|
| 136 |
+
# Define supported extensions
|
| 137 |
+
extensions = ("*.wav", "*.mp3", "*.flac")
|
| 138 |
+
|
| 139 |
+
# Gather all matching files
|
| 140 |
+
audio_files = []
|
| 141 |
+
for ext in extensions:
|
| 142 |
+
audio_files.extend(glob.glob(os.path.join(VOICES_DIR, ext)))
|
| 143 |
+
|
| 144 |
+
for f in audio_files:
|
| 145 |
name = os.path.basename(f)
|
| 146 |
# ID is the full path so the server can access it, or just filename if we handle resolution
|
| 147 |
+
# Using filename for UI consistency as per original logic
|
|
|
|
|
|
|
| 148 |
voices.append({
|
| 149 |
+
"id": name,
|
| 150 |
"name": f"Local: {name}"
|
| 151 |
})
|
| 152 |
|
|
|
|
| 256 |
parser.add_argument("--host", type=str, default="0.0.0.0", help="Host to run server")
|
| 257 |
parser.add_argument("--port", type=int, default=5002, help="Port to run server")
|
| 258 |
parser.add_argument("--stream", action="store_true", help="Enable streaming by default")
|
| 259 |
+
parser.add_argument("--voices_dir", type=str, default=None, help="Directory containing local voice .wav, .mp3 or .flac files")
|
| 260 |
|
| 261 |
args = parser.parse_args()
|
| 262 |
|
static/js/app.js
CHANGED
|
@@ -16,7 +16,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 16 |
const data = await res.json();
|
| 17 |
|
| 18 |
// Clear existing except custom
|
| 19 |
-
voiceSelect.innerHTML = '<option value="custom">Custom (Upload .wav)...</option>';
|
| 20 |
|
| 21 |
if (data.data) {
|
| 22 |
// Add built-ins first
|
|
@@ -43,7 +43,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 43 |
voiceSelect.addEventListener('change', (e) => {
|
| 44 |
if (e.target.value === 'custom') {
|
| 45 |
// Setup for Custom Path
|
| 46 |
-
document.querySelector('#custom-voice-group label').textContent = "Absolute Path to
|
| 47 |
voiceFile.type = 'text';
|
| 48 |
voiceFile.placeholder = "C:\\path\\to\\voice.wav";
|
| 49 |
customVoiceGroup.classList.remove('hidden');
|
|
@@ -62,7 +62,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 62 |
let voice = voiceSelect.value;
|
| 63 |
if (voice === 'custom') {
|
| 64 |
voice = voiceFile.value.trim();
|
| 65 |
-
if (!voice) return alert("Please enter the path to the
|
| 66 |
}
|
| 67 |
|
| 68 |
generateBtn.classList.add('loading');
|
|
|
|
| 16 |
const data = await res.json();
|
| 17 |
|
| 18 |
// Clear existing except custom
|
| 19 |
+
voiceSelect.innerHTML = '<option value="custom">Custom (Upload .wav, .mp3, .flac)...</option>';
|
| 20 |
|
| 21 |
if (data.data) {
|
| 22 |
// Add built-ins first
|
|
|
|
| 43 |
voiceSelect.addEventListener('change', (e) => {
|
| 44 |
if (e.target.value === 'custom') {
|
| 45 |
// Setup for Custom Path
|
| 46 |
+
document.querySelector('#custom-voice-group label').textContent = "Absolute Path to Audio File:";
|
| 47 |
voiceFile.type = 'text';
|
| 48 |
voiceFile.placeholder = "C:\\path\\to\\voice.wav";
|
| 49 |
customVoiceGroup.classList.remove('hidden');
|
|
|
|
| 62 |
let voice = voiceSelect.value;
|
| 63 |
if (voice === 'custom') {
|
| 64 |
voice = voiceFile.value.trim();
|
| 65 |
+
if (!voice) return alert("Please enter the path to the voice file.");
|
| 66 |
}
|
| 67 |
|
| 68 |
generateBtn.classList.add('loading');
|
templates/index.html
CHANGED
|
@@ -28,13 +28,13 @@
|
|
| 28 |
<label for="voice-select">Voice Selection</label>
|
| 29 |
<select id="voice-select">
|
| 30 |
<!-- Populated by JS -->
|
| 31 |
-
<option value="custom">Custom (Upload .wav)...</option>
|
| 32 |
</select>
|
| 33 |
</div>
|
| 34 |
|
| 35 |
<div class="control-group hidden" id="custom-voice-group">
|
| 36 |
-
<label for="voice-file">Upload Reference Audio (WAV)</label>
|
| 37 |
-
<input type="file" id="voice-file" accept=".wav">
|
| 38 |
</div>
|
| 39 |
|
| 40 |
<div class="control-group">
|
|
|
|
| 28 |
<label for="voice-select">Voice Selection</label>
|
| 29 |
<select id="voice-select">
|
| 30 |
<!-- Populated by JS -->
|
| 31 |
+
<option value="custom">Custom (Upload .wav, .mp3, or .flac)...</option>
|
| 32 |
</select>
|
| 33 |
</div>
|
| 34 |
|
| 35 |
<div class="control-group hidden" id="custom-voice-group">
|
| 36 |
+
<label for="voice-file">Upload Reference Audio (WAV, MP3, FLAC)</label>
|
| 37 |
+
<input type="file" id="voice-file" accept=".wav,.mp3,.flac">
|
| 38 |
</div>
|
| 39 |
|
| 40 |
<div class="control-group">
|