Mistral’s speech models for transcription, TTS and agents
Welcome to another official UVF IT guide! In this quick‑fire tutorial we’ll spin up a minimal speech‑to‑text and text‑to‑speech demo using only free‑tier, open‑source tools. No paid APIs, just Python, SQLite, and the Whisper & Coqui TTS models you can run locally.
You’ll end up with a tiny Flask app that accepts an audio file, returns a transcript, and can synthesize a spoken reply – all in under an hour. Perfect for learning the basics and extending into richer voice agents later.
ffmpeg installed on your machine (required for audio decoding).vits voice – accuracy is limited compared to paid services.Create a clean directory, a virtual environment, and install the required packages. This gives you an isolated workspace and pulls in Whisper, Coqui TTS, Flask and a few helpers so the rest of the guide can run without extra setup.
mkdir speech_demo && cd speech_demo
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install flask torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cpu
pip install openai-whisper tts
# Verify installations
python -c "import whisper, tts; print('Packages loaded')"A tiny SQLite table stores each request’s audio filename, transcript, and generated speech path. Keeping this metadata locally lets the Flask app quickly look up past results and demonstrates a simple persistence layer.
model.py
import sqlite3
DB_PATH = 'speech_demo.db'
def init_db():
conn = sqlite3.connect(DB_PATH)
cur = conn.cursor()
cur.execute('''
CREATE TABLE IF NOT EXISTS requests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
audio_file TEXT NOT NULL,
transcript TEXT,
tts_file TEXT
)
''')
conn.commit()
conn.close()
if __name__ == '__main__':
init_db()
print('Database initialized at', DB_PATH)In this step we expose two HTTP endpoints that the rest of the app can call. The /transcribe route accepts a multipart‑form upload of a WAV file, runs Whisper locally, and returns the plain text inside a JSON object. The /speak route receives raw text in a JSON body, feeds it to a tiny TTS model (we use gtts for simplicity), and streams the resulting WAV file back to the caller. Keeping the logic in app.py makes the service easy to run, test, and later extend with authentication or logging.
app.py
import os
from flask import Flask, request, jsonify, send_file
import whisper
from gtts import gTTS
from pydub import AudioSegment
import io
app = Flask(__name__)
# Load the tiny Whisper model once at startup
model = whisper.load_model('tiny')
@app.route('/transcribe', methods=['POST'])
def transcribe():
if 'audio' not in request.files:
return jsonify({'error': 'No audio file provided'}), 400
audio_file = request.files['audio']
# Whisper expects a file path; save temporarily
tmp_path = 'tmp.wav'
audio_file.save(tmp_path)
result = model.transcribe(tmp_path)
os.remove(tmp_path)
return jsonify({'text': result['text'].strip()})
@app.route('/speak', methods=['POST'])
def speak():
data = request.get_json(silent=True) or {}
text = data.get('text', '')
if not text:
return jsonify({'error': 'No text provided'}), 400
# Generate MP3 with gTTS, then convert to WAV in memory
tts = gTTS(text=text, lang='en')
mp3_io = io.BytesIO()
tts.write_to_fp(mp3_io)
mp3_io.seek(0)
wav_io = io.BytesIO()
AudioSegment.from_file(mp3_io, format='mp3').export(wav_io, format='wav')
wav_io.seek(0)
return send_file(wav_io, mimetype='audio/wav', as_attachment=True, download_name='speech.wav')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)Now that the API code is ready, start the Flask development server. The command below launches the service on port 5000 and keeps it alive so you can hit the endpoints with curl or a browser. If you modify app.py later, simply restart the process to pick up changes.
export FLASK_APP=app.py
export FLASK_ENV=development
flask run --host=0.0.0.0 --port=5000With the server running, use curl to send a short WAV sample and confirm you receive a JSON transcript. Then test the TTS endpoint by posting a JSON payload and playing the returned WAV file. These quick checks prove the core functionality works and give you a solid base to add features like logging, authentication, or a richer UI.
# Test transcription (replace samples/hello.wav with any short wav file)
curl -X POST -F "audio=@samples/hello.wav" http://127.0.0.1:5000/transcribe | jq .
# Test text‑to‑speech
echo '{"text":"Hello from the demo!"}' > payload.json
curl -X POST -H "Content-Type: application/json" -d @payload.json http://127.0.0.1:5000/speak --output hello.wav
aplay hello.wav # or any wav player| Check | Command / Why it matters |
|---|---|
SQLite DB file data.db exists with a logs table | ls -l data.db && sqlite3 data.db "SELECT count(*) FROM logs;" |
/transcribe returns a JSON transcript | curl -X POST -F 'audio=@samples/hello.wav' http://127.0.0.1:5000/transcribe | jq . |
/speak returns a playable wav file | curl -X POST -H 'Content-Type: application/json' -d '{"text":"test"}' http://127.0.0.1:5000/speak --output test.wav && aplay test.wav |
Your minimal speech‑to‑text / text‑to‑speech service is up and running. Feel free to swap the tiny Whisper model for base for better accuracy, add authentication, or hook it into a chatbot for a full voice agent. Happy hacking!