首页 > 解决方案 > 无法使用烧瓶和 render_template 选项获取所需的 html 页面

问题描述

我是网络开发的新手,我正在尝试构建一个在线记录器并将一些数据作为音频的反馈(通过单击 index.html 中的上传获得)发送回 results.html

我尝试在我的 python flask app.py 文件中创建一些打印语句,以检查是否在事件中触发了“POST”,它可以工作并在命令提示符中打印我想要的数据列表。但最后它没有重定向到 results.html 而是再次显示 index.html

大部分代码和含义取自

https://blog.addpipe.com/using-recorder-js-to-capture-wav-audio-in-your-html5-web-site/

用 recorder.js 录制语音并将其上传到 python-flask 服务器,但 WAV 文件已损坏

Python 文件

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask
from flask import request
from flask import render_template
import os
import random
import datetime
from detections import clean_dir,get_speech_info
from shutil import copyfile
import numpy as np
import json
from flask import Flask, redirect, url_for, request

app = Flask(__name__)

questions = ['Tell Me About Yourself.',
'Why Should We Hire You?',
' What is Your Greatest Strength?',
'What is Your Greatest Weakness?',
'What Are Your Salary Expectations?',
'How Do You Handle Stress and Pressure?',
'Describe a Difficult Work Situation or Project and How You Handled It.',
'What Are Your Goals for The Future?',
]


@app.route('/<usr>',methods = ['GET'])  
def user(usr):
    return f"<h1>hello {usr}</h1>"

data = np.zeros((6))

@app.route("/", methods=['POST', 'GET'])
def index():
    num1 = random.randint(0, len(questions)-1)
    ques = questions[num1]
    

    if request.method == "POST":
        f  = request.files['audio_data']
        basepath = os.path.dirname(__file__)
        x = str(datetime.datetime.now()).replace(" ", "").replace(":","").replace(".","-")+'.wav'

        clean_dir(basepath+'/audio/')

        with open('audio/'+x, 'wb') as audio:
            f.save(audio)
        
        print('file uploaded successfully')

        global data
        data = np.array(get_speech_info(basepath+'/rough')[0])

        clean_dir(basepath+'/rough/')
        print(data,'post is fired')
        return render_template('results.html', data=data)

    else:
        print(data,'basic file')
        return render_template("index.html",q = ques)

if __name__ == "__main__":
    app.run(debug = True)

JavaScript

//webkitURL is deprecated but nevertheless
URL = window.URL || window.webkitURL;

var gumStream;                      //stream from getUserMedia()
var rec;                            //Recorder.js object
var input;                          //MediaStreamAudioSourceNode we'll be recording

// shim for AudioContext when it's not avb.
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext //audio context to help us record

var recordButton = document.getElementById("recordButton");
var stopButton = document.getElementById("stopButton");
var pauseButton = document.getElementById("pauseButton");

//add events to those 2 buttons
recordButton.addEventListener("click", startRecording);
stopButton.addEventListener("click", stopRecording);
pauseButton.addEventListener("click", pauseRecording);

window.onload = function () { console.log({{ val }}) };
    function sendData() {
        var str = 'This is some data';
        $.ajax({
            url: '/newData',
            type: 'POST',
            data: str,
            success: function (res) { console.log(res) }, 
              // res is the response from the server 
              // (from return request.data)
            error: function (error) { console.log(error) }
        })
    }



