从flask中获取随机wav并交换音频中的src

问题描述 投票:0回答:1

基本情况: 从带有 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)

我尝试使用不同的分隔符 \ 和 / 并在静态前缀之前剪切 / 。我真的不知道错误从何而来

javascript html flask button audio
1个回答
0
投票

使用的分隔符应该是

/

不幸的是,我无法用给出的示例重现您的问题。

尽管如此,这是我的示例,加载所有源和声音,然后能够根据按下的按钮迭代声音。

应用程序.py
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)
模板/index.html
<!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>
© www.soinside.com 2019 - 2024. All rights reserved.