基本情况: 从带有 3 个按钮的 HTML 页面开始,用于 3 种不同类型的声音(sound0(例如拒绝声音)、sound1(例如批准声音)、sound2(例如笑声)),我想在“页面加载”上将文件类型 POST 到Flask 服务器,它应该动态搜索此声音类型的单个实例并返回此路径(此行为当前是硬编码的,因为首先通信应该起作用)。我可以在 javascript 中接收此 url,但是这会返回(在 javascript 中)错误“加载资源失败:服务器响应状态为 404(未找到)”。实际上在接收路径时,应该交换音频源。对所有 3 个按钮执行此操作后,应通过播放 sound0 来触发播放循环(每 3 个文件迭代)。这些文件当前位于服务器上的 app/static/soundfiles/SOME_DEEPER_PATH_TO_CERTAIN_WAV.wav 中。 我目前不明白出了什么问题,我很高兴获得有关此问题的帮助。 到目前为止我的代码:
button_page.html:(位于app/templates/button_page.html)
<!DOCTYPE html>
<html>
<head>
<style>
.button-row {
display: flex;
justify-content: center;
margin-top: 30px;
}
.question {
font-weight: bold;
font-size: 20px;
margin-bottom: 10px;
color: white; /* Set the text color to white */
}
.error{
color: red;
display: none;
margin-top: 5px;
}
.end_button {
position: relative;
bottom: -80px;
margin-bottom: 100px;
left: 125%;
transform: translateX(-50%);
}
.button {
min-width: 150px;
min-height: 50px;
font-family: 'Nunito', sans-serif;
font-size: 16px;
text-transform: uppercase;
letter-spacing: 1.3px;
font-weight: 700;
color: #313133;
background: #E592F6;
z-index: 2;
background: linear-gradient(90deg, rgba(229,146,246,1) 0%, rgb(196, 119, 213) 100%);
border: none;
border-radius: 1000px;
box-shadow: 12px 12px 24px rgba(229,146,246,.64);
transition: all 0.3s ease-in-out 0s;
cursor: pointer;
outline: none;
position: relative;
padding: 10px;
}
.wrapper_loading{
width:200px;
height:60px;
position: absolute;
left:50%;
margin-top: 150px;
transform: translate(-50%, -50%);
visibility: hidden;
}
.circle{
width:20px;
height:20px;
position: absolute;
border-radius: 50%;
background-color: #E592F6;
left:15%;
transform-origin: 50%;
animation: circle .5s alternate infinite ease;
}
@keyframes circle{
0%{
top:60px;
height:5px;
border-radius: 50px 50px 25px 25px;
transform: scaleX(1.7);
}
40%{
height:20px;
border-radius: 50%;
transform: scaleX(1);
}
100%{
top:0%;
}
}
.circle:nth-child(2){
left:45%;
animation-delay: .2s;
}
.circle:nth-child(3){
left:auto;
right:15%;
animation-delay: .3s;
}
.shadow{
width:20px;
height:4px;
border-radius: 50%;
background-color: rgba(148, 98, 160, 0.5);
position: absolute;
top:62px;
transform-origin: 50%;
z-index: -1;
left:15%;
filter: blur(1px);
animation: shadow .5s alternate infinite ease;
}
@keyframes shadow{
0%{
transform: scaleX(1.5);
}
40%{
transform: scaleX(1);
opacity: .7;
}
100%{
transform: scaleX(.2);
opacity: .4;
}
}
.shadow:nth-child(4){
left: 45%;
animation-delay: .2s
}
.shadow:nth-child(5){
left:auto;
right:15%;
animation-delay: .3s;
}
.wrapper_loading span{
position: absolute;
top:75px;
bottom:75px;
font-family: 'Nunito', sans-serif;
font-size: 20px;
letter-spacing: 12px;
color: #E592F6;;
left:15%;
}
.submit-wrapper {
display: grid;
grid-template-columns: repeat(10, 1fr);
gap: 10px;
grid-auto-rows: minmax(100px, auto);
}
.wrapper {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 10px;
grid-auto-rows: minmax(100px, auto);
}
</style>
</head>
<body>
<audio id="voice0" onended="playVoice1()" onpause="stop_ring_0()">
</audio><audio id="voice1" onended="playVoice2()" onpause="stop_ring_1()"></audio>
<audio id="voice2" onended="playVoice1()" onpause="stop_ring_2()"></audio>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="{{url_for('static', filename='js/js_tmp.js')}}"></script>
<div class="wrap">
<hr class="top-hr">
<div class="wrapper_loading" id="wrapper_loading_id">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="shadow"></div>
<div class="shadow"></div>
<div class="shadow"></div>
<!-- <span class="synthesizing_loader_text">Loading</span> -->
</div>
</div>
<div class="button-row" id="button-container"></div>
<div class="button-row">
<button id="button-id1" class="button" onclick="playSoundType1()">Sound Type1</button>
<button id="button-id2" class="button" onclick="playSoundType2()">Sound Type2</button>
<button id="button-id3" class="button" onclick="playSoundType3()">Sound Type3</button>
</div>
<script>
init_button_sounds();
</script>
</body>
</html>
js_tmp.js位于static/js/js_tmp.js:
function init_button_sounds() {
init_button_sound("voice0")
init_button_sound("voice1")
init_button_sound("voice2")
playSoundType1();
}
function init_button_sound(audio_id, rd) {
var route = '/getaudio'.concat(audio_id.slice(-1))
var rd = String(Date.now())
$.post(route).done(
function(response) {
var audio_path=response['audioFilePath']
var audio_element=document.getElementById(audio_id);
// assemble source.src & attach to audio
var source = document.createElement('source');
source.src = audio_path;
// Append the source to the audio element
audio_element.appendChild(source);
// Load the new audio source
document.getElementById(audio_id).load();
}
).fail(
function() {
alert("Something failed. Please load again.");
}
);
}
function playSoundType1(){
stopAllVoices()
playVoice0()
}
function playSoundType2(){
stopAllVoices()
playVoice1()
}
function playSoundType3(){
stopAllVoices()
playVoice2()
}
function stopAllVoices(){
stop_ring_0()
stop_ring_1()
stop_ring_2()
document.getElementById('voice0').pause();
document.getElementById('voice1').pause();
document.getElementById('voice2').pause();
}
function playVoice0(){
document.getElementById('voice0').play();
stop_ring_1()
stop_ring_2()
start_ring_0()
}
function playVoice2(){
document.getElementById('voice2').play();
stop_ring_1()
stop_ring_0()
start_ring_2()
}
function playVoice1(){
document.getElementById('voice1').play();
stop_ring_2()
stop_ring_0()
start_ring_1()
}
function stop_ring_0(){
var styleElem = document.head.appendChild(document.createElement("style"));
styleElem.innerHTML = "#button-id1::after{animation:None;display:None;}";
}
function stop_ring_1(){
var styleElem = document.head.appendChild(document.createElement("style"));
styleElem.innerHTML = "#button-id2::after{animation:None;display:None;}";
}
function stop_ring_2(){
var styleElem = document.head.appendChild(document.createElement("style"));
styleElem.innerHTML = "#button-id3::after{animation:None;display:None;}";
}
function start_ring_0(){
var styleElem2 = document.head.appendChild(document.createElement("style"));
styleElem2.innerHTML = "#button-id1::after{ animation:ring 1.5s infinite;display: block;}";
}
function start_ring_1(){
var styleElem2 = document.head.appendChild(document.createElement("style"));
styleElem2.innerHTML = "#button-id2::after{ animation:ring 1.5s infinite;display: block;}";
}
function start_ring_2(){
var styleElem2 = document.head.appendChild(document.createElement("style"));
styleElem2.innerHTML = "#button-id3::after{ animation:ring 1.5s infinite;display: block;}";
}
routes.py 在 app/routes.py
@app.route('/')
def button_page():
return render_template('button_page.html')
from pathlib import Path
sound1_path=Path('sound_files\\sound1\\a.wav')
sound2_path=Path('sound_files\\sound2\\b.wav')
sound3_path=Path('sound_files\\sound3\\c.wav')
@app.route('/getaudio<string:id>', methods=['GET','POST'])
def getaudio(id):
from flask import url_for
id_str = id
sound_path=None
if id_str=='0':
sound_path=sound1_path
elif id_str=='1':
sound_path=sound2_path
elif id_str=='2':
sound_path=sound3_path
audio_url = url_for('static', filename=str(sound_path))
return(jsonify({'audioFilePath': str(audio_url) }))
def create_app():
from flask import Flask
app = Flask(__name__)
app.secret_key = "random"
return app
if __name__=="__main__":
app=create_app()
app.run(debug=True)
我尝试使用不同的分隔符 \ 和 / 并在静态前缀之前剪切 / 。我真的不知道错误从何而来
使用的分隔符应该是
/
。尽管如此,这是我的示例,加载所有源和声音,然后能够根据按下的按钮迭代声音。
from flask import (
Flask,
abort,
jsonify,
render_template,
url_for
)
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.post('/sound-<int:id>')
def sound(id):
sounds = (
'sound_files/sound1/a.wav',
'sound_files/sound2/b.wav',
'sound_files/sound3/c.wav',
)
if 0 <= id < len(sounds):
return jsonify(src=url_for('static', filename=sounds[id]))
abort(404)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index</title>
<style>
#button-group {
display: None;
}
.button-row {
display: flex;
justify-content: center;
margin: 2rem;
gap: 1rem;
}
.visible#button-group, .visible#spinner {
display: block;
}
#spinner {
position: absolute;
bottom: 0;
right: 0;
margin: 4px;
width: 32px;
height: 32px;
border: 3px solid #ccc;
border-bottom-color: transparent;
border-radius: 50%;
display: None;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div id="spinner" class="visible"></div>
<div id="button-group">
<div class="button-row">
<button>Sound Type1</button>
<button>Sound Type2</button>
<button>Sound Type3</button>
</div>
</div>
<script type="text/javascript">
(function() {
// Load source using given id.
const loadSource = async (id) => {
return fetch(`/sound-${id}`, { method: 'post' })
.then(resp => {
if (!resp.ok) throw new Error('Something went wrong. (01)');
return resp.json();
})
.then(data => {
if (!data['src']) throw new Error('Something went wrong. (02)');
return data['src'];
});
};
// Load the sound with the given source and wait until it is playable.
const loadAudio = (src) => {
return new Promise((resolve, reject) => {
const audio = new Audio(src);
audio.preload = 'auto';
audio.addEventListener('canplaythrough', () => resolve(audio));
audio.addEventListener('error', (err) => reject(err));
});
};
const loadSounds = () => {
const soundIds = [0, 1, 2];
Promise.all(soundIds.map(loadSource)).then(async (srcs) => {
console.log('All sources retrieved.');
try {
// Load all sounds.
const sounds = await Promise.all(srcs.map(loadAudio));
console.log('All sounds loaded.');
// Register listeners to play next sound.
let current = 0;
sounds.forEach(sound => {
sound.addEventListener('ended', () => {
sounds[++current % sounds.length].play();
});
});
// Register all click listeners.
document.querySelectorAll('#button-group button').forEach((btn, i) => {
btn.addEventListener('click', () => {
// Stop and reset all sounds.
sounds.forEach(snd => {
snd.pause();
snd.currentTime = 0;
})
// Play sound.
sounds[current = i].play();
});
});
// Show all buttons as soon as all sounds are playable.
const buttonGroup = document.getElementById('button-group');
buttonGroup && buttonGroup.classList.toggle('visible');
// Hide the loading indicator.
const spinner = document.getElementById('spinner');
spinner && spinner.classList.toggle('visible');
} catch(err) {
console.error('Something went wrong. (03)');
}
}).catch(console.error);
};
loadSounds();
})();
</script>
</body>
</html>