function startRecording() {
    console.log("recordButton clicked");

    /*
        Simple constraints object, for more advanced audio features see
        https://addpipe.com/blog/audio-constraints-getusermedia/
    */

    var constraints = { audio: true, video:false }

    /*
        Disable the record button until we get a success or fail from getUserMedia()
    */

    recordButton.disabled = true;
    stopButton.disabled = false;
    pauseButton.disabled = false

    /*
        We're using the standard promise based getUserMedia()
        https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
    */

    navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
        console.log("getUserMedia() success, stream created, initializing Recorder.js ...");

        /*
            create an audio context after getUserMedia is called
            sampleRate might change after getUserMedia is called, like it does on macOS when recording through AirPods
            the sampleRate defaults to the one set in your OS for your playback device

        */
        audioContext = new AudioContext();

        //update the format
        document.getElementById("formats").innerHTML="Format: 1 channel pcm @ "+audioContext.sampleRate/1000+"kHz"

        /*  assign to gumStream for later use  */
        gumStream = stream;

        /* use the stream */
        input = audioContext.createMediaStreamSource(stream);

        /*
            Create the Recorder object and configure to record mono sound (1 channel)
            Recording 2 channels  will double the file size
        */
        rec = new Recorder(input,{numChannels:1})

        //start the recording process
        rec.record()

        console.log("Recording started");

    }).catch(function(err) {
        //enable the record button if getUserMedia() fails
        recordButton.disabled = false;
        stopButton.disabled = true;
        pauseButton.disabled = true
    });
}

function pauseRecording(){
    console.log("pauseButton clicked rec.recording=",rec.recording );
    if (rec.recording){
        //pause
        rec.stop();
        pauseButton.innerHTML="Resume";
    }else{
        //resume
        rec.record()
        pauseButton.innerHTML="Pause";

    }
}

function stopRecording() {
    console.log("stopButton clicked");

    //disable the stop button, enable the record too allow for new recordings
    stopButton.disabled = true;
    recordButton.disabled = false;
    pauseButton.disabled = true;

    //reset button just in case the recording is stopped while paused
    pauseButton.innerHTML="Pause";

    //tell the recorder to stop the recording
    rec.stop();

    //stop microphone access
    gumStream.getAudioTracks()[0].stop();

    //create the wav blob and pass it on to createDownloadLink
    rec.exportWAV(createDownloadLink);
}

function createDownloadLink(blob) {

    var url = URL.createObjectURL(blob);
    var au = document.createElement('audio');
    var li = document.createElement('li');
    var link = document.createElement('a');

    //name of .wav file to use during upload and download (without extendion)
    var filename = new Date().toISOString();

    //add controls to the <audio> element
    au.controls = true;
    au.src = url;

    //save to disk link
    link.href = url;
    link.download = filename+".wav"; //download forces the browser to donwload the file using the  filename
    link.innerHTML = "Save to disk";

    //add the new audio element to li
    li.appendChild(au);

    //add the filename to the li
    li.appendChild(document.createTextNode(filename+".wav "))

    //add the save to disk link to li
    li.appendChild(link);

    //upload link
    var upload = document.createElement('a');
    upload.href="/";
    upload.innerHTML = "Predict";
    upload.addEventListener("click", function(event){
          var xhr=new XMLHttpRequest();
          xhr.onload=function(e) {
              if(this.readyState === 4) {
                  console.log("Server returned: ",e.target.responseText);
              }
          };
          var fd=new FormData();
          fd.append("audio_data",blob, filename);
          xhr.open("POST","/",true);
          xhr.send(fd);
    })
    li.appendChild(document.createTextNode (" "))//add a space in between
    li.appendChild(upload)//add the upload link to li

    //add the li element to the ol
    recordingsList.appendChild(li);
}

索引.html

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Simple Recorder.js demo with record, stop and pause - addpipe.com</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
  <script src="https://cdn.rawgit.com/mattdiamond/Recorderjs/08e7abd9/dist/recorder.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">



</head>

