Rozpoznávání řeči pomocí služby Azure Speech
Azure Speech Service je cloudové rozhraní API, které nabízí následující funkce:
- Převod řeči na text přepisuje zvukové soubory nebo datové proudy na text.
- Převod textu na řeč převede vstupní text na syntetizovaný řeč podobný člověku.
- Překlad řeči umožňuje překlad řeči v reálném čase, více jazyků pro převod řeči na text i řeč na řeč.
- Hlasoví asistenti můžou pro aplikace vytvářet rozhraní konverzace podobné člověku.
Tento článek vysvětluje, jak se v ukázkové Xamarin.Forms aplikaci implementuje převod řeči na text pomocí služby Azure Speech. Následující snímky obrazovky ukazují ukázkovou aplikaci v iOSu a Androidu:
Vytvoření prostředku služby Azure Speech
Služba Azure Speech je součástí služeb Azure Cognitive Services, která poskytuje cloudová rozhraní API pro úlohy, jako je rozpoznávání obrázků, rozpoznávání řeči a překlad a vyhledávání Bingu. Další informace najdete v tématu Co jsou služby Azure Cognitive Services?
Ukázkový projekt vyžaduje vytvoření prostředku Azure Cognitive Services na webu Azure Portal. Prostředek služeb Cognitive Services je možné vytvořit pro jednu službu, jako je služba Speech, nebo jako prostředek s více službami. Postup vytvoření prostředku služby Speech je následující:
- Přihlaste se k webu Azure Portal.
- Vytvořte prostředek s více službami nebo jednou službou.
- Získejte informace o klíči rozhraní API a oblasti pro váš prostředek.
- Aktualizujte ukázkový soubor Constants.cs .
Podrobný průvodce vytvořením prostředku najdete v tématu Vytvoření prostředku služeb Cognitive Services.
Poznámka:
Pokud ještě nemáte předplatné Azure, vytvořte si bezplatný účet před tím, než začnete. Jakmile máte účet, můžete vytvořit prostředek jedné služby na úrovni Free a vyzkoušet službu.
Konfigurace aplikace pomocí služby Speech
Po vytvoření prostředku služeb Cognitive Services je možné soubor Constants.cs aktualizovat pomocí oblasti a klíče rozhraní API z vašeho prostředku Azure:
public static class Constants
{
public static string CognitiveServicesApiKey = "YOUR_KEY_GOES_HERE";
public static string CognitiveServicesRegion = "westus";
}
Instalace balíčku služby NuGet Speech
Ukázková aplikace používá balíček NuGet Microsoft.CognitiveServices.Speech k připojení ke službě Azure Speech. Nainstalujte tento balíček NuGet do sdíleného projektu a každého projektu platformy.
Vytvoření rozhraní IMicrophoneService
Každá platforma vyžaduje oprávnění pro přístup k mikrofonu. Ukázkový projekt poskytuje rozhraní ve sdíleném IMicrophoneService
projektu a používá Xamarin.FormsDependencyService
k získání implementací platformy rozhraní.
public interface IMicrophoneService
{
Task<bool> GetPermissionAsync();
void OnRequestPermissionResult(bool isGranted);
}
Vytvoření rozložení stránky
Ukázkový projekt definuje základní rozložení stránky v souboru MainPage.xaml . Klíčové prvky rozložení jsou prvky Button
, které spustí proces přepisu, Label
který bude obsahovat přepisovaný text a který ActivityIndicator
se má zobrazit, když probíhá přepis:
<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>
Implementace služby Speech
Soubor MainPage.xaml.cs kódu obsahuje veškerou logiku pro odesílání zvuku a přijímání přepisovaného textu ze služby Azure Speech.
Konstruktor MainPage
získá instanci IMicrophoneService
rozhraní z DependencyService
:
public partial class MainPage : ContentPage
{
SpeechRecognizer recognizer;
IMicrophoneService micService;
bool isTranscribing = false;
public MainPage()
{
InitializeComponent();
micService = DependencyService.Resolve<IMicrophoneService>();
}
// ...
}
Metoda TranscribeClicked
se volá při klepnutí instance transcribeButton
:
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();
}
Metoda TranscribeClicked
provede následující:
- Zkontroluje, jestli má aplikace přístup k mikrofonu, a ukončí se včas, pokud ne.
- Vytvoří instanci
SpeechRecognizer
třídy, pokud ještě neexistuje. - Zastaví průběžný přepis, pokud právě probíhá.
- Vloží časové razítko a spustí průběžný přepis, pokud neprobíhá.
- Upozorní aplikaci, aby aktualizovala svůj vzhled na základě nového stavu aplikace.
Zbývající část MainPage
metod třídy jsou pomocné rutiny pro zobrazení stavu aplikace:
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;
}
});
}
Metoda UpdateTranscription
zapíše poskytnuté newText
string
do elementu Label
s názvem transcribedText
. Tato aktualizace vynutí, aby se tato aktualizace stala ve vlákně uživatelského rozhraní, aby ji bylo možné volat z libovolného kontextu, aniž by to způsobilo výjimky. Zapíše InsertDateTimeRecord
aktuální datum a čas do transcribedText
instance a označí začátek nového přepisu. Nakonec metoda aktualizuje Button
a ActivityIndicator
prvky tak, aby odrážely, UpdateDisplayState
zda probíhá přepis.
Vytváření služeb mikrofonu platformy
Aplikace musí mít přístup k mikrofonu pro shromažďování dat řeči. Rozhraní IMicrophoneService
musí být implementováno a registrováno u DependencyService
každé platformy, aby aplikace fungovala.
Android
Ukázkový projekt definuje implementaci IMicrophoneService
pro Android s názvem 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);
}
}
}
}
Obsahuje AndroidMicrophoneService
následující funkce:
- Atribut
Dependency
registruje třídu pomocíDependencyService
. - Metoda
GetPermissionAsync
zkontroluje, jestli jsou oprávnění požadovaná na základě verze sady Android SDK, a voláníRequestMicPermissions
, pokud oprávnění ještě nebyla udělena. - Metoda
RequestMicPermissions
používáSnackbar
třídu k vyžádání oprávnění od uživatele, pokud je požadován odůvodnění, jinak přímo požaduje oprávnění zvukového záznamu. - Metoda
OnRequestPermissionResult
se volá sbool
výsledkem, jakmile uživatel odpoví na žádost o oprávnění.
Třída MainActivity
je přizpůsobená tak, aby po dokončení žádostí o oprávnění aktualizovala AndroidMicrophoneService
instanci:
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;
}
}
}
Třída MainActivity
definuje statický odkaz, Instance
který je vyžadován objektem AndroidMicrophoneService
při vyžádání oprávnění. Přepíše metodu OnRequestPermissionsResult
aktualizace objektu AndroidMicrophoneService
, pokud je žádost o oprávnění schválena nebo odepřena uživatelem.
Aplikace pro Android musí nakonec obsahovat oprávnění k nahrávání zvuku v souboru AndroidManifest.xml :
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>
iOS
Ukázkový projekt definuje implementaci IMicrophoneService
pro iOS s názvem 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);
});
}
}
}
Obsahuje iOSMicrophoneService
následující funkce:
- Atribut
Dependency
registruje třídu pomocíDependencyService
. - Metoda
GetPermissionAsync
voláRequestMicPermissions
žádosti o oprávnění od uživatele zařízení. - Metoda
RequestMicPermissions
používá sdílenouAVAudioSession
instanci k vyžádání oprávnění k záznamu. - Metoda
OnRequestPermissionResult
aktualizujeTaskCompletionSource
instanci zadanoubool
hodnotou.
Nakonec musí aplikace pro iOS Info.plist obsahovat zprávu s informacemi o tom, proč aplikace žádá o přístup k mikrofonu. Upravte soubor Info.plist tak, aby zahrnoval následující značky v elementu <dict>
:
<plist>
<dict>
...
<key>NSMicrophoneUsageDescription</key>
<string>Voice transcription requires microphone access</string>
</dict>
</plist>
UWP
Ukázkový projekt definuje implementaci IMicrophoneService
pro UPW s názvem 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
}
}
}
Obsahuje UWPMicrophoneService
následující funkce:
- Atribut
Dependency
registruje třídu pomocíDependencyService
. - Metoda
GetPermissionAsync
se pokusí inicializovatMediaCapture
instanci. Pokud se to nezdaří, spustí se žádost uživatele o povolení mikrofonu. - Metoda
OnRequestPermissionResult
existuje pro splnění rozhraní, ale není vyžadována pro implementaci UPW.
Nakonec musí upW Package.appxmanifest určit, že aplikace používá mikrofon. Poklikejte na soubor Package.appxmanifest a vyberte možnost Mikrofon na kartě Schopnosti v sadě Visual Studio 2019:
Testování aplikace
Spusťte aplikaci a klikněte na tlačítko Přepis . Aplikace by měla požádat o přístup k mikrofonu a zahájit proces přepisu. Animace ActivityIndicator
bude zobrazovat, že přepis je aktivní. Při mluvení bude aplikace streamovat zvuková data do prostředku azure Speech Services, který bude reagovat přepisovaným textem. Přepsaný text se zobrazí v elementu Label
při jeho přijetí.
Poznámka:
Emulátory Androidu se nepodaří načíst a inicializovat knihovny služby Speech. Pro platformu Android se doporučuje testování na fyzickém zařízení.