[英]"dependent drop down list" does't work [Flask on Google App Engine]
我是編碼初學者。 我想使用 Google Cloud Text to Speech API 制作一個簡單的 Web 應用程序。
我是日本的英語老師,所以我希望我的學生使用這個網站來提高他們的英語發音。
首先,我想告訴你我的問題。
我幾乎完成了我的網絡應用程序。 然而,出現了一個問題。 相關下拉列表不起作用。 當用戶使用該應用程序時,她會選擇國家/地區和語音 ID。
如果您選擇 US--> 您可以選擇 en-US-Wavenet-A 或 en-US-Wavenet-B 或 en-US-Wavenet-C。
如果您選擇 GB--> 您可以選擇 en-GB-Wavenet-A 或 en-GB-Wavenet-B 或 en-GB-Wavenet-C。
如果您選擇美國,它可以完美運行。 但是,如果選擇GB,就會出現問題。
即使選擇GB--> en-GB-Wavenet-B,您下載的mp3文件聽起來像en-GB-Wavenet-A。
此外,即使選擇GB--> en-GB-Wavenet-C,您下載的mp3文件聽起來像en-GB-Wavenet-A。
其次,我想向您展示我的代碼。 我在 Google App Engine 標准環境 Python3.7 上使用 Flask。
這是目錄結構。
.
├── app.yaml
├── credentials.json
├── main.py
├── requirements.txt
└── templates
└── index.html
這是main.py。
from flask import Flask
from flask import render_template
from flask import request
from flask import send_file
import os
from google.cloud import texttospeech
app = Flask(__name__)
@app.route("/", methods=['POST', 'GET'])
def index():
if request.method == "POST":
ssml = '<speak><prosody rate="slow">' + request.form['text'] + '</prosody></speak>'
language = request.form['language']
voiceid = request.form['voiceId']
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="credentials.json"
client = texttospeech.TextToSpeechClient()
input_text = texttospeech.types.SynthesisInput(ssml=ssml)
voice = texttospeech.types.VoiceSelectionParams(
language_code=language,
name=voiceid)
audio_config = texttospeech.types.AudioConfig(
audio_encoding=texttospeech.enums.AudioEncoding.MP3)
response = client.synthesize_speech(input_text, voice, audio_config)
# The response's audio_content is binary.
with open('/tmp/output.mp3', 'wb') as out:
out.write(response.audio_content)
return send_file("/tmp/output.mp3",as_attachment=True)
else:
return render_template("index.html")
if __name__ == "__main__":
app.run()
這是index.html(有些解釋是用日文寫的,對不起。)。
<html>
<head>
<style>
#text {width: 100%; height: 300px;}
</style>
<script type="text/javascript">
// ▼HTMLの読み込み直後に実行:
document.addEventListener('DOMContentLoaded', function() {
// ▼2階層目の要素を全て非表示にする
var allSubBoxes = document.getElementsByClassName("subbox");
for( var i=0 ; i<allSubBoxes.length ; i++) {
allSubBoxes[i].style.display = 'none';
}
});
</script>
<script type="text/javascript">
// ▼HTMLの読み込み直後に実行:
document.addEventListener('DOMContentLoaded', function() {
// ▼全てのプルダウンメニューセットごとに処理
var mainBoxes = document.getElementsByClassName('pulldownset');
for( var i=0 ; i<mainBoxes.length ; i++) {
var mainSelect = mainBoxes[i].getElementsByClassName("mainselect"); // 1階層目(メイン)のプルダウンメニュー(※後でvalue屬性値を參照するので、select要素である必要があります。)
mainSelect[0].onchange = function () {
// ▼同じ親要素に含まれているすべての2階層目(サブ)要素を消す
var subBox = this.parentNode.getElementsByClassName("subbox"); // 同じ親要素に含まれる.subbox(※select要素に限らず、どんな要素でも構いません。)
for( var j=0 ; j<subBox.length ; j++) {
subBox[j].style.display = 'none';
}
// ▼指定された2階層目(サブ)要素だけを表示する
if( this.value ) {
var targetSub = document.getElementById( this.value ); // 「1階層目のプルダウンメニューで選択されている項目のvalue屬性値」と同じ文字列をid屬性値に持つ要素を得る
targetSub.style.display = 'inline';
}
}
}
});
</script>
</head>
<body>
<form action="/" method="POST">
<div class="pulldownset">
<!-- ========================================== -->
<select class="mainselect" name="language">
<option value="">country</option>
<option value="en-US">US</option>
<option value="en-GB">GB</option>
</select>
<!-- ================================================================ -->
<select id="en-US" class="subbox" name="voiceId">
<option value="">voice</option>
<option value="en-US-Wavenet-A">en-US-Wavenet-A</option>
<option value="en-US-Wavenet-B">en-US-Wavenet-B</option>
<option value="en-US-Wavenet-C">en-US-Wavenet-C</option>
</select>
<!-- ================================================================ -->
<select id="en-GB" class="subbox" name="voiceId">
<option value="">en-GB</option>
<option value="en-GB-Wavenet-A">en-GB-Wavenet-A</option>
<option value="en-GB-Wavenet-B">en-GB-Wavenet-B</option>
<option value="en-GB-Wavenet-C">en-GB-Wavenet-C</option>
</select>
</div>
<textarea id="text" name="text" placeholder="input text here"></textarea>
<input type="submit" value="download">
</form>
</body>
</html>
這是requirements.txt。
Flask==1.1.1
future==0.18.2
google-cloud-texttospeech==0.5.0
grpcio==1.26.0
gunicorn
這是 app.yaml。
runtime: python37
entrypoint: gunicorn -b :$PORT main:app
我以為這是JavaScript的問題,於是上網查了一下。 但是,我無法得到答案。
你能給我任何信息或建議嗎?
先感謝您。
真誠的,和
您的問題是您有 2 個同名的選擇輸入。
當向服務器發送請求時,它只選擇第一個,這可以是英國語音的默認值,也可以是美國語音(如果之前已選擇)。
為了使用具有相同名稱的多個輸入,您需要使用一對括號指定它們的名稱,如下所示:
<select id="en-US" class="subbox" name="voiceId[]">
和
<select id="en-GB" class="subbox" name="voiceId[]">
在服務器端,您可以查找語言 ID 的第一次出現以確定列表中的哪些項目應分配給變量。
所以而不是:
voiceid = request.form['voiceId']
你會有類似的東西:
voiceid = next(voice for voice in request.form.getlist('voiceId[]') if language in voice)
編輯:
下面是一個沒有生成器表達式的替代方案。
voices = []
for voice in request.form.getlist('voiceId[]'):
if language in voice:
voices.append(voice)
voiceid = next(iter(voices))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.