templates

Primero vamos crear una base de datos y una tabla para almacenar la ruta de nuestros archivos mp3.
 
  
  CREATE SCHEMA `bitacoradb` DEFAULT CHARACTER SET utf8 ;

CREATE TABLE `bitacoradb`.`actividades` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `ruta_audio` VARCHAR(250) NOT NULL,
  `fecha` DATETIME NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
  
  
    
   

Hacemos click derecho sobre el proyecto y le damos New Directory
phyton project
lo nombramos static aqui va todos los documentos estáticos css,imagenes,js,etc
Sobre el directorio static creamos el directorio uploads ahí vamos a generar todos los archivos mp3 de la grabación de audio.
phyton project
En el archivo app.py quedade la siguiente manera:
 
  
      import os
import mysql.connector
from datetime import datetime
import uuid
from flask import Flask, flash, request, redirect, render_template, json

app = Flask(__name__)

app.config["UPLOAD_FOLDER"] = "./static/uploads"





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

@app.route("/mostrar")
def audio():
    mydb = mysql.connector.connect(
        host="localhost",
        user="admin",
        passwd="adminlara",
        database="bitacoradb"
    )
    mycursor = mydb.cursor(dictionary=True)
    sql = "SELECT * FROM actividades ORDER BY id DESC"
    mycursor.execute(sql)
    resultadoBusqueda = mycursor.fetchall()
    mycursor.close()
    mydb.close()
    return render_template('bitacora.html',audios=resultadoBusqueda)




@app.route("/recibir", methods=['POST'])
def agregarAudio():
    # check if the post request has the file part
    if 'file' not in request.files:
        flash('No file part')
        return redirect(request.url)
    file = request.files['file']
    # if user does not select file, browser also
    # submit an empty part without filename
    if file.filename == '':
        flash('No selected file')
        return redirect(request.url)
    file_name = str(uuid.uuid4()) + ".mp3"
    full_file_name = os.path.join(app.config['UPLOAD_FOLDER'], file_name)
    file.save(full_file_name)
    now = datetime.now()
    formatted_date = now.strftime('%Y-%m-%d %H:%M:%S')
    mydb = mysql.connector.connect(
        host="localhost",
        user="admin",
        passwd="adminlara",
        database="bitacoradb"
    )
    mycursor = mydb.cursor()
    sql = "INSERT INTO actividades (id,ruta_audio,fecha) VALUES (null,%s,%s)"
    parameters = ('uploads/'+file_name,formatted_date)
    mycursor.execute(sql, parameters)
    mydb.commit()
    mycursor.close()
    mydb.close()
    return json.dumps({'html':'<span style="color:red;">Archivo generado !!</span>'}) 
       
     
   

Hacemos click derecho sobre el proyecto y le damos New Directory
phyton project
lo nombramos templates
phyton project
Dentro de templates creamos un archivo html
phyton project
lo nombramos index
phyton project
El archivo index.html queda de esta manera:
 
  
 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Web Speech Recorder</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
          integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
    <div class="container">
      <div class="header">
        <nav class="navbar navbar-expand-lg navbar-light bg-light">

  <div class="collapse navbar-collapse" id="navbarNav">
    <ul class="navbar-nav">
      <li class="nav-item active">
        <a class="nav-link" href="#">Grabar bitácora <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="/mostrar">Ver bitácora</a>
      </li>

    </ul>
  </div>
</nav>
        <h3 class="text-muted">Bitácora de voz App</h3>
      </div>



    <p>
        <button id="startRecording">Iniciar Grabación</button>
        <button id="stopRecording" disabled>Detener Grabación</button>

    </p>
    </div>
</body>
<script>
    navigator
        .mediaDevices
        .getUserMedia({audio: true})
        .then(stream => { handlerFunction(stream) });

    function handlerFunction(stream) {
        rec = new MediaRecorder(stream);
        rec.ondataavailable = e => {
            audioChunks.push(e.data);
            if (rec.state == "inactive") {
                let blob = new Blob(audioChunks, {type: 'audio/mpeg-3'});
                sendData(blob);
            }
        }
    }

    function sendData(data) {
        var form = new FormData();
        form.append('file', data, 'data.mp3');
        form.append('title', 'data.mp3');
        //Chrome inspector shows that the post data includes a file and a title.
        $.ajax({
            type: 'POST',
            url: '/recibir',
            data: form,
            cache: false,
            processData: false,
            contentType: false
        }).done(function(data) {
            console.log(data);
        });
    }

    startRecording.onclick = e => {
        console.log('Recording are started..');
        startRecording.disabled = true;
        stopRecording.disabled = false;
        audioChunks = [];
        rec.start();
    };

    stopRecording.onclick = e => {
        console.log("Recording are stopped.");
        startRecording.disabled = false;
        stopRecording.disabled = true;
        rec.stop();
    };
</script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</html> 
  
  
  
    
   

Creamos el archivo bitacora.html
 
  
  <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bitácora de voz</title>
     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
          integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
       <div class="container">
      <div class="header">
        <nav class="navbar navbar-expand-lg navbar-light bg-light">

  <div class="collapse navbar-collapse" id="navbarNav">
    <ul class="navbar-nav">
      <li class="nav-item">
        <a class="nav-link" href="/">Grabar bitácora <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item active" >
        <a class="nav-link" href="#">Ver bitácora</a>
      </li>

    </ul>
  </div>
</nav>
        <h3 class="text-muted">Bitácora de voz App</h3>
      </div>
       <table class="table table-bordered table-hover">
           {% for audio in audios %}
           <tr>

               <td>{{audio.id}}</td>
               <td>
     <audio controls><source src="{{url_for('static', filename=audio.ruta_audio)}}"></audio>

               </td>
               <td>{{audio.fecha}}</td>

           </tr>
            {% endfor %}
      </table>
       </div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
  
  
    
   


Ejecutando el programa