Cursus
OpenAI heeft de volgende generatie audiomodellen geïntroduceerd, gericht op het verbeteren van spraak-naar-tekst en tekst-naar-spraak. Deze nieuwste modellen beloven een hogere nauwkeurigheid, vooral in complexe situaties zoals accenten of lawaaierige omgevingen, en bieden meer aanpasbare steminteracties.
In deze tutorial leg ik stap voor stap uit hoe je deze nieuwe OpenAI-audiomodellen gebruikt om een voice-to-voice AI-assistent te bouwen. Ons doel is om een AI-assistent te ontwikkelen die gesproken input begrijpt en antwoordt met een natuurlijk gesynthetiseerde stem, afgestemd op specifieke behoeften.
De OpenAI Audio API
Deze nieuwe release van OpenAI bevat drie modellen:
gpt-4o-mini-tts: Een tekst-naar-audio-model dat audio kan genereren uit tekst met verschillende tonen en stemmen. Een handige functie van dit tekst-naar-spraakmodel is dat we kunnen sturen hoe de stem klinkt door specifieke tekstinstructies te geven. Dit zorgt voor een hoge mate van maatwerk, waardoor je unieke en op maat gemaakte stemervaringen kunt creëren. Je kunt het uitproberen op OpenAI.fm.-
gpt-4o-transcribeengpt-4o-mini-transcribe: Twee audio-naar-tekstmodellen die zijn ontworpen om gesproken taal om te zetten in geschreven tekst. Hun hoofdfunctie is om zeer nauwkeurige en betrouwbare transcripties van audio te leveren. Deze modellen hebben een lagere word error rate (WER), wat betekent dat ze minder fouten maken bij het herkennen van gesproken woorden dan eerdere oplossingen.

Deze nieuwe modellen hebben de volgende prijsstelling:

Voice Assistant-project
In deze tutorial leid ik je door het bouwen van een AI-spraakassistent direct in je terminal. Deze voice-assistent bootst in essentie een populair tekstgebaseerd AI-model na, maar communiceert volledig via gesproken taal. Stel je voor dat je rechtstreeks tegen je computer kunt praten, elke vraag kunt stellen en vrijwel direct een gesproken antwoord krijgt.
Ons project gebruikt een eenvoudige maar effectieve architectuur. We beginnen met je microfoon om je gesproken prompt vast te leggen. Zodra deze is opgenomen, zetten we deze audio-invoer om in tekst met behulp van geavanceerde spraak-naar-tekstmodellen.
Deze tekst voeren we vervolgens in een groot taalmodel om een passend antwoord te genereren. Tot slot zetten we het tekstuele antwoord terug om in audio, zodat de assistent het antwoord naar je kan “uitspreken”. Elke stap in dit proces is ontworpen om ervoor te zorgen dat onze voice-assistent zowel nauwkeurig als aantrekkelijk is.