<body>
  <nav class="navbar navbar-dark bg-primary">
    <a class="navbar-brand" href="#">
      My Prosodic Features
    </a>
  </nav>

  <div id ="controls" class="container">
  <div class="row">
    <div class="col-sm">
      <div class="jumbotron">
        <h1 class="display-4">Hello, People!</h1>
        <p class="lead">This is a simple unit,since its campus placement season I wanted to help my friends to know about their prosodic skills.</p>
        <p class='lead'>I have used python libraries like librosa and PRAAT for speech processing techniques along with Tensorflow for detection of certain tasks</p>

        <hr class="my-4">
        <p>We just wanted you know that the results are not 100% accurate, but it provides you some idea about your presentation and speaking skills.</p>
        <p>What we do is give some random question and you try to answer it. Make sure you limit yourself upto 1 minute for a preparation time so that you can perform well in real interviews. </p>
        <!-- <p class="lead">
        <a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
      </p> -->
      </div>
    </div>
    <div  class="col-sm">
      <div class="col-sm">
        <div class="jumbotron">
          <h1 class="display-4"> Question</h1>
          <p class = 'lead'>{{ q }}</p>

          <p class = 'lead'>
            <ol>
            <li>Click on Record button</li>
            <li>Speak for 5 minutes</li>
            <li>Click on upload button</li>
            </ol>
            <hr class="my-4">

          </p>

                  <button id="recordButton">Record</button>
                  <button id="pauseButton" disabled>Pause</button>
                  <button id="stopButton" disabled>Stop</button>
                  <div id="formats">Format: start recording to see sample rate</div>
                  <p><strong>Recordings:</strong></p>
                  <ol id="recordingsList"></ol>

        </div>
      </div>

    </div>

  </div>

</div>
  <!-- <div id="controls">
    <button id="recordButton">Record</button>
    <button id="pauseButton" disabled>Pause</button>
    <button id="stopButton" disabled>Stop</button>
  </div>
  <div id="formats">Format: start recording to see sample rate</div>
  <p><strong>Recordings:</strong></p>
  <ol id="recordingsList"></ol> -->
  <!-- inserting these scripts at the end to be able to use all the elements in the DOM -->
  <script src="https://code.jquery.com/jquery-3.5.1.js"></script>

  <script src="https://cdn.rawgit.com/mattdiamond/Recorderjs/08e7abd9/dist/recorder.js"></script>
  
  <script src={{ url_for('static', filename='js/app.js') }}></script>

</body>

</html>

结果.html 文件

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
  <script src="https://cdn.rawgit.com/mattdiamond/Recorderjs/08e7abd9/dist/recorder.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">

</head>

<!-- nsyll, npause, dur (s), phonationtime (s), speechrate (nsyll/dur), articulation rate (nsyll / phonationtime), -->

<body>
    <table class="table">
        <thead class="thead-dark">
          <tr>
            <th scope="col">#</th>
            <th scope="col">Feature</th>
            <th scope="col">Result</th>
            <th scope="col">Average Result</th>
          </tr>
        </thead>
        <tbody>

          <tr>
            <th scope="row">1</th>
            <td>nsyll</td>
            <td>{{ data[0] }}</td>
            <td>@fat</td>
          </tr>
          <tr>
            <th scope="row">2</th>
            <td>npause</td>
            <td>{{ data[1] }}</td>
            <td>@twitter</td>
          </tr>
          <tr>
            <th scope="row">3</th>
            <td>dur</td>
            <td>{{ data[2] }}</td>
            <td>@twitter</td>
          </tr>
          <tr>
            <th scope="row">4</th>
            <td>phonationtime</td>
            <td>{{ data[3] }}</td>
            <td>@twitter</td>
          </tr>
          <tr>
            <th scope="row">5</th>
            <td>speechrate</td>
            <td>{{ data[4] }}</td>
            <td>@twitter</td>
          </tr>
          <tr>
            <th scope="row">6</th>
            <td>articulation rate</td>
            <td>{{ data[5] }}</td>
            <td>@twitter</td>
          </tr>
        </tbody>
      </table>
</body>

标签: javascripthtmlflaskaudiobackend

解决方案


模板文件应位于templates与您的 python 文件位于同一目录级别的文件夹中。

例如

project
|---run.py
|---templates
|   |---index.html
|   |---results.html
|---static
    |---js
        |---app.js

推荐阅读