حول المحتوى:
تعرف على كيفية تحديد فترات الصمت والكلام في الصوت باستخدام WebRTC VAD لتحسين تقطيع الصوت ورفع دقة نماذج التعرف على الكلام، مع شرح عملي وأمثلة في بايثون.
كيفية تحديد فترات الصمت والكلام في الصوت باستخدام WebRTC VAD أصبحت خطوة أساسية في تطبيقات الذكاء الاصطناعي الصوتية، مثل: التعرف على الكلام، أنظمة الرد الآلي، تسجيل المكالمات، وتطبيقات تحليل الصوت. في هذا الشرح سنركز على كيفية استخدام WebRTC VAD في بايثون لتحديد متى يكون هناك كلام ومتى يكون صمت في نفس اللحظة تقريباً (Real-time أو شبه لحظي)، مع أمثلة عملية ونصائح لتحسين النتائج.
إذا لم تكن قد جهزت بيئة بايثون من قبل، يمكنك الرجوع إلى: خطوات تثبيت بايثون على جهاز بنظام ويندوز ثم شرح البيئة الافتراضية في بايثون لتهيئة بيئة عمل مستقلة لمشروعك.
VAD اختصار لـ Voice Activity Detection، أي اكتشاف وجود صوت بشري (كلام) في الإشارة الصوتية. مكتبة WebRTC VAD هي جزء من مشروع WebRTC من جوجل، وتم تصميمها لتعمل في الزمن الحقيقي لاكتشاف الكلام بدقة وسرعة معقولة.
يمكننا باستخدام WebRTC VAD تقسيم أي إشارة صوتية أو بث مباشر إلى:
هذا التقسيم ضروري قبل تمرير الصوت إلى نموذج التعرف على الكلام (ASR) لأنه:
WebRTC VAD لا يحول الصوت إلى نص، بل يأخذ Frame صوتي قصير (مثل 10 أو 20 أو 30 ميلي ثانية) ويعيد كقيمة منطقية:
يعتمد في قراره على:
لذلك، لمعرفة كيفية تحديد فترات الصمت والكلام في الصوت باستخدام WebRTC VAD، سنقوم بتقسيم الصوت إلى Frames صغيرة وتمرير كل Frame إلى VAD بشكل متتابع، ثم نجمع نتائج هذه الـ Frames لتكوين مقاطع الكلام والصمت.
قبل الدخول في الكود، تحتاج إلى:
webrtcvad، ومكتبات للتعامل مع الصوت مثل pyaudio أو sounddevice في حالة العمل مع الميكروفون.من خلال الطرفية (Terminal أو CMD):
pip install webrtcvad
للتعامل مع ملفات WAV يمكن استخدام wave المدمجة مع بايثون، وللتسجيل من الميكروفون يمكنك استخدام أحد الخيارين:
pip install pyaudio
أو pip install sounddevice
مكتبة webrtcvad في بايثون توفر كائن بسيط للعمل معه. الفكرة العامة:
True/False لكل Frame.import webrtcvad
vad = webrtcvad.Vad()
vad.set_mode(2) # 0 أقل حساسية - 3 أعلى حساسية
# لاحقاً: vad.is_speech(frame_bytes, sample_rate)
يمكنك التجربة بين 1 و 2 و 3 حتى تصل للنتيجة الأنسب لتطبيقك.
لنفترض أن لدينا ملف WAV أحادي القناة (Mono) بتردد 16000 Hz و16-bit PCM. سنقرأ الملف، نقسمه إلى Frames، ثم نستخدم WebRTC VAD لتحديد الكلام.
import wave
import webrtcvad
def read_wave(path):
with wave.open(path, 'rb') as wf:
num_channels = wf.getnchannels()
assert num_channels == 1, "الملف يجب أن يكون Mono"
sample_width = wf.getsampwidth()
assert sample_width == 2, "الملف يجب أن يكون 16-bit PCM"
sample_rate = wf.getframerate()
assert sample_rate in (8000, 16000, 32000, 48000), "معدل العينات غير مدعوم"
pcm_data = wf.readframes(wf.getnframes())
return pcm_data, sample_rate
def frame_generator(frame_duration_ms, audio, sample_rate):
n = int(sample_rate * (frame_duration_ms / 1000.0) * 2) # 2 بايت لكل عينة 16-bit
offset = 0
while offset + n <= len(audio):
yield audio[offset:offset + n]
offset += n
def detect_speech_segments(path, frame_duration_ms=30, mode=2):
audio, sample_rate = read_wave(path)
vad = webrtcvad.Vad(mode)
frames = list(frame_generator(frame_duration_ms, audio, sample_rate))
speech_frames = []
segments = []
in_speech = False
start_index = 0
for i, frame in enumerate(frames):
is_speech = vad.is_speech(frame, sample_rate)
if is_speech and not in_speech:
# بداية مقطع كلام
in_speech = True
start_index = i
speech_frames = [frame]
elif is_speech and in_speech:
# استمرار الكلام
speech_frames.append(frame)
elif not is_speech and in_speech:
# نهاية مقطع كلام
in_speech = False
end_index = i
segments.append((start_index, end_index, b''.join(speech_frames)))
speech_frames = []
# في حالة انتهى الملف ونحن داخل كلام
if in_speech and speech_frames:
segments.append((start_index, len(frames), b''.join(speech_frames)))
# حساب الأزمنة بالثواني
segments_with_time = []
for start, end, data in segments:
start_time = (start * frame_duration_ms) / 1000.0
end_time = (end * frame_duration_ms) / 1000.0
segments_with_time.append({
"start": start_time,
"end": end_time,
"data": data
})
return segments_with_time
if __name__ == "__main__":
segments = detect_speech_segments("input.wav")
for seg in segments:
print(f"كلام من {seg['start']:.2f} إلى {seg['end']:.2f} ثانية")
بهذا الشكل نكون قد طبقنا عملياً كيفية تحديد فترات الصمت والكلام في الصوت باستخدام WebRTC VAD على ملف صوتي كامل، وحصلنا على أزمنة بداية ونهاية كل مقطع كلام بدقة الإطار المستخدم.
لتحديد الكلام والصمت في نفس اللحظة تقريباً من الميكروفون، نحتاج إلى:
المثال التالي يستخدم مكتبة pyaudio:
import pyaudio
import webrtcvad
import struct
import time
RATE = 16000
FRAME_DURATION_MS = 30 # طول الإطار
FRAME_SIZE = int(RATE * FRAME_DURATION_MS / 1000) # عدد العينات في كل إطار
CHANNELS = 1
vad = webrtcvad.Vad(2) # حساسية متوسطة
p = pyaudio.PyAudio()
stream = p.open(
format=pyaudio.paInt16,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=FRAME_SIZE
)
print("ابدأ التحدث (Ctrl+C للإيقاف)...")
try:
while True:
data = stream.read(FRAME_SIZE, exception_on_overflow=False)
# data بالفعل Bytes 16-bit PCM Mono إذا كانت الإعدادات صحيحة
is_speech = vad.is_speech(data, RATE)
timestamp = time.time()
if is_speech:
print(f"{timestamp}: كلام")
else:
print(f"{timestamp}: صمت/ضوضاء")
except KeyboardInterrupt:
print("تم الإيقاف.")
finally:
stream.stop_stream()
stream.close()
p.terminate()
في هذا المثال، كل 30ms من الصوت تُسحب من الميكروفون وتُمرر إلى WebRTC VAD، ليعطيك نتيجة فورية تقريباً ما إذا كان هناك كلام أم لا. يمكنك ربط هذه النتيجة مباشرة بتسجيل الصوت، أو إرسال Frames الكلام فقط إلى خادم التعرف على الكلام، أو تشغيل منطق معين (مثلاً: بدء تسجيل عند ظهور الكلام).
تحديد الكلام بناءً على Frame واحدة قد يكون متذبذباً أحياناً (Frame كلام يتبعه Frame صمت وهكذا). لتحسين الاستقرار، نستخدم عادة نافذة منزلقة (Sliding Window) أو عتبات زمنية:
هذا يقلل التقطيع الزائد ويجعل المقاطع أكثر منطقية. مثال مبسط:
from collections import deque
def realtime_vad_with_hysteresis():
import pyaudio, webrtcvad
RATE = 16000
FRAME_DURATION_MS = 30
FRAME_SIZE = int(RATE * FRAME_DURATION_MS / 1000)
CHANNELS = 1
vad = webrtcvad.Vad(2)
p = pyaudio.PyAudio()
stream = p.open(
format=pyaudio.paInt16,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=FRAME_SIZE
)
# معلمات التحكم
speech_start_threshold = 5 # عدد الإطارات المتتالية لاعتبار بداية كلام
speech_end_threshold = 10 # عدد الإطارات المتتالية لاعتبار نهاية كلام
speech_buffer = deque(maxlen=speech_start_threshold)
silence_buffer = deque(maxlen=speech_end_threshold)
in_speech = False
print("تحدث وسيتم اكتشاف الكلام والصمت...")
try:
while True:
data = stream.read(FRAME_SIZE, exception_on_overflow=False)
is_speech = vad.is_speech(data, RATE)
if is_speech:
speech_buffer.append(1)
silence_buffer.clear()
else:
silence_buffer.append(1)
speech_buffer.clear()
if not in_speech and len(speech_buffer) == speech_start_threshold:
in_speech = True
print("بداية كلام")
if in_speech and len(silence_buffer) == speech_end_threshold:
in_speech = False
print("نهاية كلام")
except KeyboardInterrupt:
print("تم الإيقاف.")
finally:
stream.stop_stream()
stream.close()
p.terminate()
if __name__ == "__main__":
realtime_vad_with_hysteresis()
بهذه الطريقة نحصل على تحديد فترات الصمت والكلام في الصوت باستخدام WebRTC VAD بشكل أكثر استقراراً، مع إشعارات “بداية كلام” و“نهاية كلام” في نفس اللحظة تقريباً مع الحدث الفعلي.
بعد أن نستطيع تقسيم الصوت إلى مقاطع كلام وصمت، يمكننا:
إذا كنت مهتماً بتشغيل النماذج محلياً، يمكنك الاطلاع على: تشغيل نماذج الذكاء الاصطناعي محلياً باستخدام Ollama: دليل المطورين لرؤية كيف يمكن دمج التقنيات الصوتية مع نماذج لغوية تعمل على جهازك.
pydub أو ffmpeg للتحويل.speech_start_threshold وspeech_end_threshold تعتمد على نوع الكلام (سريع/بطيء)، جرّب عدة قيم.فهم كيفية تحديد فترات الصمت والكلام في الصوت باستخدام WebRTC VAD هو خطوة أساسية لأي نظام يعتمد على الصوت:
WebRTC VAD يوفر لك حل جاهز وخفيف الوزن، يعمل في الزمن الحقيقي، ويمكن دمجه بسهولة مع مشاريع بايثون. من خلال تقسيم الصوت إلى Frames صغيرة وتمريرها للمكتبة، ثم استخدام بعض المنطق التجميعي (مثل النافذة المنزلقة)، يمكنك الوصول إلى كشف دقيق ومستقر لمناطق الكلام والصمت، وبالتالي تحسين أداء نماذج التعرف على الكلام بشكل ملحوظ.
إذا كنت تعمل على مشاريع بايثون أكبر، فقد تحتاج أيضاً إلى تنظيم الكود واختباره باستخدام أدوات مثل pytest لاختبار الوحدات في بايثون لضمان استقرار منطق VAD وتقطيع الصوت مع الوقت.
تعرف على كيفية تحديد فترات الصمت والكلام في الصوت باستخدام WebRTC VAD لتحسين تقطيع الصوت ورفع دقة نماذج التعرف على الكلام، مع شرح عملي وأمثلة في بايثون.
مساحة اعلانية