Hoewel OpenAI een speciale Realtime API biedt die interacties kan verbeteren door het hele proces te stroomlijnen, kiezen we voor een andere aanpak. De Realtime API is indrukwekkend en perfect voor ontwikkelaars die snelle integraties zoeken, maar is vaak duurder en biedt minder flexibiliteit.
Door ons project op te bouwen met losse componenten voor elke stap, krijgen we meer controle over de maatwerkopties van onze AI-assistent. Deze aanpak laat ons de modellen kiezen die we willen gebruiken, zodat we kunnen optimaliseren voor specifieke behoeften, of dat nu nauwkeurigheid, snelheid of voorkeur in toon van het antwoord is. Zo wordt onze voice-assistent niet alleen een krachtig hulpmiddel, maar ook sterk op maat, geschikt voor unieke projectvereisten.
Alle code die we hier ontwikkelen is beschikbaar in deze GitHub-repository.
Python-setup
Om te beginnen maken we eerst een nieuwe Anaconda-omgeving aan met de naam audio-demo. Met Anaconda-omgevingen kun je voor elk project een geïsoleerde ruimte maken waar je specifieke versies van pakketten zonder conflicten kunt installeren. Voer de volgende opdrachten uit in je command-line interface:
conda create -n audio-demo -y python=3.9
conda activate audio-demo
pip install openai
pip install numpy
pip install dotenv
pip install sounddevice
pip install scipy
Laten we toelichten wat elke opdracht en elk pakket doet:
- De omgeving maken:
conda create -n audio-demo -y python=3.9: Deze opdracht maakt een nieuwe omgeving genaamdaudio-demomet Python-versie 3.9. De vlag-ykeurt de installatie van pakketten automatisch goed zonder te vragen.
- De omgeving activeren:
conda activate audio-demo: Activeert de zojuist gemaakteaudio-demo-omgeving, zodat we daarin kunnen werken.
- Pakketten installeren:
pip install openai: OpenAI is een bibliotheek die eenvoudige toegang biedt tot de modellen en API’s van OpenAI.pip install numpy: NumPy is een essentiële bibliotheek voor numerieke berekeningen.pip install dotenv: Dotenv helpt om omgevingsvariabelen uit een.env-bestand te laden, waardoor configuratiebeheer eenvoudiger en veiliger wordt.pip install sounddevice: Sounddevice laat ons geluid opnemen en afspelen met simpele functies, ideaal voor audio-invoer en -uitvoer in Python.pip install scipy: SciPy bouwt voort op NumPy en biedt extra functionaliteit voor wetenschappelijke en technische computing, zoals signaalverwerking. In ons geval gebruiken we het om het audiobestand op te slaan.
Met onze audio-demo-omgeving opgezet, zijn we klaar om te werken aan onze AI-assistent die audio-invoer kan verwerken. Deze gestructureerde setup helpt ons een schone ontwikkelomgeving te behouden en zorgt dat alle afhankelijkheden voor ons project aanwezig zijn.
OpenAI API-sleutel instellen
Om de OpenAI API te gebruiken, hebben we een API-sleutel nodig. Ga naar hun API-sleutelpagina en genereer een API-sleutel door op de knop "Generate new secret key" te klikken. Kopieer de sleutel, maak een bestand met de naam .env en plak deze daarin met het volgende formaat:
OPENAI_API_KEY=<paste_your_api_key_here>
Voorbeeld: tekst naar audio
Laten we de stappen doorlopen om een Python-script te maken dat de tekst-naar-audiomogelijkheden van OpenAI gebruikt en tekst met een persoonlijk tintje omzet in spraak. We schrijven onze code in een bestand met de naam text_to_audio.py in dezelfde map als het .env-bestand.
Benodigde libraries importeren
Eerst importeren we de benodigde libraries voor ons script:
import asyncio
from openai import AsyncOpenAI
from openai.helpers import LocalAudioPlayer
from dotenv import load_dotenv
Laten we kort toelichten wat elk van deze imports doet:
asyncio: Deze bibliotheek is nodig voor asynchrone code in Python, wat essentieel is voor werken met streaming-API’s.AsyncOpenAI: Onderdeel van de OpenAI-bibliotheek; biedt tools om asynchroon met de API’s van OpenAI te werken.LocalAudioPlayer: Deze helper van OpenAI laat ons lokaal audio afspelen op onze machine.load_dotenv: Laadt omgevingsvariabelen uit het.env-bestand, waar we gevoelige informatie zoals onze API-sleutels opslaan.
Omgevingsvariabelen laden
Vervolgens laden we onze API-sleutel uit het .env-bestand met de functie load_dotenv:
load_dotenv()
Dit zorgt ervoor dat ons script veilig toegang heeft tot de API-sleutel.
OpenAI initialiseren
We maken een instantie van AsyncOpenAI om met de OpenAI API te communiceren:
openai = AsyncOpenAI()
De hoofdfunctionaliteit schrijven
Nu definiëren we onze hoofdfunctie, text_to_audio(), die de tekst-naar-audiofunctie van OpenAI gebruikt om de invoer te verwerken en het resulterende geluid af te spelen:
async def text_to_audio(text, tone_and_style_instructions):
async with openai.audio.speech.with_streaming_response.create(
model="gpt-4o-mini-tts",
voice="coral",
input=text,
instructions=tone_and_style_instructions,
response_format="pcm",
) as response:
await LocalAudioPlayer().play(response)
Even snel samenvatten wat we hierboven gedaan hebben:
- We geven de parameters
modelenvoiceop om de spraaksynthese te sturen. Het gebruiktemodelisgpt-4o-mini-ttsen de gekozen stem is "coral". - De
response_formatis ingesteld op"pcm", geschikt voor audiobewerking. - De
LocalAudioPlayerspeelt vervolgens het audiovoorstel af dat door de API is gegenereerd.
De functie uitvoeren
We maken het script af met de volgende regels zodat de functie text_to_audio() wordt uitgevoerd wanneer we het script starten:
if __name__ == "__main__":
asyncio.run(text_to_audio("Hello world!", "Enthusiastic voice."))
Dit codeblok controleert of het script het hoofdmodule is dat wordt uitgevoerd, en voert de functie text_to_audio() uit met asyncio.run() om de asynchrone logica af te handelen.
Met deze stappen is ons script klaar om tekstinvoer om te zetten in spraak met de tekst-naar-audiodienst van OpenAI. Deze setup laat je experimenteren met verschillende input en stijlen en brengt tekst tot leven via geluid.
We kunnen het script uitvoeren met het commando:
python text_to_audio.py
De volledige code vind je hier.
Audio transcriberen vanuit een bestand
In deze sectie bekijken we hoe je een audiobestand naar tekst transcribeert met de audiotranscriptietool van OpenAI. Ons script verwerkt audiobestanden asynchroon om het proces efficiënt en snel te maken. We implementeren dit script in een bestand met de naam audio_to_text.py.
De imports en initiële setup zijn hetzelfde als eerder, behalve dat we hier de LocalAudioPlayer niet hoeven te importeren. Zo kun je een functie schrijven die een audiobestand transcribeert:
async def transcribe_audio(audio_filename = "audio.wav"):
audio_file = await asyncio.to_thread(open, audio_filename, "rb")
stream = await openai.audio.transcriptions.create(
model="gpt-4o-mini-transcribe",
file=audio_file,
response_format="text",
stream=True,
)
transcript = ""
async for event in stream:
if event.type == "transcript.text.delta":
print(event.delta, end="", flush=True)
transcript += event.delta
print()
audio_file.close()
return transcript
Laten we uiteenzetten wat hier gebeurt:
- Het audiobestand openen:
audio_file = await asyncio.to_thread(open, audio_filename, "rb"): Deze regel opent het audiobestand in binaire leesmodus ("rb"). De methodeasyncio.to_thread()laat deze open-bewerking in een aparte thread draaien, zodat deze andere onderdelen van het programma niet blokkeert.
- Een transcriptiestream maken:
stream = await openai.audio.transcriptions. create(...): Deze regel roept de transcriptie-API aan.- We geven de parameter
modelop alsgpt-4o-mini-transcribe, speciaal ontworpen voor transcriptietaken. - De parameter
filebevat ons geopende audiobestand. response_format="text"vertelt de API om de transcriptie als tekst terug te geven.stream=Truewordt gebruikt om de transcriptie in realtime te streamen; zodra een deel van de audio is verwerkt, wordt het direct teruggestuurd, wat de reactie versnelt.
- De transcriptiestream verwerken:
async for event in stream: Start een lus om gebeurtenissen uit de transcriptiestream te lezen zodra ze plaatsvinden.if event.type == "transcript.text.delta":: Controleert elk type gebeurtenis en verwerkt deze als het typetranscript.text.deltais, wat aangeeft dat een deel van de transcriptie klaar is.print(event.delta, end="", flush=True): Print de incrementele transcriptie zodra die beschikbaar komt, zodat onze output realtime is.
- Het audiobestand sluiten:
audio_file.close(): Nadat de transcriptie voltooid is, is het goed gebruik om het audiobestand te sluiten om systeembronnen vrij te geven.
Door de functie main() uit te voeren, kunnen we een audiobestand efficiënt naar tekst omzetten en het gestreamd verwerken om direct feedback te krijgen. Deze setup is ideaal voor toepassingen die snelle transcriptie nodig hebben of met lange audiobestanden werken.
Je kunt het proberen door een audiobestand in dezelfde map als het script te plaatsen, audio.wav te vervangen door de naam van jouw audiobestand en het commando uit te voeren:
python audio_to_text.py
De volledige code vind je hier.
Audio transcriberen via de microfoon
Omdat ons doel is om een voice-assistent te maken, moeten we de audioprompt van de gebruiker opnemen in een audiobestand.
We maken een nieuw bestand met de naam record.py met een functie record_audio. Deze functie vangt geluid op van de microfoon en slaat het op als een audiobestand. We gaan niet te diep in op hoe dit werkt, omdat het niet de hoofdfocus van dit artikel is:
import sounddevice as sd
import numpy as np
import scipy.io.wavfile as wavfile
SAMPLE_RATE = 44100 # Sample rate in Hz
def record_audio():
print("[INFO: Recording... Press <Enter> to stop]")
audio_data = [] # Initialize a list to store audio frames
def callback(indata, frames, time, status):
audio_data.append(indata.copy())
with sd.InputStream(samplerate=SAMPLE_RATE, channels=1, callback=callback, dtype='int16'):
input() # Wait for the user to press Enter to stop recording
print("[INFO: Recording complete]")
print()
audio_data = np.concatenate(audio_data) # Concatenate the list into a single array
filename = "output.wav"
wavfile.write(filename, SAMPLE_RATE, audio_data)
return audio_data
Wanneer we deze functie aanroepen, begint hij met opnemen via de microfoon van de gebruiker. Hij wacht tot de gebruiker op "Enter" drukt en slaat dan de audio op in een bestand met de opgegeven bestandsnaam.
Om dit te testen, kunnen we deze functie combineren met de transcriptiefunctie hierboven om een door de gebruiker ingesproken bericht te transcriberen. Zo kun je een nieuw bestand record_and_transcribe.py maken om dit te implementeren:
import asyncio
from audio_to_text import transcribe_audio
from audio_recorder import record_audio
async def main():
record_audio("prompt.wav")
await transcribe_audio("prompt.wav")
if __name__ == "__main__":
asyncio.run(main())
Je kunt dit proberen uit te voeren met het commando python record_and_transcribe.py. Het script neemt op wat je zegt totdat je op "Enter" drukt en transcribeert vervolgens wat je hebt gezegd.
Een audio-assistent bouwen
In deze sectie zetten we alles bij elkaar om een audio-assistent te bouwen. We implementeren dit in een nieuw bestand genaamd audio_assistant.py volgens deze stappen:
- Neem de audioprompt van de gebruiker op met de functie
record_audio(). - Zet de audioprompt om naar tekst met de functie
transcribe_audio(). - Gebruik een regulier tekst-naar-tekstmodel zoals
gpt-4oom een antwoord te genereren. - Zet het tekstuele antwoord ten slotte om naar audio met de functie
text_to_audio(). - Herhaal dit totdat de gebruiker afsluit.
Het volgende diagram illustreert dit:

