Pengenalan ucapan menggunakan Azure Speech Service
Azure Speech Service adalah API berbasis cloud yang menawarkan fungsionalitas berikut:
- Ucapan ke teks mentranskripsikan file audio atau streaming ke teks.
- Teks ke ucapan mengonversi teks input menjadi ucapan yang disintesis seperti manusia.
- Terjemahan ucapan memungkinkan terjemahan multi-bahasa real-time untuk ucapan ke teks dan ucapan ke ucapan.
- Asisten suara dapat membuat antarmuka percakapan seperti manusia untuk aplikasi.
Artikel ini menjelaskan bagaimana ucapan ke teks diimplementasikan dalam aplikasi sampel Xamarin.Forms menggunakan Azure Speech Service. Cuplikan layar berikut menunjukkan aplikasi sampel di iOS dan Android:
Membuat sumber daya Azure Speech Service
Azure Speech Service adalah bagian dari Azure Cognitive Services, yang menyediakan API berbasis cloud untuk tugas seperti pengenalan gambar, pengenalan dan terjemahan ucapan, dan pencarian Bing. Untuk informasi selengkapnya, lihat Apa itu Azure Cognitive Services?.
Proyek sampel memerlukan sumber daya Azure Cognitive Services untuk dibuat di portal Azure Anda. Sumber daya Cognitive Services dapat dibuat untuk satu layanan, seperti Layanan Ucapan, atau sebagai sumber daya multi-layanan. Langkah-langkah untuk membuat sumber daya Layanan Ucapan adalah sebagai berikut:
- Masuk ke portal Azure Anda.
- Buat sumber daya multi-layanan atau layanan tunggal.
- Dapatkan kunci API dan informasi wilayah untuk sumber daya Anda.
- Perbarui sampel file Constants.cs .
Untuk panduan langkah demi langkah untuk membuat sumber daya, lihat Membuat sumber daya Cognitive Services.
Catatan
Jika Anda tidak memiliki langganan Azure, buatlah akun gratis sebelum Anda memulai. Setelah Anda memiliki akun, sumber daya layanan tunggal dapat dibuat di tingkat gratis untuk mencoba layanan.
Mengonfigurasi aplikasi Anda dengan Layanan Ucapan
Setelah membuat sumber daya Cognitive Services, file Constants.cs dapat diperbarui dengan wilayah dan kunci API dari sumber daya Azure Anda:
public static class Constants
{
public static string CognitiveServicesApiKey = "YOUR_KEY_GOES_HERE";
public static string CognitiveServicesRegion = "westus";
}
Menginstal paket NuGet Speech Service
Aplikasi sampel menggunakan paket NuGet Microsoft.CognitiveServices.Speech untuk menyambungkan ke Azure Speech Service. Instal paket NuGet ini di proyek bersama dan setiap proyek platform.
Membuat antarmuka IMicrophoneService
Setiap platform memerlukan izin untuk mengakses mikrofon. Proyek sampel menyediakan IMicrophoneService
antarmuka dalam proyek bersama, dan menggunakan Xamarin.FormsDependencyService
untuk mendapatkan implementasi platform antarmuka.
public interface IMicrophoneService
{
Task<bool> GetPermissionAsync();
void OnRequestPermissionResult(bool isGranted);
}
Membuat tata letak halaman
Proyek sampel menentukan tata letak halaman dasar dalam file MainPage.xaml . Elemen tata letak kunci adalah Button
yang memulai proses transkripsi, untuk Label
berisi teks yang ditranskripsikan, dan untuk ActivityIndicator
ditampilkan saat transkripsi sedang berlangsung:
<ContentPage ...>
<StackLayout>
<Frame ...>
<ScrollView x:Name="scroll"
...>
<Label x:Name="transcribedText"
... />
</ScrollView>
</Frame>
<ActivityIndicator x:Name="transcribingIndicator"
IsRunning="False" />
<Button x:Name="transcribeButton"
...
Clicked="TranscribeClicked"/>
</StackLayout>
</ContentPage>
Menerapkan Layanan Ucapan
File MainPage.xaml.cs code-behind berisi semua logika untuk mengirim audio dan menerima teks yang ditranskripsikan dari Azure Speech Service.
MainPage
Konstruktor mendapatkan instans IMicrophoneService
antarmuka dari DependencyService
:
public partial class MainPage : ContentPage
{
SpeechRecognizer recognizer;
IMicrophoneService micService;
bool isTranscribing = false;
public MainPage()
{
InitializeComponent();
micService = DependencyService.Resolve<IMicrophoneService>();
}
// ...
}
Metode TranscribeClicked
ini dipanggil ketika transcribeButton
instans diketuk:
async void TranscribeClicked(object sender, EventArgs e)
{
bool isMicEnabled = await micService.GetPermissionAsync();
// EARLY OUT: make sure mic is accessible
if (!isMicEnabled)
{
UpdateTranscription("Please grant access to the microphone!");
return;
}
// initialize speech recognizer
if (recognizer == null)
{
var config = SpeechConfig.FromSubscription(Constants.CognitiveServicesApiKey, Constants.CognitiveServicesRegion);
recognizer = new SpeechRecognizer(config);
recognizer.Recognized += (obj, args) =>
{
UpdateTranscription(args.Result.Text);
};
}
// if already transcribing, stop speech recognizer
if (isTranscribing)
{
try
{
await recognizer.StopContinuousRecognitionAsync();
}
catch(Exception ex)
{
UpdateTranscription(ex.Message);
}
isTranscribing = false;
}
// if not transcribing, start speech recognizer
else
{
Device.BeginInvokeOnMainThread(() =>
{
InsertDateTimeRecord();
});
try
{
await recognizer.StartContinuousRecognitionAsync();
}
catch(Exception ex)
{
UpdateTranscription(ex.Message);
}
isTranscribing = true;
}
UpdateDisplayState();
}
Metode TranscribeClicked
melakukan hal berikut:
- Memeriksa apakah aplikasi memiliki akses ke mikrofon dan keluar lebih awal jika tidak.
- Membuat instans
SpeechRecognizer
kelas jika belum ada. - Menghentikan transkripsi berkelanjutan jika sedang berlangsung.
- Menyisipkan tanda waktu dan memulai transkripsi berkelanjutan jika tidak sedang berlangsung.
- Memberi tahu aplikasi untuk memperbarui penampilannya berdasarkan status aplikasi baru.
Sisa metode kelas adalah pembantu MainPage
untuk menampilkan status aplikasi:
void UpdateTranscription(string newText)
{
Device.BeginInvokeOnMainThread(() =>
{
if (!string.IsNullOrWhiteSpace(newText))
{
transcribedText.Text += $"{newText}\n";
}
});
}
void InsertDateTimeRecord()
{
var msg = $"=================\n{DateTime.Now.ToString()}\n=================";
UpdateTranscription(msg);
}
void UpdateDisplayState()
{
Device.BeginInvokeOnMainThread(() =>
{
if (isTranscribing)
{
transcribeButton.Text = "Stop";
transcribeButton.BackgroundColor = Color.Red;
transcribingIndicator.IsRunning = true;
}
else
{
transcribeButton.Text = "Transcribe";
transcribeButton.BackgroundColor = Color.Green;
transcribingIndicator.IsRunning = false;
}
});
}
Metode UpdateTranscription
menulis yang disediakan newText
string
ke Label
elemen bernama transcribedText
. Ini memaksa pembaruan ini terjadi pada utas UI sehingga dapat dipanggil dari konteks apa pun tanpa menyebabkan pengecualian. menulis InsertDateTimeRecord
tanggal dan waktu saat ini ke transcribedText
instans untuk menandai awal transkripsi baru. Akhirnya, metode memperbarui UpdateDisplayState
Button
elemen dan ActivityIndicator
untuk mencerminkan apakah transkripsi sedang berlangsung atau tidak.
Membuat layanan mikrofon platform
Aplikasi harus memiliki akses mikrofon untuk mengumpulkan data ucapan. Antarmuka IMicrophoneService
harus diimplementasikan dan didaftarkan dengan DependencyService
pada setiap platform agar aplikasi berfungsi.
Android
Proyek sampel mendefinisikan implementasi untuk Android yang IMicrophoneService
disebut AndroidMicrophoneService
:
[assembly: Dependency(typeof(AndroidMicrophoneService))]
namespace CognitiveSpeechService.Droid.Services
{
public class AndroidMicrophoneService : IMicrophoneService
{
public const int RecordAudioPermissionCode = 1;
private TaskCompletionSource<bool> tcsPermissions;
string[] permissions = new string[] { Manifest.Permission.RecordAudio };
public Task<bool> GetPermissionAsync()
{
tcsPermissions = new TaskCompletionSource<bool>();
if ((int)Build.VERSION.SdkInt < 23)
{
tcsPermissions.TrySetResult(true);
}
else
{
var currentActivity = MainActivity.Instance;
if (ActivityCompat.CheckSelfPermission(currentActivity, Manifest.Permission.RecordAudio) != (int)Permission.Granted)
{
RequestMicPermissions();
}
else
{
tcsPermissions.TrySetResult(true);
}
}
return tcsPermissions.Task;
}
public void OnRequestPermissionResult(bool isGranted)
{
tcsPermissions.TrySetResult(isGranted);
}
void RequestMicPermissions()
{
if (ActivityCompat.ShouldShowRequestPermissionRationale(MainActivity.Instance, Manifest.Permission.RecordAudio))
{
Snackbar.Make(MainActivity.Instance.FindViewById(Android.Resource.Id.Content),
"Microphone permissions are required for speech transcription!",
Snackbar.LengthIndefinite)
.SetAction("Ok", v =>
{
((Activity)MainActivity.Instance).RequestPermissions(permissions, RecordAudioPermissionCode);
})
.Show();
}
else
{
ActivityCompat.RequestPermissions((Activity)MainActivity.Instance, permissions, RecordAudioPermissionCode);
}
}
}
}
memiliki AndroidMicrophoneService
fitur berikut:
- Atribut
Dependency
mendaftarkan kelas denganDependencyService
. - Metode ini
GetPermissionAsync
memeriksa apakah izin diperlukan berdasarkan versi Android SDK, dan memanggilRequestMicPermissions
jika izin belum diberikan. - Metode ini
RequestMicPermissions
menggunakanSnackbar
kelas untuk meminta izin dari pengguna jika diperlukan alasan, jika tidak, metode ini secara langsung meminta izin perekaman audio. - Metode
OnRequestPermissionResult
ini dipanggil dengan hasilbool
setelah pengguna merespons permintaan izin.
Kelas MainActivity
disesuaikan untuk memperbarui AndroidMicrophoneService
instans ketika permintaan izin selesai:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
IMicrophoneService micService;
internal static MainActivity Instance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
Instance = this;
// ...
micService = DependencyService.Resolve<IMicrophoneService>();
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
// ...
switch(requestCode)
{
case AndroidMicrophoneService.RecordAudioPermissionCode:
if (grantResults[0] == Permission.Granted)
{
micService.OnRequestPermissionResult(true);
}
else
{
micService.OnRequestPermissionResult(false);
}
break;
}
}
}
Kelas MainActivity
menentukan referensi statis yang disebut Instance
, yang diperlukan oleh AndroidMicrophoneService
objek saat meminta izin. Ini mengambil alih OnRequestPermissionsResult
metode untuk memperbarui AndroidMicrophoneService
objek ketika permintaan izin disetujui atau ditolak oleh pengguna.
Terakhir, aplikasi Android harus menyertakan izin untuk merekam audio dalam file AndroidManifest.xml :
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>
iOS
Proyek sampel mendefinisikan implementasi untuk iOS yang IMicrophoneService
disebut iOSMicrophoneService
:
[assembly: Dependency(typeof(iOSMicrophoneService))]
namespace CognitiveSpeechService.iOS.Services
{
public class iOSMicrophoneService : IMicrophoneService
{
TaskCompletionSource<bool> tcsPermissions;
public Task<bool> GetPermissionAsync()
{
tcsPermissions = new TaskCompletionSource<bool>();
RequestMicPermission();
return tcsPermissions.Task;
}
public void OnRequestPermissionResult(bool isGranted)
{
tcsPermissions.TrySetResult(isGranted);
}
void RequestMicPermission()
{
var session = AVAudioSession.SharedInstance();
session.RequestRecordPermission((granted) =>
{
tcsPermissions.TrySetResult(granted);
});
}
}
}
memiliki iOSMicrophoneService
fitur berikut:
- Atribut
Dependency
mendaftarkan kelas denganDependencyService
. - Metode ini
GetPermissionAsync
memanggilRequestMicPermissions
untuk meminta izin dari pengguna perangkat. - Metode ini
RequestMicPermissions
menggunakan instans bersamaAVAudioSession
untuk meminta izin perekaman. - Metode memperbarui
OnRequestPermissionResult
TaskCompletionSource
instans dengan nilai yang disediakanbool
.
Terakhir, info.plist aplikasi iOS harus menyertakan pesan yang memberi tahu pengguna mengapa aplikasi meminta akses ke mikrofon. Edit file Info.plist untuk menyertakan tag berikut dalam <dict>
elemen :
<plist>
<dict>
...
<key>NSMicrophoneUsageDescription</key>
<string>Voice transcription requires microphone access</string>
</dict>
</plist>
UWP
Proyek sampel mendefinisikan IMicrophoneService
implementasi untuk UWP yang disebut UWPMicrophoneService
:
[assembly: Dependency(typeof(UWPMicrophoneService))]
namespace CognitiveSpeechService.UWP.Services
{
public class UWPMicrophoneService : IMicrophoneService
{
public async Task<bool> GetPermissionAsync()
{
bool isMicAvailable = true;
try
{
var mediaCapture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings();
settings.StreamingCaptureMode = StreamingCaptureMode.Audio;
await mediaCapture.InitializeAsync(settings);
}
catch(Exception ex)
{
isMicAvailable = false;
}
if(!isMicAvailable)
{
await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-microphone"));
}
return isMicAvailable;
}
public void OnRequestPermissionResult(bool isGranted)
{
// intentionally does nothing
}
}
}
memiliki UWPMicrophoneService
fitur berikut:
- Atribut
Dependency
mendaftarkan kelas denganDependencyService
. - Metode ini
GetPermissionAsync
mencoba menginisialisasiMediaCapture
instans. Jika gagal, ia meluncurkan permintaan pengguna untuk mengaktifkan mikrofon. - Metode ini
OnRequestPermissionResult
ada untuk memenuhi antarmuka tetapi tidak diperlukan untuk implementasi UWP.
Terakhir, UWP Package.appxmanifest harus menentukan bahwa aplikasi menggunakan mikrofon. Klik dua kali file Package.appxmanifest dan pilih opsi Mikrofon pada tab Kemampuan di Visual Studio 2019:
Uji aplikasi
Jalankan aplikasi dan klik tombol Mentranskripsikan . Aplikasi harus meminta akses mikrofon dan memulai proses transkripsi. Akan ActivityIndicator
menganimasikan, menunjukkan bahwa transkripsi aktif. Saat Anda berbicara, aplikasi akan mengalirkan data audio ke sumber daya Azure Speech Services, yang akan merespons dengan teks yang ditranskripsikan. Teks yang ditranskripsikan akan muncul di elemen seperti Label
yang diterima.
Catatan
Emulator Android gagal memuat dan menginisialisasi pustaka Layanan Ucapan. Pengujian pada perangkat fisik direkomendasikan untuk platform Android.