شارك المقالة

تحويل الصوت إلى نص Flutter Speech to Text باستخدام talk_it ودعم اللغة العربية

إذا كنت تريد إضافة ميزة Speech to Text إلى تطبيق Flutter، سواء لإنشاء البحث الصوتي، كتابة الرسائل بالصوت، تنفيذ الأوامر الصوتية، أو إضافة مساعد ذكي داخل التطبيق، فإن مكتبة talk_it توفر طريقة بسيطة وخفيفة لتنفيذ ذلك على Android وiOS.

تعتمد المكتبة على أنظمة التعرف على الصوت الموجودة بشكل Native داخل النظام، بدون الاعتماد على SDK خارجي لخدمات Speech-to-Text، كما توفر دعمًا جيدًا للغة العربية وإمكانية استخدام أسلوب Push to Talk.

ما هي مكتبة talk_it؟

talk_it هي مكتبة Flutter مخصصة لتحويل كلام المستخدم إلى نص باستخدام أدوات التعرف الصوتي الأصلية الموجودة في Android وiOS.

على Android تعتمد المكتبة على:


SpeechRecognizer
RecognizerIntent

بينما على iOS تعتمد على:


SFSpeechRecognizer
AVAudioEngine

وبذلك تستطيع استخدام إمكانيات التعرف على الصوت الخاصة بالنظام من خلال API بسيطة داخل Flutter.

ما الذي يميز talk_it؟

  • دعم Android وiOS.
  • واجهة API بسيطة جدًا.
  • دعم اللغة العربية مثل ar-EG.
  • الحصول على النص أثناء تحدث المستخدم.
  • معرفة متى أصبحت نتيجة التعرف نهائية.
  • دعم Push-to-Talk.
  • إيقاف التسجيل تلقائيًا بعد الصمت.
  • إمكانية إلغاء جلسة التعرف الصوتي.
  • لا تعتمد على SDK خاص بخدمة Speech-to-Text خارجية.
  • تعتمد بشكل أساسي على Flutter فقط.

تثبيت talk_it في Flutter

الإصدار الحالي المنشور على pub.dev وقت كتابة المقال هو:


talk_it: ^1.0.1

قم بإضافته داخل ملف:


pubspec.yaml

بهذا الشكل:


dependencies:
  flutter:
    sdk: flutter

  talk_it: ^1.0.1

ثم نفذ:


flutter pub get

إضافة صلاحية الميكروفون على Android

قبل استخدام التعرف الصوتي تحتاج إلى منح التطبيق صلاحية الوصول إلى الميكروفون.

افتح الملف:


android/app/src/main/AndroidManifest.xml

ثم أضف:


<uses-permission android:name="android.permission.RECORD_AUDIO"/>

كما تحتاج إلى إضافة الاستعلام الخاص بخدمات التعرف على الصوت:


<queries>
    <intent>
        <action android:name="android.speech.RecognitionService"/>
    </intent>
</queries>

ليصبح جزء الإعدادات بالشكل التالي:


<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission
        android:name="android.permission.RECORD_AUDIO"/>

    <queries>
        <intent>
            <action
                android:name="android.speech.RecognitionService"/>
        </intent>
    </queries>

</manifest>

ويشير مطور المكتبة إلى أن وجود تطبيق Google على الجهاز قد يعطي نتائج أفضل، خصوصًا عند استخدام التعرف على اللغة العربية.

إعداد صلاحيات iOS

على iOS نحتاج إلى صلاحيتين:

  • صلاحية استخدام الميكروفون.
  • صلاحية استخدام Speech Recognition.

افتح:


ios/Runner/Info.plist

وأضف:


<key>NSMicrophoneUsageDescription</key>
<string>We need the microphone for voice input.</string>

<key>NSSpeechRecognitionUsageDescription</key>
<string>We need speech recognition to transcribe your voice.</string>

ويمكنك بالطبع تغيير رسائل الصلاحيات إلى النص المناسب لتطبيقك.

طلب صلاحية الميكروفون أثناء تشغيل التطبيق

