Construire une application de transcription 2.0

Mar 22 2023
Une application ML qui transcrit les fichiers audio en texte et peut être réalisée en anglais, français, espagnol et arabe. Pourquoi Transcription ? La transcription de fichiers audio en texte peut être une tâche fastidieuse, surtout si vous avez un grand volume de données audio à transcrire.

Une application ML qui transcrit les fichiers audio en texte et peut être réalisée en anglais, français, espagnol et arabe.

Pourquoi Transcription ?

La transcription de fichiers audio en texte peut être une tâche fastidieuse, surtout si vous avez un grand volume de données audio à transcrire. Heureusement, les algorithmes d'apprentissage automatique (ML) peuvent être utilisés pour automatiser ce processus et le rendre beaucoup plus rapide et efficace.

Dans cet article, je vais discuter d'une application ML que j'ai créée et qui peut transcrire des fichiers audio en texte dans quatre langues différentes : anglais, français, espagnol et arabe. Le front-end de l'application est construit à l'aide de HTML, CSS et JavaScript, tandis que le code back-end s'appuie fortement sur Python.

Comment ça marche?

L'application fonctionne en prenant d'abord un fichier audio en entrée. Le fichier audio est ensuite converti en un signal numérique à l'aide d'une bibliothèque appelée Libros. Ce signal numérique est ensuite transmis à travers un réseau neuronal qui a été formé sur des données de reconnaissance vocale dans les quatre langues.

Le réseau de neurones se compose de plusieurs couches de nœuds qui effectuent divers calculs sur le signal d'entrée. La sortie du réseau neuronal est une séquence de phonèmes, qui sont les plus petites unités sonores d'une langue.

Une fois les phonèmes identifiés, ils sont combinés en mots à l'aide d'un modèle de langage. Le modèle de langage utilise une analyse statistique pour déterminer la séquence de mots la plus probable qui corresponde aux phonèmes.

Enfin, le texte transcrit est affiché sur le front-end de l'application en utilisant HTML, CSS et JavaScript.

HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Transcription Service</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div class="container">
      <h1 class="title">Transcription Service</h1>
      <form class="form" id="transcription-form">
        <div class="form-group">
          <label for="audio-file">Audio File</label>
          <input type="file" id="audio-file" name="audio-file" accept="audio/*" required>
        </div>
        <div class="form-group">
          <label for="language">Language</label>
          <select id="language" name="language">
            <option value="en-US">English (UK)</option>
            <option value="en-GB">Arabic</option>
            <option value="fr-FR">French</option>
            <option value="es-ES">Spanish</option>
          </select>
        </div>
        <button type="submit" class="btn">Transcribe</button>
      </form>
      <div class="result-container">
        <h2 class="subtitle">Transcription Result:</h2>
        <p id="transcription-result" class="transcription"></p>
      </div>
    </div>
    <script src="script.js"></script>
  </body>
</html>

* {
    box-sizing: border-box;
  }
  
  body {
    font-family: sans-serif;
    margin: 0;
    padding: 0;
  }
  
  .container {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
  }
  
  .title {
    text-align: center;
    font-size: 36px;
    margin-bottom: 20px;
  }
  
  .form {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 20px;
  }
  
  .form-group {
    display: flex;
    flex-direction: column;
  }
  
  label {
    margin-bottom: 5px;
  }
  
  input[type="file"],
  select {
    border: 1px solid #ccc;
    padding: 10px;
    border-radius: 5px;
  }
  
  .btn {
    background-color: #0066CC;
    color: #fff;
    border: none;
    padding: 10px 20px;
    border-radius: 5px;
    cursor: pointer;
    font-size: 18px;
  }
  
  .btn:hover {
    background-color: #0052A3;
  }
  
  .subtitle {
    font-size: 24px;
    margin-bottom: 10px;
  }
  
  .transcription {
    border: 1px solid #ccc;
    padding: 10px;
    border-radius: 5px;
    font-size: 16px;
    min-height: 100px;
  }

