Add ability to play audio on server

This commit is contained in:
Michael Hansen 2022-06-07 16:51:41 -04:00
commit 70177bcfc5
4 changed files with 34 additions and 6 deletions

View file

@ -19,6 +19,8 @@ import dataclasses
import json
import logging
import re
import shlex
import subprocess
import typing
from pathlib import Path
from queue import Queue
@ -163,7 +165,7 @@ def get_app(args: argparse.Namespace, request_queue: Queue, temp_dir: str):
)
@app.route("/api/tts", methods=["GET", "POST"])
async def app_tts() -> Response:
async def app_tts() -> typing.Union[Response, str]:
"""Speak text to WAV."""
tts_args: typing.Dict[str, typing.Any] = {
"length_scale": args.length_scale,
@ -224,7 +226,15 @@ def get_app(args: argparse.Namespace, request_queue: Queue, temp_dir: str):
TextToWavParams(text=text, **tts_args), no_cache=no_cache
)
return Response(wav_bytes, mimetype="audio/wav")
audio_target = request.args.get("audioTarget", "client").strip().lower()
if audio_target == "client":
return Response(wav_bytes, mimetype="audio/wav")
# Play audio on server
play_cmd = shlex.split(args.play_program)
subprocess.run(play_cmd, input=wav_bytes, check=True)
return "OK"
@app.route("/api/voices", methods=["GET"])
async def api_voices():

View file

@ -90,6 +90,9 @@ def get_args(argv=None) -> argparse.Namespace:
"--default-voice",
help="Default voice key to select in web interface",
)
parser.add_argument(
"--play-program", default="aplay -q", help="Program to play WAV audio on server"
)
parser.add_argument(
"--no-show-openapi", action="store_true", help="Don't show OpenAPI link"
)

View file

@ -115,6 +115,15 @@
<button id="copy-voice" class="btn btn-info btn-sm" title="Copy voice key to clipboard">Copy</button>
</div>
</div>
<div class="row mt-3">
<div class="col-auto">
<label for="audio-target" title="Audio target">Play audio on:</label>
<select id="audio-target" name="audio-target">
<option value="client" selected>Client</value>
<option value="server">Server</value>
</select>
</div>
</div>
<div id="audio-message" class="row mt-3" hidden>
<div class="col">
<audio id="audio" preload="none" controls autoplay hidden></audio>
@ -302,6 +311,8 @@
var ssml = q('#ssml').checked || 'false'
var audioTarget = q('#audio-target').value || 'client'
q('#audio-message').hidden = false
q('#audio').pause()
@ -313,7 +324,8 @@
'&noiseScale=' + encodeURIComponent(noiseScale) +
'&noiseW=' + encodeURIComponent(noiseW) +
'&lengthScale=' + encodeURIComponent(lengthScale) +
'&ssml=' + encodeURIComponent(ssml),
'&ssml=' + encodeURIComponent(ssml) +
'&audioTarget=' + encodeURIComponent(audioTarget),
{cache: 'no-cache'})
if (res.ok) {
@ -322,8 +334,11 @@
q('#message').innerHTML = (elapsedTime / 1000).toFixed(3) + ' second(s)'
q('#speak-button').disabled = false
q('#audio').src = URL.createObjectURL(blob)
q('#audio').hidden = false
if (audioTarget != 'server') {
q('#audio').src = URL.createObjectURL(blob)
q('#audio').hidden = false
}
} else {
message = await res.text()
q('#message').textContent = message

View file

@ -1 +1 @@
0.2.0
0.2.1