المكتبة لا تقوم بطلب صلاحيات الميكروفون تلقائيًا، ولذلك يجب عليك إدارتها بنفسك.

يمكن استخدام مكتبة:


permission_handler

وإضافتها إلى المشروع:


dependencies:
  permission_handler: latest_version

ثم إنشاء Function للتحقق من الصلاحيات:


import 'dart:io';

import 'package:permission_handler/permission_handler.dart';

Future<bool> ensurePermissions() async {

  final microphone =
      await Permission.microphone.request();

  if (!microphone.isGranted) {
    return false;
  }

  if (Platform.isIOS) {
    final speech =
        await Permission.speech.request();

    if (!speech.isGranted) {
      return false;
    }
  }

  return true;
}

إنشاء TalkIt

بعد إعداد الصلاحيات يمكن إنشاء Object من المكتبة:


import 'package:talk_it/talk_it.dart';

final TalkIt talk = TalkIt();

ومن خلال هذا الـ Object يمكننا بدء وإيقاف جلسات التعرف على الصوت.

تهيئة Speech Recognition

قبل بدء الاستماع يجب تنفيذ:


await talk.initialize();

وترجع الدالة قيمة من نوع bool تخبرنا هل Speech Recognition متاح على الجهاز أم لا.


final available =
    await talk.initialize();

if (!available) {
  print('Speech recognition is not available');
}

استخدام اللغة العربية

من أهم مميزات talk_it اهتمامها بدعم اللغة العربية.

يمكن تحديد اللغة أثناء التهيئة:


final available =
    await talk.initialize(
  localeId: 'ar-EG',
);

حيث:


ar-EG

تعني اللغة العربية باللهجة أو الإعداد المصري.

ويمكن استخدام Locale آخر حسب اللغات المتوفرة في خدمة Speech Recognition على جهاز المستخدم.

بدء تحويل الصوت إلى نص

بعد التهيئة يمكن بدء الاستماع باستخدام:


await talk.listen(
  onResult: (result) {
    print(result.recognizedWords);
  },
);

كلما تعرف النظام على كلمات جديدة يتم إرسال النتيجة داخل:


onResult

ويمكن الحصول على النص من:


result.recognizedWords

معرفة النتيجة النهائية

أثناء تحدث المستخدم قد تصل أكثر من نتيجة مؤقتة قبل انتهاء الجملة.

لذلك توفر talk_it الخاصية:


result.isFinal

مثال:


await talk.listen(
  onResult: (result) {

    print(result.recognizedWords);

    if (result.isFinal) {

      print(
        'Final: ${result.recognizedWords}',
      );

    }
  },
);

وهذه الخاصية مهمة جدًا إذا كنت تريد إرسال النص إلى API أو إلى نموذج ذكاء اصطناعي فقط بعد انتهاء المستخدم من الكلام.

مثال: إرسال النص إلى AI بعد انتهاء الكلام


await talk.listen(
  localeId: 'ar-EG',

  onResult: (result) {

    if (result.isFinal) {

      sendToAI(
        result.recognizedWords,
      );

    }

  },
);

هذا الأسلوب مناسب جدًا لإنشاء:

  • AI Voice Assistant.
  • Chatbot صوتي.
  • البحث الصوتي.
  • إدخال البيانات بالصوت.
  • إرسال رسائل صوتية يتم تحويلها إلى نص.

إنشاء واجهة Speech to Text كاملة

يمكننا الآن إنشاء صفحة بسيطة تحتوي على زر ميكروفون وتحويل كلام المستخدم إلى نص.


import 'package:flutter/material.dart';
import 'package:talk_it/talk_it.dart';

class VoicePage extends StatefulWidget {
  const VoicePage({super.key});

  @override
  State<VoicePage> createState() =>
      _VoicePageState();
}

class _VoicePageState
    extends State<VoicePage> {

  final TalkIt talk = TalkIt();

  bool enabled = false;

  String words = '';

  @override
  void initState() {
    super.initState();

    initializeSpeech();
  }

  Future<void> initializeSpeech() async {

    enabled =
        await talk.initialize(
      localeId: 'ar-EG',

      onStatus: (status) {
        debugPrint(status);
      },

      onError: (error) {
        debugPrint(error);
      },
    );

    setState(() {});
  }

  Future<void> startListening() async {

    await talk.listen(
      onResult: (result) {

        setState(() {
          words =
              result.recognizedWords;
        });

      },
    );

    setState(() {});
  }

  Future<void> stopListening() async {

    await talk.stop();

    setState(() {});
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(
        title: const Text(
          'Talk It',
        ),
      ),

      body: Center(
        child: Padding(
          padding:
              const EdgeInsets.all(20),

          child: Text(
            talk.isListening
                ? words
                : enabled
                    ? 'اضغط على الميكروفون'
                    : 'Speech Recognition غير متاح',

            textDirection:
                TextDirection.rtl,

            textAlign:
                TextAlign.center,

            style:
                const TextStyle(
              fontSize: 24,
            ),
          ),
        ),
      ),

      floatingActionButton:
          FloatingActionButton(

        onPressed:
            talk.isNotListening
                ? startListening
                : stopListening,

        child: Icon(
          talk.isNotListening
              ? Icons.mic
              : Icons.stop,
        ),
      ),
    );
  }
}

طرق الاستماع داخل talk_it

توفر المكتبة طريقتين أساسيتين للتحكم في جلسة التسجيل.

1. التوقف عند صمت المستخدم

وهو الوضع الافتراضي والمناسب للجمل القصيرة والأوامر الصوتية.


await talk.listen(
  onResult: (result) {

    print(
      result.recognizedWords,
    );

  },

  listenOptions:
      const TalkItListenOptions(

    mode:
        TalkItMode.untilSilence,

  ),
);

في هذا الوضع يقوم النظام بإيقاف جلسة الاستماع بعد ملاحظة توقف المستخدم عن الكلام لفترة قصيرة.

Push to Talk في Flutter

الطريقة الثانية هي Push to Talk.

في هذا الوضع تستمر جلسة التعرف على الصوت حتى تقوم أنت باستدعاء:


talk.stop();

لبدء الجلسة:


await talk.listen(
  onResult: (result) {

    print(
      result.recognizedWords,
    );

  },

  listenOptions:
      const TalkItListenOptions(

    mode:
        TalkItMode.untilStopped,

  ),
);

ثم عندما يرفع المستخدم إصبعه من زر الميكروفون مثلًا:


await talk.stop();

هذا الوضع مناسب جدًا لتطبيقات المحادثة والرسائل الصوتية.

إنشاء زر Push to Talk

يمكن استخدام:


GestureDetector

لبدء الاستماع عند الضغط وإيقافه عند رفع الإصبع.


GestureDetector(

  onLongPressStart: (_) async {

    await talk.listen(

      onResult: (result) {

        setState(() {

          words =
              result.recognizedWords;

        });

      },

      listenOptions:
          const TalkItListenOptions(

        mode:
            TalkItMode.untilStopped,

      ),
    );
  },

  onLongPressEnd: (_) async {

    await talk.stop();

  },

  child: Container(
    width: 80,
    height: 80,

    decoration:
        const BoxDecoration(

      shape: BoxShape.circle,

      color: Colors.blue,

    ),

    child:
        const Icon(
      Icons.mic,
      color: Colors.white,
    ),
  ),
)

وبذلك يحصل المستخدم على تجربة مشابهة لتطبيقات المحادثة:


اضغط باستمرار 🎙️
        ↓
تحدث
        ↓
ارفع إصبعك
        ↓
تحويل الكلام إلى نص

إيقاف Speech Recognition

لإيقاف جلسة الاستماع بشكل طبيعي استخدم:


await talk.stop();

عندها يتم إنهاء الجلسة والحصول على النتيجة النهائية من خلال onResult.

إلغاء جلسة Speech Recognition

إذا أردت إلغاء العملية بالكامل بدون انتظار نتيجة نهائية استخدم:


await talk.cancel();

وهذا مفيد مثلًا عندما يقوم المستخدم بإغلاق النافذة أو الضغط على زر إلغاء.

الفرق بين stop و cancel


stop()

