@python3_10
В процессе познания

Working outside of request context – как передать переменную через пост с формы (flask)?

Есть сниппет тинькофф войскит.
Локально все запускается и работает, удается сгенерировать аудио из текста при запуске 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>


Структура проекта:

645824a503c4b122405657.jpeg

Все остальные файлы сниппета остались без изменения, если надо могу приложить код.

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)
  • Вопрос задан
  • 106 просмотров
Решения вопроса 1
@python3_10 Автор вопроса
В процессе познания
Нашли с одним товарищем решение, возможно, кому-то будет полезно.
Правильный скрипт:
#!/usr/bin/env python3

import sys
import time
sys.path.append("..")
from flask import Flask, render_template, request as flask_request, send_from_directory
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='/')


storage = os.path.join(app.root_path, "storage")
if not os.path.exists(os.path.join(app.root_path, storage)):
    os.makedirs(storage)


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/build_request', methods=['POST'])
def route_build_request_post():
    data_text: str = flask_request.form.get('data_text')
    speaker_name = flask_request.form.get('speaker_name')

    filename = f'{time.strftime("%H-%M-%S", time.localtime())}.wav'

    # with open(os.path.join(storage, filename), "wb") as f:f.write(data_text.encode())
    with wave.open(filename, "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 send_from_directory(storage, filename, as_attachment=True)


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)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы