เวิร์กโฟลว์เอเจนต์เสียง + ข้อความ
การถอดเสียง → การให้เหตุผล → สายงานตอบกลับด้วยเสียงตั้งแต่ต้นจนจบ
เวิร์กโฟลว์เอเจนต์เสียง + ข้อความ เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
ภาพรวมกระบวนการทำงานของเอเจนต์เสียงและข้อความ
กระบวนการทำงานของเอเจนต์เสียงและข้อความจะแปลงข้อมูลระหว่างโลกของภาษาพูดและภาษาเขียน ลำดับการทำงานมาตรฐานคือ รับเสียงเข้า → การถอดเสียงด้วยวิสเปอร์ → เอเจนต์ข้อความ → ส่งเสียงออกด้วย TTS ซึ่งช่วยให้สร้างผู้ช่วยเสียง การวิเคราะห์การโทร การสรุปการประชุม และส่วนติดต่อที่ใช้งานได้โดยไม่ต้องใช้มือ
รูปแบบไฟล์เสียงที่รองรับ
OpenAI Whisper รองรับรูปแบบต่อไปนี้: mp3, mp4, mpeg, mpga, m4a, wav และ webm ขนาดไฟล์สูงสุดคือ 25 MB สำหรับไฟล์ที่มีขนาดใหญ่กว่านี้ คุณต้องแบ่งหรือบีบอัดเสียงก่อนส่ง
เพื่อให้ได้คุณภาพการถอดเสียงดีที่สุดและขนาดไฟล์เล็กที่สุด ให้บันทึกหรือแปลงเสียงเป็นโมโน 16 kHz เสมอ
import os
SUPPORTED_FORMATS = {'.mp3', '.mp4', '.mpeg', '.mpga', '.m4a', '.wav', '.webm'}
MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024 # 25 MB
def validate_audio_file(path: str) -> dict:
ext = os.path.splitext(path)[1].lower()
size = os.path.getsize(path) if os.path.exists(path) else 0
return {
'path': path,
'format_ok': ext in SUPPORTED_FORMATS,
'size_ok': size <= MAX_FILE_SIZE_BYTES,
'size_mb': round(size / 1024 / 1024, 2),
'extension': ext
}
# Usage:
info = validate_audio_file('meeting.wav')
print(info)การถอดเสียงด้วย Whisper
จุดปลายทาง audio.transcriptions.create ของ OpenAI ทำหน้าที่ครอบ Whisper ไว้ ให้ส่งออบเจ็กต์ไฟล์และชื่อโมเดล พร้อมระบุคำใบ้ภาษาและพรอมต์ได้ตามต้องการ คำใบ้ภาษาจะช่วยให้ทำงานเร็วขึ้นและหลีกเลี่ยงการตรวจจับภาษาผิด ส่วนพรอมต์จะช่วยเตรียมคลังคำศัพท์สำหรับคำเฉพาะด้าน
from openai import OpenAI
client = OpenAI(api_key='YOUR_OPENAI_API_KEY')
def transcribe_audio(
audio_path: str,
language: str = 'en',
prompt: str = ''
) -> str:
with open(audio_path, 'rb') as audio_file:
transcript = client.audio.transcriptions.create(
model='whisper-1',
file=audio_file,
language=language,
prompt=prompt, # e.g. 'Python, NestJS, TypeScript, API'
response_format='text'
)
return transcript
text = transcribe_audio('user_query.mp3', language='en',
prompt='Kubernetes, microservices, Docker')
print('Transcription:', text)การถอดเสียงพร้อมการประทับเวลา
สำหรับการวิเคราะห์การประชุมหรือการแยกผู้พูด ให้ขอรูปแบบ verbose_json รูปแบบนี้จะส่งคืนการประทับเวลาระดับคำหรือระดับส่วน ทำให้คุณระบุตำแหน่งช่วงเวลาที่แน่นอนในเสียงเพื่อใช้อ้างอิงหรือตัดคลิปได้
def transcribe_with_timestamps(audio_path: str) -> dict:
from openai import OpenAI
client = OpenAI(api_key='YOUR_OPENAI_API_KEY')
with open(audio_path, 'rb') as f:
result = client.audio.transcriptions.create(
model='whisper-1',
file=f,
response_format='verbose_json',
timestamp_granularities=['segment']
)
# result.segments: list of {start, end, text}
segments = [
{'start': s.start, 'end': s.end, 'text': s.text}
for s in result.segments
]
return {'full_text': result.text, 'segments': segments}
# Example output structure:
# {'full_text': 'Hello team...', 'segments': [{'start': 0.0, 'end': 2.3, 'text': 'Hello team'}]}การประมวลผลโดยเอเจนต์ข้อความ
หลังการถอดเสียง ข้อความจะถูกส่งผ่านเอเจนต์ LLM ในฐานะข้อความธรรมดา ให้ใส่พรอมต์ระบบเพื่อกำหนดบริบทว่า ข้อความนี้มาจากคำพูด ดังนั้นจึงอาจมีคำฟุ่มเฟือยและประโยคที่ไม่สมบูรณ์
import anthropic
VOICE_AGENT_SYSTEM = (
'You are a helpful voice assistant. The user\'s message was transcribed from speech '
'and may contain filler words ("um", "uh"), false starts, or incomplete sentences. '
'Interpret the intent charitably and respond concisely in 1-3 sentences. '
'Your response will be converted to speech, so avoid markdown, lists, or code blocks.'
)
def voice_agent_respond(transcription: str) -> str:
client = anthropic.Anthropic(api_key='YOUR_ANTHROPIC_API_KEY')
response = client.messages.create(
model='claude-opus-4-5',
max_tokens=256,
system=VOICE_AGENT_SYSTEM,
messages=[{'role': 'user', 'content': transcription}]
)
return response.content[0].textการแปลงข้อความเป็นเสียงด้วย OpenAI TTS
แปลงข้อความตอบกลับของเอเจนต์กลับเป็นเสียงโดยใช้ API ของ OpenAI TTS ให้เลือกเสียง (alloy, echo, fable, onyx, nova, shimmer) และโมเดล (tts-1 สำหรับความเร็ว หรือ tts-1-hd สำหรับคุณภาพ) จากนั้นบันทึกผลลัพธ์เป็นไฟล์ mp3 หรือสตรีมโดยตรง
from openai import OpenAI
from pathlib import Path
client = OpenAI(api_key='YOUR_OPENAI_API_KEY')
def text_to_speech(
text: str,
output_path: str = 'response.mp3',
voice: str = 'nova',
model: str = 'tts-1'
) -> str:
response = client.audio.speech.create(
model=model,
voice=voice,
input=text,
response_format='mp3'
)
Path(output_path).write_bytes(response.content)
print(f'TTS audio saved to {output_path}')
return output_path
# Full pipeline:
tts_file = text_to_speech(
'The weather in London is currently 15 degrees and partly cloudy.',
voice='nova'
)การสตรีมเอาต์พุตเสียง
สำหรับการตอบกลับด้วยเสียงแบบเรียลไทม์ ให้สตรีมเสียง TTS เป็นชิ้นข้อมูลแทนการรอไฟล์ทั้งหมดให้เสร็จสมบูรณ์ ตัวช่วย stream_to_file ของ OpenAI หรือการวนซ้ำผ่านชิ้นข้อมูลด้วยตนเอง จะทำให้คุณเริ่มเล่นเสียงได้ขณะที่ส่วนที่เหลือยังคงกำลังถูกสร้าง
from openai import OpenAI
client = OpenAI(api_key='YOUR_OPENAI_API_KEY')
def stream_tts_to_file(text: str, output_path: str):
# OpenAI SDK streams the audio response
with client.audio.speech.with_streaming_response.create(
model='tts-1',
voice='nova',
input=text,
response_format='mp3'
) as response:
response.stream_to_file(output_path)
print(f'Streamed to {output_path}')
def stream_tts_chunks(text: str):
"""Yield raw audio bytes for piping to an audio player."""
with client.audio.speech.with_streaming_response.create(
model='tts-1',
voice='nova',
input=text
) as response:
for chunk in response.iter_bytes(chunk_size=4096):
yield chunk # pipe to audio player or WebSocketการแบ่งไฟล์เสียงขนาดยาว
ไฟล์เสียงที่มีขนาดใหญ่กว่า 25 MB ต้องถูกแบ่งก่อนส่งให้ Whisper ให้ใช้ไลบรารี pydub แบ่งเสียงตามช่วงเวลาและประมวลผลแต่ละชิ้นแยกกัน จากนั้นจึงนำข้อความถอดเสียงมาต่อกัน
from pydub import AudioSegment
import os
def split_audio(
path: str,
chunk_minutes: int = 10
) -> list:
audio = AudioSegment.from_file(path)
chunk_ms = chunk_minutes * 60 * 1000
chunks = []
os.makedirs('audio_chunks', exist_ok=True)
for i, start in enumerate(range(0, len(audio), chunk_ms)):
chunk = audio[start:start + chunk_ms]
chunk_path = f'audio_chunks/chunk_{i:03d}.mp3'
chunk.export(chunk_path, format='mp3')
chunks.append(chunk_path)
return chunks
def transcribe_long_audio(path: str) -> str:
chunks = split_audio(path, chunk_minutes=10)
transcripts = []
for chunk_path in chunks:
text = transcribe_audio(chunk_path)
transcripts.append(text)
# Clean up chunks
for chunk_path in chunks:
os.remove(chunk_path)
return ' '.join(transcripts)ไปป์ไลน์เสียงแบบเรียลไทม์
ไปป์ไลน์แบบเรียลไทม์จะรับข้อมูลเสียงจากไมโครโฟนเป็นชิ้นข้อมูล ส่งแต่ละชิ้นให้ Whisper ทันทีที่ได้รับ และสตรีมเอาต์พุต TTS กลับมา ทำให้เกิดวงจรสนทนาด้วยเสียงที่เกือบเป็นแบบเรียลไทม์ ความท้าทายสำคัญคือการจัดการความหน่วงในแต่ละขั้นตอน
import asyncio
import time
async def realtime_voice_loop(mic_stream, speaker_stream, client):
"""
mic_stream: async generator yielding audio bytes
speaker_stream: async callable accepting audio bytes
"""
buffer = b''
BUFFER_THRESHOLD = 50 * 1024 # ~3 seconds at 16kHz mono mp3
async for audio_chunk in mic_stream:
buffer += audio_chunk
if len(buffer) >= BUFFER_THRESHOLD:
t0 = time.time()
# Save buffer to temp file
with open('/tmp/voice_chunk.mp3', 'wb') as f:
f.write(buffer)
buffer = b''
# Transcribe
text = transcribe_audio('/tmp/voice_chunk.mp3')
print(f'Transcribed ({time.time()-t0:.1f}s): {text}')
# Agent response
reply = voice_agent_respond(text)
# TTS and stream to speaker
for audio_bytes in stream_tts_chunks(reply):
await speaker_stream(audio_bytes)การตรวจจับภาษาและการกำหนดเส้นทางอัตโนมัติ
Whisper ตรวจจับภาษาที่พูดโดยอัตโนมัติ ให้ใช้ภาษาที่ตรวจจับได้เพื่อกำหนดเส้นทางการสนทนาไปยังบุคลิกของเอเจนต์ที่ถูกต้อง หรือกำหนดภาษาของ TTS สำหรับการตอบกลับ
def transcribe_and_detect_language(audio_path: str) -> dict:
from openai import OpenAI
client = OpenAI(api_key='YOUR_OPENAI_API_KEY')
with open(audio_path, 'rb') as f:
result = client.audio.transcriptions.create(
model='whisper-1',
file=f,
response_format='verbose_json'
)
return {
'text': result.text,
'language': result.language, # e.g. 'english', 'spanish'
'duration': result.duration
}
LANGUAGE_VOICE_MAP = {
'english': 'nova',
'spanish': 'alloy',
'french': 'echo',
'german': 'fable'
}
def respond_in_detected_language(audio_path: str) -> str:
info = transcribe_and_detect_language(audio_path)
voice = LANGUAGE_VOICE_MAP.get(info['language'], 'nova')
reply = voice_agent_respond(info['text'])
return text_to_speech(reply, voice=voice)การจัดการเสียงรบกวนเบื้องหลังและเสียงคุณภาพต่ำ
เสียงคุณภาพต่ำทำให้ความแม่นยำในการถอดเสียงลดลง วิธีรับมือที่ใช้ได้จริง ได้แก่ ประมวลผลล่วงหน้าด้วยการลดเสียงรบกวน (ไลบรารี noisereduce) เพิ่มคลังคำศัพท์เฉพาะด้านใน prompt ของ Whisper ตรวจสอบความเชื่อมั่นของข้อความถอดเสียง และขอคำชี้แจงเพิ่มเติมเมื่อความเชื่อมั่นต่ำ
def transcribe_with_quality_check(
audio_path: str,
min_confidence_words: int = 3
) -> dict:
from openai import OpenAI
import string
client = OpenAI(api_key='YOUR_OPENAI_API_KEY')
with open(audio_path, 'rb') as f:
result = client.audio.transcriptions.create(
model='whisper-1',
file=f,
response_format='verbose_json',
timestamp_granularities=['word']
)
# Word count as a basic quality proxy
words = result.text.translate(
str.maketrans('', '', string.punctuation)
).split()
quality_ok = len(words) >= min_confidence_words
return {
'text': result.text,
'word_count': len(words),
'quality_ok': quality_ok,
'fallback_message': None if quality_ok else 'I could not hear you clearly. Please repeat.'
}ตรวจสอบความรู้
พารามิเตอร์ prompt ของ Whisper ทำหน้าที่อะไร
สรุป: เวิร์กโฟลว์เอเจนต์เสียง-ข้อความ
ยอดเยี่ยม! ประเด็นสำคัญมีดังนี้:
- Whisper: รองรับ mp3/wav/m4a และรูปแบบอื่น ๆ ขนาดสูงสุด 25 MB ให้แบ่งไฟล์ขนาดใหญ่ด้วย pydub
- การประทับเวลา: ใช้
verbose_jsonร่วมกับtimestamp_granularitiesเพื่อระบุเวลาของแต่ละส่วน - TTS: OpenAI TTS มีตัวเลือกเสียงหลากหลาย และสามารถสตรีมชิ้นข้อมูลเพื่อลดความหน่วง
- การตรวจจับภาษา: Whisper ตรวจจับภาษาโดยอัตโนมัติ แล้วกำหนดเส้นทางไปยังเสียงหรือเอเจนต์ที่ถูกต้องตามภาษาที่ตรวจจับได้
- ไปป์ไลน์แบบเรียลไทม์: บัฟเฟอร์ชิ้นข้อมูลเสียง → ถอดเสียง → เอเจนต์ → สตรีม TTS
ถัดไป: การทำความเข้าใจวิดีโอในเอเจนต์ — การแยกเฟรมและการให้เหตุผลตามลำดับเวลา
คำถามที่พบบ่อย
บทเรียน “เวิร์กโฟลว์เอเจนต์เสียง + ข้อความ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “เวิร์กโฟลว์เอเจนต์เสียง + ข้อความ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “เวิร์กโฟลว์เอเจนต์เสียง + ข้อความ”
การถอดเสียง → การให้เหตุผล → สายงานตอบกลับด้วยเสียงตั้งแต่ต้นจนจบ คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “เวิร์กโฟลว์เอเจนต์เสียง + ข้อความ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม
ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เอเจนต์ภาพ + ข้อความด้วย Claude Vision และ GPT-4V
- เวิร์กโฟลว์เอเจนต์เสียง + ข้อความ
- การทำความเข้าใจวิดีโอในเอเจนต์
- รูปแบบการให้เหตุผลข้ามสื่อ