teddybear082 commited on
Commit ·
3ab3c26
1
Parent(s): f459c16
add proper opus support
Browse filesOpenai compatible requires opus output as one of the formats which was not working before, create fixes through server and webui to support opus output
- README.md +1 -1
- app/services/audio.py +22 -2
- pyproject.toml +1 -0
- requirements.txt +1 -0
- static/js/app.js +2 -0
- templates/index.html +6 -2
README.md
CHANGED
|
@@ -154,7 +154,7 @@ with client.audio.speech.with_streaming_response.create(
|
|
| 154 |
| `model` | string | No | - | Ignored (for OpenAI compatibility) |
|
| 155 |
| `input` | string | Yes | - | Text to synthesize |
|
| 156 |
| `voice` | string | No | `alba` | Voice ID (see `/v1/voices`) |
|
| 157 |
-
| `response_format` | string | No | `mp3` | Output format: `mp3`, `wav`, `pcm`, `opus`, `flac` |
|
| 158 |
| `stream` | boolean | No | `false` | Enable streaming response |
|
| 159 |
|
| 160 |
## Custom Voices
|
|
|
|
| 154 |
| `model` | string | No | - | Ignored (for OpenAI compatibility) |
|
| 155 |
| `input` | string | Yes | - | Text to synthesize |
|
| 156 |
| `voice` | string | No | `alba` | Voice ID (see `/v1/voices`) |
|
| 157 |
+
| `response_format` | string | No | `mp3` | Output format: `mp3`, `wav`, `pcm`, `opus`, `aac`, `flac` |
|
| 158 |
| `stream` | boolean | No | `false` | Enable streaming response |
|
| 159 |
|
| 160 |
## Custom Voices
|
app/services/audio.py
CHANGED
|
@@ -63,12 +63,32 @@ def convert_audio(
|
|
| 63 |
if audio_tensor.dim() == 1:
|
| 64 |
audio_tensor = audio_tensor.unsqueeze(0)
|
| 65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
try:
|
| 67 |
-
torchaudio.save(buffer, audio_tensor, sample_rate, format=
|
| 68 |
buffer.seek(0)
|
| 69 |
return buffer
|
| 70 |
except Exception as e:
|
| 71 |
-
logger.error(f
|
| 72 |
raise
|
| 73 |
|
| 74 |
|
|
|
|
| 63 |
if audio_tensor.dim() == 1:
|
| 64 |
audio_tensor = audio_tensor.unsqueeze(0)
|
| 65 |
|
| 66 |
+
# Handle PCM raw bytes (no container)
|
| 67 |
+
if target_format == 'pcm':
|
| 68 |
+
try:
|
| 69 |
+
pcm_bytes = tensor_to_pcm_bytes(audio_tensor)
|
| 70 |
+
buffer.write(pcm_bytes)
|
| 71 |
+
buffer.seek(0)
|
| 72 |
+
return buffer
|
| 73 |
+
except Exception as e:
|
| 74 |
+
logger.error(f'Error converting audio to PCM: {e}')
|
| 75 |
+
raise
|
| 76 |
+
|
| 77 |
+
# Map OpenAI format names to torchaudio/backend supported format names
|
| 78 |
+
# torchaudio uses 'ogg' as the container for 'opus'
|
| 79 |
+
# 'aac' usually requires 'adts' or 'm4a'
|
| 80 |
+
actual_format = target_format
|
| 81 |
+
if actual_format == 'opus':
|
| 82 |
+
actual_format = 'ogg'
|
| 83 |
+
elif actual_format == 'aac':
|
| 84 |
+
actual_format = 'adts'
|
| 85 |
+
|
| 86 |
try:
|
| 87 |
+
torchaudio.save(buffer, audio_tensor, sample_rate, format=actual_format)
|
| 88 |
buffer.seek(0)
|
| 89 |
return buffer
|
| 90 |
except Exception as e:
|
| 91 |
+
logger.error(f"Error converting audio to {target_format} (backend format: {actual_format}): {e}")
|
| 92 |
raise
|
| 93 |
|
| 94 |
|
pyproject.toml
CHANGED
|
@@ -12,6 +12,7 @@ dependencies = [
|
|
| 12 |
"pocket-tts>=2.0.0",
|
| 13 |
"torch>=2.0.0,<=2.8.0",
|
| 14 |
"torchaudio>=2.0.0,<=2.8.0",
|
|
|
|
| 15 |
"scipy>=1.10.0",
|
| 16 |
"numpy>=1.24.0",
|
| 17 |
"soundfile>=0.12.0",
|
|
|
|
| 12 |
"pocket-tts>=2.0.0",
|
| 13 |
"torch>=2.0.0,<=2.8.0",
|
| 14 |
"torchaudio>=2.0.0,<=2.8.0",
|
| 15 |
+
"torchao==0.13.0",
|
| 16 |
"scipy>=1.10.0",
|
| 17 |
"numpy>=1.24.0",
|
| 18 |
"soundfile>=0.12.0",
|
requirements.txt
CHANGED
|
@@ -9,6 +9,7 @@ pocket-tts>=2.0.0
|
|
| 9 |
# Audio processing
|
| 10 |
torch>=2.0.0,<=2.8.0
|
| 11 |
torchaudio>=2.0.0,<=2.8.0
|
|
|
|
| 12 |
scipy>=1.10.0
|
| 13 |
numpy>=1.24.0
|
| 14 |
soundfile>=0.12.0
|
|
|
|
| 9 |
# Audio processing
|
| 10 |
torch>=2.0.0,<=2.8.0
|
| 11 |
torchaudio>=2.0.0,<=2.8.0
|
| 12 |
+
torchao==0.13.0
|
| 13 |
scipy>=1.10.0
|
| 14 |
numpy>=1.24.0
|
| 15 |
soundfile>=0.12.0
|
static/js/app.js
CHANGED
|
@@ -43,6 +43,8 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 43 |
if (fmt === 'mp3') {
|
| 44 |
infoLabel.textContent =
|
| 45 |
'Streaming is not available for MP3 (Server limitation). A full file will be generated and played.';
|
|
|
|
|
|
|
| 46 |
} else {
|
| 47 |
infoLabel.textContent = 'Streaming is not available for this format.';
|
| 48 |
}
|
|
|
|
| 43 |
if (fmt === 'mp3') {
|
| 44 |
infoLabel.textContent =
|
| 45 |
'Streaming is not available for MP3 (Server limitation). A full file will be generated and played.';
|
| 46 |
+
} else if (['opus', 'aac', 'flac'].includes(fmt)) {
|
| 47 |
+
infoLabel.textContent = `Streaming is not available for ${fmt.toUpperCase()}. A full file will be generated and played.`;
|
| 48 |
} else {
|
| 49 |
infoLabel.textContent = 'Streaming is not available for this format.';
|
| 50 |
}
|
templates/index.html
CHANGED
|
@@ -126,6 +126,9 @@ Hello! I am Pocket TTS, running locally on your machine. I can clone voices and
|
|
| 126 |
"
|
| 127 |
>
|
| 128 |
<option value="mp3">MP3</option>
|
|
|
|
|
|
|
|
|
|
| 129 |
<option value="wav" selected>WAV</option>
|
| 130 |
<option value="pcm">PCM (Raw)</option>
|
| 131 |
</select>
|
|
@@ -272,8 +275,9 @@ Hello! I am Pocket TTS, running locally on your machine. I can clone voices and
|
|
| 272 |
<td></td>
|
| 273 |
<td><code>mp3</code></td>
|
| 274 |
<td>
|
| 275 |
-
Audio format: <code>mp3</code>, <code>
|
| 276 |
-
<code>
|
|
|
|
| 277 |
</td>
|
| 278 |
</tr>
|
| 279 |
<tr>
|
|
|
|
| 126 |
"
|
| 127 |
>
|
| 128 |
<option value="mp3">MP3</option>
|
| 129 |
+
<option value="opus">Opus</option>
|
| 130 |
+
<option value="aac">AAC</option>
|
| 131 |
+
<option value="flac">FLAC</option>
|
| 132 |
<option value="wav" selected>WAV</option>
|
| 133 |
<option value="pcm">PCM (Raw)</option>
|
| 134 |
</select>
|
|
|
|
| 275 |
<td></td>
|
| 276 |
<td><code>mp3</code></td>
|
| 277 |
<td>
|
| 278 |
+
Audio format: <code>mp3</code>, <code>opus</code>,
|
| 279 |
+
<code>aac</code>, <code>flac</code>, <code>wav</code>,
|
| 280 |
+
<code>pcm</code>
|
| 281 |
</td>
|
| 282 |
</tr>
|
| 283 |
<tr>
|