Есть сниппет тинькофф войскит.
Локально все запускается и работает, удается сгенерировать аудио из текста при запуске main.py – генерируем файл в формате wav.
Я добавил flask в сниппет и обернул функции в роуты (как мне кажется, но если что – поправьте).
По задумке, когда запускается flask, ничего происходить не должно до момента, пока не нажмешь сабмит. Тогда из textarea в переменную записывается текст и передается в функцию.
(дальнейшая доработка – страница с ссылкой для скачивания, но это потом).
На деле происходит следующее: сразу при запуске main.py запускается функция синтеза и создает файл.
Однако это только полбеды, потому что если я хочу передать текст из textarea в таком формате: txt = request.form['data-text'] – то получают ошибку: Working outside of request context. Про контекст гуглил/яндексил, не помогло.
Возможно я упускаю логику, буду очень признателен, если направите в нужное русло.
Коротко – как передать с фронта в переменную текст?
Немного наглостиБыло бы круто еще понять, как запускать функцию после сабмита. Предполагаю, сейчас проблема в логике.
Дока по voiekit
оригинальный код сниппетов
Мой код (main.py):
#!/usr/bin/env python3
import sys
import time
sys.path.append("..")
from flask import Flask, render_template, request, copy_current_request_context, current_app
import ssl
from tinkoff.cloud.tts.v1 import tts_pb2_grpc, tts_pb2
from auth import authorization_metadata
import grpc
import os
import wave
endpoint = os.environ.get("VOICEKIT_ENDPOINT") or "api.tinkoff.ai:443"
api_key = os.environ["VOICEKIT_API_KEY"]
secret_key = os.environ["VOICEKIT_SECRET_KEY"]
txt = "Это просто переменная, из которой я передаю текст."
spk = 'dorofeev'
sample_rate = 48000
ssl.create_default_https_context = ssl._create_unverified_context
app = Flask(__name__, static_folder='/')
#txt = request.form['data-text']
filename = time.strftime("%H-%M-%S", time.localtime())
@app.route('/')
def index():
return render_template('index.html')
@app.route('/build_request', methods=['POST'])
def build_request():
return tts_pb2.SynthesizeSpeechRequest(
input=tts_pb2.SynthesisInput(
text=txt
),
audio_config=tts_pb2.AudioConfig(
audio_encoding=tts_pb2.LINEAR16,
sample_rate_hertz=sample_rate,
),
voice=tts_pb2.VoiceSelectionParams(
name=spk
),
)
with wave.open(f"{filename}.wav", "wb") as f:
f.setframerate(sample_rate)
f.setnchannels(1)
f.setsampwidth(2)
stub = tts_pb2_grpc.TextToSpeechStub(
grpc.secure_channel(endpoint, grpc.ssl_channel_credentials()))
request = build_request()
metadata = authorization_metadata(api_key, secret_key, "tinkoff.cloud.tts")
responses = stub.StreamingSynthesize(request, metadata=metadata)
for key, value in responses.initial_metadata():
if key == "x-audio-duration-seconds":
print("Estimated audio duration is {:.2f} seconds".format(float(value)))
break
for stream_response in responses:
f.writeframes(stream_response.audio_chunk)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3000, debug=True)
html шаблон, с которого должен приходить запрос:
<!DOCTYPE html>
<html>
<head>
<link rel= "stylesheet" type= "text/css" href= "static/style.css">
<title>
T-Dictor
</title>
</head>
<body>
<header>
<img src="static/img/logo.png" alt="" class="logo"> <h2>Text-To-Speech</h2>
</header>
<main>
<section class="content">
<h2 class="h3-synt">
Синтез речи из текста
</h2>
<form class="form-sender" action="/build_request" method="post">
<textarea placeholder="Введите текст в поле..." class="txt-inp" type="text" name="data_text"></textarea>
<button class="btn" type="submit" name= "form" value="Submit">Синтезировать речь</button>
<select name="speaker_name">
<option value="alyona">Алена</option>
<option value="dorofeev">Дорофеев</option>
</select>
</form>
</section>
</main>
</body>
Структура проекта:
Все остальные файлы сниппета остались без изменения, если надо могу приложить код.
UPD:
Поправили код main.py, получаю новую ошибку argument should be a bytes-like object or ASCII
#!/usr/bin/env python3
import sys
import time
sys.path.append("..")
from flask import Flask, render_template, request as flask_request, redirect
import ssl
from tinkoff.cloud.tts.v1 import tts_pb2_grpc, tts_pb2
from auth import authorization_metadata
import grpc
import os
import wave
endpoint = os.environ.get("VOICEKIT_ENDPOINT") or "api.tinkoff.ai:443"
api_key = os.environ.get("VOICEKIT_API_KEY")
secret_key = os.environ.get("VOICEKIT_SECRET_KEY")
# txt = 'текст, который мы передаем в переменную для синтеза речи.'
# spk = 'alyona'
# txt = request.form['data-text']
sample_rate = 48000
ssl.create_default_https_context = ssl._create_unverified_context
app = Flask(__name__, static_folder='/')
@app.route('/')
def index():
return render_template('index.html')
@app.route('/build_request', methods=['POST'])
def route_build_request_post():
data_text = flask_request.form.get('data_text')
speaker_name = flask_request.form.get('speaker_name')
filename = time.strftime("%H-%M-%S", time.localtime())
with wave.open(f"{filename}.wav", "wb") as f:
f.setframerate(sample_rate)
f.setnchannels(1)
f.setsampwidth(2)
stub = tts_pb2_grpc.TextToSpeechStub(
grpc.secure_channel(endpoint, grpc.ssl_channel_credentials()))
request = build_request(data_text, speaker_name)
metadata = authorization_metadata(api_key, secret_key, "tinkoff.cloud.tts")
responses = stub.StreamingSynthesize(request, metadata=metadata)
for key, value in responses.initial_metadata():
if key == "x-audio-duration-seconds":
print("Estimated audio duration is {:.2f} seconds".format(float(value)))
break
for stream_response in responses:
f.writeframes(stream_response.audio_chunk)
return redirect("/")
def build_request(text, name):
return tts_pb2.SynthesizeSpeechRequest(
input=tts_pb2.SynthesisInput(
text=text
),
audio_config=tts_pb2.AudioConfig(
audio_encoding=tts_pb2.LINEAR16,
sample_rate_hertz=sample_rate,
),
voice=tts_pb2.VoiceSelectionParams(
name=name,
),
)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3000, debug=True)