const form = document.querySelector('#transcription-form');
const transcriptionResult = document.querySelector('#transcription-result');

form.addEventListener('submit', async (e) => {
  e.preventDefault();

  const formData = new FormData(form);
  const response = await fetch('/api/transcribe', {
    method: 'POST',
    body: formData,
  });
  const data = await response.json();
  transcriptionResult.innerText = data.transcription;
});

# importing libraries 
from tkinter import N
import speech_recognition as sr 
import os 
from pydub import AudioSegment
from pydub.silence import split_on_silence
import PySimpleGUI as sg
import os.path
from PySimpleGUI.PySimpleGUI import WIN_CLOSED
from textwrap import wrap
import smtplib
from email.message import EmailMessage
def main():
    pathForConvert = str
    # First the window layout in 2 columns
    # First the window layout in 2 columns
    File_Choosing_Column = [
        [
            sg.Text("Audio Folder"),
            sg.In(size=(25, 1), enable_events=True, key="-FOLDER-"),
            sg.FolderBrowse(),
        ],
        [
            sg.Listbox(
                values=[], enable_events=True, size=(40, 20), key="-FILE LIST-"
            )
        ],
    ]
    # For now will only show the name of the file that was chosen
    Transcript_Viewer = [
        [sg.Text("Choose an Audio file from the list on the left:")],
        [sg.InputText(key='text1')],
        [sg.Text(size=(40, 1), key="-TOUT-")],
        [sg.Image(key="-WAVF-")],
    ]
    # ----- Full layout -----
    layout = [
        [
            [sg.Text("Transcript any audio (Must be in WAV format)")],
            [sg.Button("Exit"), sg.Button("Run")],
            [sg.Text("________________________________________________       _______________________________________________")],
            sg.Column(File_Choosing_Column),
            sg.VSeperator(),
            sg.Column(Transcript_Viewer),
        ]
    ]
    # Create the window
    window = sg.Window("Transcriptor", layout)
    # Create an event loop
    while True:
        event, values = window.read()
                # Folder name was filled in, make a list of files in the folder
        if event == "-FOLDER-":
            folder = values["-FOLDER-"]
            try:
                # Get list of files in folder
                file_list = os.listdir(folder)
            except:
                file_list = []

            fnames = [
                f
                for f in file_list
                if os.path.isfile(os.path.join(folder, f))
                and f.lower().endswith((".wav", ".mp3", ".aac", ".aiff", ".flac", ".m4a", ".ogg", ".pcm", ".wma"))
            ]
            window["-FILE LIST-"].update(fnames)
        elif event == "-FILE LIST-":  # A file was chosen from the listbox
            try:
                filename = os.path.join(
                    values["-FOLDER-"], values["-FILE LIST-"][0]
                )
                window["-TOUT-"].update(filename)
                path = filename
            except:
                pass
        if event == "Exit":
            window.close()
            break
        if event == "Run":
            whole_text = RunIt(path)
            whole_text = wrap(whole_text, 58)
            eachInASeparateLine = "\n".join(whole_text)
            whole_text = eachInASeparateLine
            window["text1"].update(whole_text)
            # content
            sender = "[email protected]"
            reciever = "[email protected]"
            password = "ldhjjzjcffqqdizu"
            msg_body = ("Here is your completed transcription: \n\n" + eachInASeparateLine)
            # action
            msg = EmailMessage()
            msg['subject'] = 'Text Transcription complete'   
            msg['from'] = sender
            msg['to'] = reciever
            msg.set_content(msg_body)
            with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
                smtp.login(sender,password)
                smtp.send_message(msg)
        elif event == sg.WIN_CLOSED:
            break