Ik raad je aan om te proberen het zelf te bouwen voordat je verder leest.
Eerst importeren we de functies die we eerder hebben geïmplementeerd en initialiseren we de OpenAI-client.
# Import the functions we created
from text_to_audio import text_to_audio
from audio_to_text import transcribe_audio
from audio_recorder import record_audio
# Import other dependencies and initialize OpenAI
import asyncio
from openai import AsyncOpenAI
from dotenv import load_dotenv
load_dotenv()
openai = AsyncOpenAI()
Vervolgens hebben we een functie nodig om het antwoord te genereren. Deze gebruikt de normale OpenAI GPT API met een model zoals gpt-4o of elk ander tekst-naar-tekstmodel. Als je hier nieuw in bent, kijk dan eens naar deze GPT-4o API-tutorial.
Hier is een asynchrone implementatie van deze functie:
async def get_answer(prompt):
stream = await openai.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "user", "content": prompt}
],
stream=True,
)
answer = ""
async for chunk in stream:
content = chunk.choices[0].delta.content
if content is not None:
answer += content
print(content, end="", flush=True)
print("\n\n")
return answer
Om de hoofdlus te implementeren, volgen we de hierboven beschreven stappen:
async def main(tone_and_style_instructions):
await text_to_audio("Hello, how can I help you today?", tone_and_style_instructions)
while True:
record_audio("prompt.wav")
prompt = await transcribe_audio("prompt.wav")
print()
answer = await get_answer(prompt)
await text_to_audio(answer, tone_and_style_instructions)
Tot slot draaien we de hoofdlus wanneer het script wordt uitgevoerd:
if __name__ == "__main__":
tone_and_style_instructions = "Enthusiastic voice."
asyncio.run(main(tone_and_style_instructions))
Hier is een demo van hoe het werkt:
De volledige code vind je hier.
Verdere verbeteringen
Als we de assistent proberen met complexe toon- en stijlinstructies, kunnen we een discrepantie merken tussen de woorden en de toon. Neem bijvoorbeeld de volgende instructies voor een "Emo Teenager"-stem van de OpenAI-website:
tone_and_style_instructions = """
Tone: Sarcastic, disinterested, and melancholic, with a hint of passive-aggressiveness.
Emotion: Apathy mixed with reluctant engagement.
Delivery: Monotone with occasional sighs, drawn-out words, and subtle disdain, evoking a classic emo teenager attitude.
"""
De stemtoon van de audio zal bij deze stijl passen, maar de tekstinhoud van het antwoord dat door de functie get_answer() wordt gegenereerd, houdt hier geen rekening mee, wat tot wat inconsistentie kan leiden. Hier is een voorbeeld:
Om dit te ondervangen, kunnen we het gebruikersbericht in de functie get_answer() koppelen aan een systeemprompt die aangeeft dat de gegenereerde tekst de toon- en stijlinstructies moet volgen.
Daarvoor geven we de tone_and_style_instructions als tweede argument door aan de functie get_answer() en wijzigen we het chatverzoek door een systeembericht toe te voegen:
async def get_answer(prompt, tone_and_style_instructions):
stream = await openai.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content":
f"""
The text you generate is being used in a text-to-voice model.
Make sure your answer matches the guidelines {tone_and_style_instructions}
"""
},
{"role": "user", "content": prompt}
],
stream=True,
)
answer = ""
async for chunk in stream:
content = chunk.choices[0].delta.content
if content is not None:
answer += content
print(content, end="", flush=True)
print("\n\n")
return answer
Zo antwoordt het model nu:
Zoals je ziet komt de tekst die het nu genereert overeen met de tooninstructies. De volledige code vind je hier.
Een assistent bouwen met de Agents API
In het vorige voorbeeld hebben we handmatig de voice-to-text- en text-to-voice-modellen aangeroepen om een voice-assistent te bouwen. Zo leerden we expliciet de nieuwe modellen van de voice API van OpenAI te gebruiken.
Als het doel echter is om een voice-assistent te bouwen, is er een eenvoudigere manier om de Agents API te gebruiken. Deze API is bijgewerkt om automatisch de voice-to-text-to-voice-workflow te verwerken die we hier hebben geïmplementeerd.
Als dit de eerste keer is dat je de Agents API gebruikt, kijk dan eens naar deze tutorial over de OpenAI Agents SDK.
Voor we beginnen, moeten we nog één extra dependency installeren:
pip install 'openai-agents[voice]'
Met dat uit de weg, starten we door alles te importeren wat we nodig hebben om een agent te draaien met een voice-pijplijn:
from dotenv import load_dotenv
load_dotenv()
import asyncio
from agents import Agent
from agents.voice import (
AudioInput,
SingleAgentVoiceWorkflow,
VoicePipeline,
VoicePipelineConfig,
TTSModelSettings,
)
from audio_recorder import record_audio
from audio_player import AudioPlayer
De AudioPlayer hoort niet bij een pakket. Hij wordt geïmporteerd uit een lokaal bestand en bevat een eenvoudige class om ons te helpen audio in realtime af te spelen. Dit is nodig omdat we met de VoicePipeline de audio stukje bij beetje binnenkrijgen en elk stukje afspelen zodra we het ontvangen. Hier is de inhoud van het audio_player.py-bestand:
import numpy as np
import sounddevice as sd
class AudioPlayer:
def __enter__(self):
self.stream = sd.OutputStream(samplerate=24000, channels=1, dtype=np.int16)
self.stream.start()
return self
def __exit__(self, tp, val, tb):
self.stream.close()
def add_audio(self, audio_data):
self.stream.write(audio_data)
De volgende stap is het aanmaken van een agent:
agent = Agent(
name="Voice Assistant",
instructions="You’re a helpful assistant speaking to a human.",
model="gpt-4o-mini",
)
Hier is een beschrijving van de parameters die we gebruikten:
name: Dit kan alles zijn wat je wilt.instructions: Deze instructies bepalen wat de agent moet zijn. Het werkt als de systeemprompt.model: Het model dat wordt gebruikt om antwoorden te genereren.
De agent werkt als de functie get_answer() die we eerder implementeerden. Zie het als het deel van de pijplijn dat een antwoord geeft op een tekstprompt.
Vervolgens definiëren we de pijplijn. Hier specificeren we alle configuraties met betrekking tot de stem:
pipeline = VoicePipeline(
workflow=SingleAgentVoiceWorkflow(agent),
stt_model="gpt-4o-mini-transcribe",
tts_model="gpt-4o-mini-tts",
config=VoicePipelineConfig(
tts_settings=TTSModelSettings(
voice="coral",
instructions="""
Speak in an enthusiastic voice.
"""
)
)
)
Hier is een overzicht van enkele parameters:
stt_model: Het model om spraak naar tekst om te zetten.tts_model: Het model om tekst naar spraak om te zetten.config: Biedt de pijplijnconfiguratie. Hier gebruiken we het om de stem te specificeren die hettts_modelmoet gebruiken, evenals de spraakinstructies.
Tot slot draaien we de hoofdlus, vergelijkbaar met wat we eerder deden:
async def main():
while True:
audio_input = AudioInput(buffer=record_audio())
result = await pipeline.run(audio_input)
with AudioPlayer() as player:
async for event in result.stream():
if event.type == "voice_stream_event_audio":
player.add_audio(event.data)
if __name__ == "__main__":
asyncio.run(main())
Je vindt een volledige implementatie hier.
Tools toevoegen
Merk op dat deze lus voor altijd blijft draaien, omdat we geen stopvoorwaarde hebben opgegeven. Bij het uitvoeren moet je het proces handmatig beëindigen om het te stoppen. Een manier om het stoppen te implementeren, is door een tool aan de agent te geven.
Tools zijn functies die we aan de agent geven zodat hij ze voor ons kan uitvoeren. In dit geval kunnen we een functie aanbieden die het script stopt. De agent gebruikt de functienaam en commentaar om te beslissen of hij deze moet aanroepen.
from agents import function_tool
@function_tool
def stop_conversation():
"""Stop the conversation."""
exit()
Vervolgens geven we de tool door aan de agent:
agent = Agent(
…
tools=[stop_conversation], # Add this line when creating the agent
)
Met deze implementatie, als we zeggen: “Ik wil het gesprek stoppen”, zal de agent begrijpen dat hij de functie stop_conversation() moet aanroepen. Merk op dat deze implementatie niet netjes afsluit vanwege de manier waarop de functie stop_conversation() is geïmplementeerd.
Bekijk dit bestand als je een compleet script wilt.
Meerdere agents gebruiken
Een leuke functie van de Agents API is dat we meerdere agents kunnen configureren om samen te werken. Hier is een voorbeeld uit de OpenAI-documentatie:
from agents.extensions.handoff_prompt import prompt_with_handoff_instructions
spanish_agent = Agent(
name="Spanish voice assistant",
handoff_description="A spanish speaking agent.",
instructions=prompt_with_handoff_instructions(
"You're speaking to a human, so be polite and concise. Speak in Spanish.",
),
model="gpt-4o-mini",
)
agent = Agent(
name="Voice Assistant",
instructions=prompt_with_handoff_instructions("""
You're speaking to a human, so be polite and concise.
If the user speaks in Spanish, handoff to the spanish agent.
"""),
model="gpt-4o-mini",
)
In dit voorbeeld definiëren we een tweede agent die is ontworpen om Spaans te spreken en we wijzigen de eerste agent door een prompt met een handoff te geven. Wanneer aan de handoff-instructies wordt voldaan, neemt de tweede agent het gesprek over.
Het volledige script is beschikbaar hier.
Conclusie
Door gebruik te maken van de geavanceerde mogelijkheden van de nieuwste audiomodellen van OpenAI hebben we een systeem gemaakt dat gesproken taal effectief kan transcriberen naar tekst en mensachtige spraak kan genereren uit tekstuele reacties. Dit project laat niet alleen het potentieel van de huidige technologie zien, maar ook hoe toegankelijk deze tools zijn geworden voor ontwikkelaars die aangepaste AI-oplossingen willen bouwen.