يقوم بإنهاء جلسة الاستماع بشكل طبيعي والحصول على النتيجة النهائية.

أما:


cancel()

فيقوم بإلغاء جلسة التعرف الصوتي بدون انتظار النتيجة النهائية.

معرفة هل التطبيق يستمع حاليًا

توفر المكتبة:


talk.isListening

وترجع:


true

أثناء وجود جلسة Speech Recognition نشطة.

كما يوجد:


talk.isNotListening

وهي القيمة العكسية.

يمكن استخدامها بسهولة لتغيير شكل زر الميكروفون:


Icon(
  talk.isListening
      ? Icons.stop
      : Icons.mic,
)

التحقق من توفر Speech Recognition

بعد تنفيذ:


initialize()

يمكن معرفة هل الخدمة متوفرة من خلال:


talk.isAvailable

مثال:


if (!talk.isAvailable) {

  print(
    'Speech Recognition not available',
  );

}

الحصول على آخر نص تم التعرف عليه

توفر المكتبة أيضًا:


talk.lastWords

والتي تحتوي على آخر نص تم التعرف عليه في آخر جلسة.


print(
  talk.lastWords,
);

TalkItResult

عند استخدام:


onResult

يتم إرجاع Object من نوع:


TalkItResult

ويحتوي بشكل أساسي على:

recognizedWords


result.recognizedWords

ويحتوي على النص الذي تم التعرف عليه.

isFinal


result.isFinal

وتحدد هل هذه النتيجة هي النتيجة النهائية لجلسة التعرف أم ما زالت نتيجة جزئية.

التعامل مع حالة Speech Recognition

يمكن متابعة تغير حالة الخدمة من خلال:


onStatus

أثناء التهيئة:


await talk.initialize(

  onStatus: (status) {

    debugPrint(
      'Status: $status',
    );

  },

);

وهذا مفيد أثناء تطوير التطبيق ومعرفة حالة الـ Speech Recognizer.

التعامل مع الأخطاء

يمكن أيضًا التقاط الأخطاء باستخدام:


onError

مثال:


await talk.initialize(

  onError: (error) {

    debugPrint(
      'Speech Error: $error',
    );

  },

);

ومن الأفضل دائمًا عرض رسالة واضحة للمستخدم إذا لم تكن خدمة Speech Recognition متوفرة أو رفض المستخدم صلاحية الميكروفون.

هل talk_it تحتاج إلى الإنترنت؟

مكتبة talk_it نفسها لا ترسل التسجيلات إلى Cloud API خاص بها ولا تعتمد على SDK خارجي لخدمة Speech-to-Text.

هي تستخدم Speech Recognition الموجود على Android وiOS.

لكن القدرة الفعلية على العمل بدون اتصال بالإنترنت قد تختلف حسب نظام التشغيل، الجهاز، اللغة، خدمة التعرف الصوتي المثبتة، وحزم اللغات المتاحة على الجهاز.

لذلك من الأفضل اختبار التطبيق على الأجهزة واللغات التي يستهدفها مشروعك، خصوصًا إذا كان العمل بدون إنترنت شرطًا أساسيًا.

دعم اللغة العربية

واحدة من النقاط التي تركز عليها مكتبة talk_it هي دعم اللغة العربية.

يمكنك مثلًا استخدام:


await talk.initialize(
  localeId: 'ar-EG',
);

ثم بدء الاستماع بنفس اللغة:


await talk.listen(

  localeId: 'ar-EG',

  onResult: (result) {

    print(
      result.recognizedWords,
    );

  },
);

وهذا يجعل المكتبة مفيدة للتطبيقات العربية التي تحتاج إلى إدخال نصوص باستخدام الصوت.

مثال لاستخدام talk_it في البحث الصوتي

من الاستخدامات العملية للمكتبة إضافة البحث الصوتي.


Future<void> voiceSearch() async {

  await talk.listen(

    localeId: 'ar-EG',

    onResult: (result) {

      if (result.isFinal) {

        search(
          result.recognizedWords,
        );

      }

    },
  );
}

وبذلك يمكن للمستخدم الضغط على الميكروفون وقول:


ابحث عن هواتف سامسونج