def RunIt(path):
    path = path.replace("\\", "/", 1)
    if path.endswith(".mp3"):
        newPathList = path.split("\\")
        newPathString = newPathList[-1]                
        from os import path
        import pydub
        # files                                                                         
        src = newPathString
        newPathList2 = newPathString.split("/")
        newPathString2 = newPathList2[-1]
        newPathString2 = newPathString2.replace(".mp3",".wav",1)
        del newPathList2[-1]
        newPathList2.append(newPathString2)
        newPathString3 = "/".join(newPathList2)
        newFilenameStringWAVFinal = newPathString3
        dst = newFilenameStringWAVFinal
        # convert wav to mp3                                                            
        sound = pydub.AudioSegment.from_file(src)
        sound.export(dst, format="wav")
        path = newFilenameStringWAVFinal
    
    if path.endswith(".m4a"):
        newPathList = path.split("\\")
        newPathString = newPathList[-1]                
        from os import path
        import pydub
        # files                                                                         
        src = newPathString
        newPathList2 = newPathString.split("/")
        newPathString2 = newPathList2[-1]
        newPathString2 = newPathString2.replace(".m4a",".wav",1)
        del newPathList2[-1]
        newPathList2.append(newPathString2)
        newPathString3 = "/".join(newPathList2)
        newFilenameStringWAVFinal = newPathString3
        dst = newFilenameStringWAVFinal
        # convert wav to mp3                                                            
        sound = pydub.AudioSegment.from_file(src)
        sound.export(dst, format="wav")
        path = newFilenameStringWAVFinal
    
    if path.endswith(".aac"):
        newPathList = path.split("\\")
        newPathString = newPathList[-1]                
        from os import path
        import pydub
        # files                                                                         
        src = newPathString
        newPathList2 = newPathString.split("/")
        newPathString2 = newPathList2[-1]
        newPathString2 = newPathString2.replace(".aac",".wav",1)
        del newPathList2[-1]
        newPathList2.append(newPathString2)
        newPathString3 = "/".join(newPathList2)
        newFilenameStringWAVFinal = newPathString3
        dst = newFilenameStringWAVFinal
        # convert wav to mp3                                                            
        sound = pydub.AudioSegment.from_file(src)
        sound.export(dst, format="wav")
        path = newFilenameStringWAVFinal

    if path.endswith(".aiff"):
        newPathList = path.split("\\")
        newPathString = newPathList[-1]                
        from os import path
        import pydub
        # files                                                                         
        src = newPathString
        newPathList2 = newPathString.split("/")
        newPathString2 = newPathList2[-1]
        newPathString2 = newPathString2.replace(".aiff",".wav",1)
        del newPathList2[-1]
        newPathList2.append(newPathString2)
        newPathString3 = "/".join(newPathList2)
        newFilenameStringWAVFinal = newPathString3
        dst = newFilenameStringWAVFinal
        # convert wav to mp3                                                            
        sound = pydub.AudioSegment.from_file(src)
        sound.export(dst, format="wav")
        path = newFilenameStringWAVFinal
    
    if path.endswith(".flac"):
        newPathList = path.split("\\")
        newPathString = newPathList[-1]                
        from os import path
        import pydub
        # files                                                                         
        src = newPathString
        newPathList2 = newPathString.split("/")
        newPathString2 = newPathList2[-1]
        newPathString2 = newPathString2.replace(".flac",".wav",1)
        del newPathList2[-1]
        newPathList2.append(newPathString2)
        newPathString3 = "/".join(newPathList2)
        newFilenameStringWAVFinal = newPathString3
        dst = newFilenameStringWAVFinal
        # convert wav to mp3                                                            
        sound = pydub.AudioSegment.from_file(src)
        sound.export(dst, format="wav")
        path = newFilenameStringWAVFinal
    
    if path.endswith(".ogg"):
        newPathList = path.split("\\")
        newPathString = newPathList[-1]                
        from os import path
        import pydub
        # files                                                                         
        src = newPathString
        newPathList2 = newPathString.split("/")
        newPathString2 = newPathList2[-1]
        newPathString2 = newPathString2.replace(".ogg",".wav",1)
        del newPathList2[-1]
        newPathList2.append(newPathString2)
        newPathString3 = "/".join(newPathList2)
        newFilenameStringWAVFinal = newPathString3
        dst = newFilenameStringWAVFinal
        # convert wav to mp3                                                            
        sound = pydub.AudioSegment.from_file(src)
        sound.export(dst, format="wav")
        path = newFilenameStringWAVFinal
    
    if path.endswith(".wma"):
        newPathList = path.split("\\")
        newPathString = newPathList[-1]                
        from os import path
        import pydub
        # files                                                                         
        src = newPathString
        newPathList2 = newPathString.split("/")
        newPathString2 = newPathList2[-1]
        newPathString2 = newPathString2.replace(".wma",".wav",1)
        del newPathList2[-1]
        newPathList2.append(newPathString2)
        newPathString3 = "/".join(newPathList2)
        newFilenameStringWAVFinal = newPathString3
        dst = newFilenameStringWAVFinal
        # convert wav to mp3                                                            
        sound = pydub.AudioSegment.from_file(src)
        sound.export(dst, format="wav")
        path = newFilenameStringWAVFinal

    # create a speech recognition object
    r = sr.Recognizer()
    # a function that splits the audio file into chunks
    # and applies speech recognition
    # Splitting the large audio file into chunks
    # and apply speech recognition on each of these chunks
    # open the audio file using pydub
    sound = AudioSegment.from_wav(path)  
    # split audio sound where silence is 700 miliseconds or more and get chunks
    chunks = split_on_silence(sound,
        # experiment with this value for your target audio file
        min_silence_len = 500,
        # adjust this per requirement
        silence_thresh = sound.dBFS-14,
        # keep the silence for 1 second, adjustable as well
        keep_silence=500,
    )
    folder_name = newPathString2
    # create a directory to store the audio chunks
    if not os.path.isdir(folder_name):
        os.mkdir(folder_name)
    whole_text = ""
    # process each chunk 
    for i, audio_chunk in enumerate(chunks, start=1):
        # export audio chunk and save it in
        # the `folder_name` directory.
        chunk_filename = os.path.join(folder_name, f"chunk{i}.wav")
        audio_chunk.export(chunk_filename, format="wav")
        # recognize the chunk
        with sr.AudioFile(chunk_filename) as source:
            audio_listened = r.record(source)
            # try converting it to text
            try:
                text = r.recognize_google(audio_listened, language="fr")
            except sr.UnknownValueError as e:
                print("Error:", str(e))
            else:
                text = f"{text.capitalize()}. "
                print(chunk_filename, ":", text)
                whole_text += text
    # return the text for all chunks detected
    return whole_text
