المتعرّف على الكلام لا يحتاج إلى سماع لوحة المفاتيح، ولا مكيّف الهواء، ولا الثواني الثلاث من الصمت أثناء تفكيرك.
يستخدم Voice Type كاشف نشاط الصوت Silero بنمط البث المتدفق ليقرر أي أجزاء من تدفق الميكروفون هي كلام. وكل ما يأتي بعد ذلك، بما في ذلك طول كل دفعة ووقت تشغيل النموذج، يتحدد بناءً على ما تعلّمه هذه البوابة.
تصحيح. ذكرت نسخة سابقة من هذه الصفحة أن Voice Type يستخدم RNNoise. هذا غير صحيح، ولم يحدث قط. لم يُشحن التطبيق مع RNNoise في أي وقت، وكان الادعاء خاطئًا حين نشرناه. البوابة هي Silero، والإعدادات أدناه هي التي تُشحن فعليًا. إذا وصلت إلى هنا وأنت تبحث عن RNNoise، فالقسم التالي لك.
RNNoise، ولماذا ليس هو البوابة
RNNoise شبكة عصبية متكررة لكبت الضوضاء، نشرتها Xiph.Org وأُطلقت برخصة BSD. إنها صغيرة وسريعة وجيدة فعلًا فيما تفعله: تأخذ كلامًا مشوبًا بالضوضاء وتعيد كلامًا أنقى. وهي موجودة داخل كثير من برامج الصوت، والنسخة التي يصادفها معظم الناس هي المضمّنة مع OBS.
السبب في عدم وجودها في Voice Type هو أن كبت الضوضاء واكتشاف نشاط الصوت مهمتان مختلفتان.
- كبت الضوضاء يغيّر الصوت. فهو يُضعف ما يحكم بأنه ضوضاء ويمرّر الباقي، لذا فإن الإشارة المسلَّمة إلى المراحل التالية ليست الإشارة التي التُقطت.
- اكتشاف نشاط الصوت لا يغيّر شيئًا. فهو يقرأ الصوت ويضع علامات على المقاطع التي تحتوي على كلام. ويظل المتعرّف يتلقى العيّنات الأصلية.
يُظهر RNNoise فعلًا احتمال نشاط صوتي كناتج جانبي لعملية الكبت التي يجريها، ولهذا يظهر في عمليات البحث عن VAD. لكن استخدام ذلك الناتج كبوابة يعني تشغيل أداة كبت لا تريدها من أجل الحصول على إشارة ليست غرضها الرئيسي. Silero كاشف، فيؤدي مهمة الاكتشاف مباشرةً ويترك الصوت دون تغيير.
هذا الفرق أهم في الإملاء منه في المكالمة. في المكالمة، الهدف هو صوت يبدو أنقى، وإذا أزالت أداة الكبت بعض الكلام الحقيقي مع صوت المروحة فهذه مقايضة مقبولة لأن المستمع يملأ الفجوة. أما المتعرّف فلا يملأ الفجوة. إنه ينسخ ما يُعطى له، لذا فالصوت الذي عُدِّل قبل التعرف قد يكلّف دقة، وتحديدًا في الحروف الساكنة التي يصعب على أداة الكبت تمييزها عن الضوضاء.
إذا كنت تبحث عن عتبة VAD لـ RNNoise، فالقيمة تعتمد على الغلاف البرمجي الذي تستخدمه، لأن RNNoise نفسه يُرجع احتمالًا بين 0 و1 وكل تكامل يختار حد القطع الخاص به. للمرجعية، الأرقام المقابلة في بوابة Silero في هذا التطبيق هي 0.30 للبقاء في الكلام و0.22 للدخول فيه، والمنطق وراء القيمتين في القسم أدناه. هذه الأرقام تخص Silero لا RNNoise، ولن تنتقل مباشرةً.
RNNoise برنامج جيد. إنه يحل مشكلة ليست لدينا.
باختصار
- التقطيع هو ما يحدد ما يُعطى للمتعرّف. النموذج الذي يُعطى صمتًا يُرجع نصًا مع ذلك، لأن إرجاع النص هو ما يفعله.
- تعمل البوابة على إطارات من 512 عيّنة بتردد 16 كيلوهرتز، بعتبة كلام قدرها 0.30.
- تحصل مناطق الكلام على 1,000 مللي ثانية من التمهيد المسبق (pre-roll) للعبارة الأولى، ثم 150 مللي ثانية على كل جانب، حتى لا تُقتطع الكلمات عند الحدود.
- لا تُرسَل دفعة أقصر من 5 ثوانٍ عند التوقف أبدًا. بل تنتظر العبارة التالية.
لماذا التقطيع، لا النموذج، هو ما يحدد سقف الدقة
أعطِ المتعرّف مقطع كلام نظيفًا فسينسخ الكلام. أعطه ثلاث ثوانٍ من أزيز التكييف مع كلمة واحدة مدفونة فيه وسيظل فاك الترميز يُنتج نصًا. يبدو الفشل كخطأ في النموذج، وهو في الحقيقة خطأ في المُدخل.
لهذا السبب تكون البوابة هي المكوّن المثير للاهتمام. فهي ليست موجودة لجعل الصوت يبدو أجمل للإنسان. بل هي موجودة للتأكد من أن النموذج لا يُسأل إلا عن صوت يحتوي على سؤال.
الإعدادات التي تُشحن
هذه هي القيم الافتراضية الحالية في وضع الإملاء المتوازن، وهو الوضع الذي يعمل ما لم تنتقل إلى الالتقاط الخام.
| الإعداد | القيمة | | --- | --- | | حجم الإطار | 512 عيّنة بتردد 16 كيلوهرتز | | عتبة الكلام | 0.30 | | عتبة البدء الهادئ | 0.22 | | التمهيد المسبق قبل العبارة الأولى | 1,000 مللي ثانية | | التمهيد المسبق في العبارات اللاحقة | 150 مللي ثانية | | التمهيد اللاحق | 150 مللي ثانية | | الصمت الذي يغلق العبارة، مباشرةً | 400 مللي ثانية | | الصمت الذي يغلق العبارة، عند الإيقاف | 350 مللي ثانية |
العتبتان هما الجزء الذي يستحق الفهم. العتبة الواحدة يجب أن تكون حساسة بما يكفي لالتقاط مقطع أول هادئ، وصارمة بما يكفي لتجاهل المروحة. هاتان مهمتان مختلفتان، لذا تستخدم البوابة حدًا أدنى (0.22) عندما تنتظر بدء الكلام، والحد المعتاد (0.30) بمجرد أن يكون الكلام جاريًا.
ويؤدي التمهيد المسبق غير المتماثل الحيلة نفسها في المجال الزمني. الكلمة الأولى من العبارة هي الأكثر عرضة للاقتطاع، لأن البوابة لا تملك قبلها شيئًا تعمل عليه، لذا تحصل على ثانية كاملة من الصوت قبل نقطة الاكتشاف. أما العبارات اللاحقة فتحتاج إلى 150 مللي ثانية فقط، لأن البوابة تتابعك بالفعل.
لماذا تنتظر الدفعة القصيرة
يُلحِق المجمِّع مناطق الكلام كاملةً ويرفض قطع إحداها إلى نصفين. كما يرفض إرسال دفعة أقصر من أن تستحق عملية فك ترميز.
إذا كانت الدفعة الحالية تحتوي على أقل من 5 ثوانٍ من الصوت المحدد وتوقفتَ عن الكلام، فلن يُرسَل شيء. تبقى الدفعة بعد التوقف وتنضم إليها العبارة التالية. هذا مقصود: مقطع مدته 1.5 ثانية يُفك ترميزه وحده لا سياق حوله، ونماذج عائلة Whisper تستخدم السياق. مقطعان يُفك ترميزهما معًا أفضل من مقطعين يُفك ترميزهما منفصلين.
عند علامة الـ 5 ثوانٍ تُستأنف القواعد المعتادة: توقف لمدة 400 مللي ثانية بعد عبارة مغلقة يُفرِّغ الدفعة، وكذلك عبارة من شأنها دفع الدفعة إلى ما بعد هدف الـ 29 ثانية. وعندما تحرر الاختصار، يُفرَّغ كل ما تبقى بغض النظر عن الطول.
تعمل البوابة على خيط CPU واحد حتى لا تتنافس أبدًا مع المتعرّف على وحدة GPU. المصدر: StreamingSileroSpeechGate.swift.
المسار الذي تسلكه الدفعة
بمجرد تفريغ الدفعة، تُهيَّأ ثم يُفك ترميزها:
- إزالة إزاحة التيار المستمر (DC).
- تطبيق المرشّحات النشطة والتحكم في الجهارة، بما في ذلك مرشّح تمرير عالٍ عند 50 هرتز افتراضيًا.
- إعادة العيّنة إلى 16 كيلوهرتز التي يتوقعها Whisper، إذا لم يكن جهاز الالتقاط عندها أصلًا.
- تشغيل النموذج خارج الممثل الرئيسي (main actor).
- ضم النص الناتج إلى النص المفرَّغ، مع إزالة الكلمات المكررة عند حدود الدفعة.
الخطوة 5 أهم مما تبدو. فلأن الدفعات يُفك ترميزها بشكل مستقل، يمكن أن تظهر الكلمة نفسها في نهاية إحداها وبداية التالية. كما تُمرَّر آخر الكلمات المعتمدة إلى الأمام كسياق للموجِّه (prompt)، فيعرف النموذج ما قاله للتو دون إعادة فك ترميز الصوت القديم.
عندما تفشل البوابة
اكتشاف نشاط الصوت نموذج أيضًا، ويمكن أن يخطئ. إذا فشل Silero تمامًا، يمكن للمسار الرجوع إلى استخدام الصوت الملتقط كمقاطع احتياطية موسومة.
وهناك استثناء متعمّد واحد. إذا عملت البوابة بشكل طبيعي وأبلغت عن عدم وجود أي كلام، فإن التطبيق لا يرجع إلى عتبة الطاقة. فذلك هو نمط الفشل الذي تتحول فيه المراوح والكتابة ونقرة مفتاح الإيقاف إلى نص مفرَّغ، والنص المفرَّغ الزائف أسوأ من عدم وجود نص.
ذو صلة: لماذا أوقفنا مشفّر Core ML · إعادة العيّنة إلى 16 كيلوهرتز