ويتم تحويل العبارة مباشرة إلى نص واستخدامها في عملية البحث.

استخدام talk_it مع TextField

يمكن أيضًا كتابة الكلام مباشرة داخل TextField.


final TextEditingController
    textController =
        TextEditingController();

ثم:


await talk.listen(

  localeId: 'ar-EG',

  onResult: (result) {

    textController.text =
        result.recognizedWords;

  },
);

وأصبح بإمكان المستخدم الكتابة بالطريقة التقليدية أو استخدام صوته لإدخال النص.

استخدام talk_it في تطبيقات الذكاء الاصطناعي

من الاستخدامات الممتازة للمكتبة دمجها مع تطبيقات AI.

يمكن أن تكون دورة العمل:


User Voice
   ↓
talk_it
   ↓
Speech to Text
   ↓
AI / LLM API
   ↓
AI Response

مثلًا:


await talk.listen(

  localeId: 'ar-EG',

  onResult: (result) async {

    if (!result.isFinal) {
      return;
    }

    final response =
        await askAI(
      result.recognizedWords,
    );

    print(response);

  },
);

وهذا يسمح لك بإنشاء مساعد صوتي داخل تطبيق Flutter بسهولة.

هل تقوم talk_it بتشغيل أصوات؟

لا تقوم المكتبة بتشغيل أصوات خاصة بها قبل أو بعد التسجيل.

إذا أردت تشغيل صوت عند بدء الاستماع أو نهايته فيمكنك استخدام Audio Player منفصل.

وفقًا لتوثيق المكتبة يتم كتم أصوات النظام أثناء جلسة Android، بينما يستخدم iOS إعداد mixWithOthers حتى لا يتم قطع صوت التطبيق الحالي.

أين يمكن استخدام talk_it؟

يمكن استخدام مكتبة talk_it في عدد كبير من التطبيقات، مثل:

  • تطبيقات المحادثة.
  • تطبيقات الذكاء الاصطناعي.
  • المساعدات الصوتية.
  • البحث الصوتي.
  • كتابة الملاحظات بالصوت.
  • كتابة الرسائل بالصوت.
  • إدخال البيانات باستخدام الصوت.
  • تطبيقات اللغة العربية.
  • أوامر التحكم الصوتي.
  • Push-to-Talk interfaces.

talk_it أم speech_to_text؟

إذا كان مشروعك يحتاج إلى API بسيطة وخفيفة تعتمد على Native Speech Recognition، وتهتم بشكل خاص باللغة العربية وPush-to-Talk، فإن talk_it تقدم حلًا مباشرًا لهذه الاستخدامات.

أما اختيار المكتبة النهائية فيجب أن يعتمد على احتياجات المشروع، والمنصات المطلوبة، واللغات، ومستوى التحكم المطلوب في Speech Recognition.

ومن المهم أيضًا ملاحظة أن talk_it حاليًا تدعم Android وiOS، لذلك إذا كان مشروعك يحتاج إلى Web أو Windows أو macOS أو Linux يجب التأكد من توفر حل آخر لهذه المنصات.

الخلاصة

توفر مكتبة talk_it طريقة بسيطة لإضافة Speech to Text في Flutter باستخدام أدوات التعرف الصوتي الأصلية الموجودة في Android وiOS.

المكتبة مناسبة بشكل خاص إذا كنت تريد دعم اللغة العربية، أو إنشاء Push-to-Talk، أو تحويل صوت المستخدم إلى نص وإرساله إلى API أو نموذج ذكاء اصطناعي.

كما أن واجهتها البسيطة التي تعتمد على initialize وlisten وstop وcancel تجعل دمجها داخل تطبيقات Flutter مباشرًا بدون تعقيد كبير.



مكتبة talk_it لتحويل الصوت إلى نص في Flutter


مزيد من المقالات : Fan Cards في Jetpack Compose لإنشاء بطاقات تفاعلية بتصميم احترافي
شاهد أيضًا
مقالات ذات صلة
🚫 مانع الإعلانات مفعل

يجب إيقاف مانع الإعلانات لاستكمال تصفح الموقع