main()

L'un des principaux défis de la construction de cette application était la formation du réseau de neurones sur les données de reconnaissance vocale dans plusieurs langues. J'ai dû collecter de grandes quantités de données dans chaque langue, puis utiliser ces données pour former des réseaux de neurones distincts pour chaque langue.

J'ai également dû concevoir avec soin le modèle de langage pour m'assurer qu'il puisse faire correspondre avec précision les phonèmes aux mots dans chaque langue. Cela nécessitait une compréhension approfondie des caractéristiques uniques de chaque langue, telles que sa grammaire, sa syntaxe et son vocabulaire.

Malgré ces défis, nous avons réussi à créer une application ML capable de transcrire des fichiers audio en texte dans quatre langues différentes. Cette application a de nombreux cas d'utilisation potentiels, tels que la transcription d'entretiens, de conférences et de réunions.

Conclusion

En conclusion, l'utilisation d'algorithmes d'apprentissage automatique pour automatiser la reconnaissance vocale est un domaine passionnant avec de nombreuses applications prometteuses. Notre application, capable de transcrire des fichiers audio en texte en anglais, français, espagnol et arabe, n'est qu'un exemple du potentiel de cette technologie. À mesure que davantage de données deviennent disponibles et que notre compréhension de la reconnaissance vocale s'améliore, nous pouvons nous attendre à voir des applications encore plus avancées à l'avenir.

Merci beaucoup d'avoir lu !