Rozpoznawanie mowy przy użyciu usługi Azure Speech Service
Azure Speech Service to oparty na chmurze interfejs API, który oferuje następujące funkcje:
- Zamiana mowy na tekst transkrypuje pliki audio lub strumienie do tekstu.
- Zamiana tekstu na mowę konwertuje tekst wejściowy na syntetyzowany mowę przypominającą człowieka.
- Tłumaczenie mowy umożliwia tłumaczenie w czasie rzeczywistym w wielu językach zarówno dla zamiany mowy na tekst, jak i zamiany mowy na mowę.
- Asystentzy głosowi mogą tworzyć interfejsy konwersacji przypominające człowieka dla aplikacji.
W tym artykule wyjaśniono, jak zaimplementowano mowę do tekstu w przykładowej Xamarin.Forms aplikacji przy użyciu usługi Azure Speech Service. Na poniższych zrzutach ekranu przedstawiono przykładową aplikację w systemach iOS i Android:
Tworzenie zasobu usługi Azure Speech Service
Usługa Azure Speech Service jest częścią usług Azure Cognitive Services, która udostępnia oparte na chmurze interfejsy API dla zadań takich jak rozpoznawanie obrazów, rozpoznawanie mowy i tłumaczenie oraz wyszukiwanie Bing. Aby uzyskać więcej informacji, zobacz Co to są usługi Azure Cognitive Services?.
Przykładowy projekt wymaga utworzenia zasobu usług Azure Cognitive Services w witrynie Azure Portal. Zasób usług Cognitive Services można utworzyć dla jednej usługi, takiej jak usługa Mowa, lub jako zasób z wieloma usługami. Kroki tworzenia zasobu usługi Mowa są następujące:
- Zaloguj się do witryny Azure Portal.
- Utwórz zasób z wieloma usługami lub pojedynczą usługą.
- Uzyskaj informacje o kluczu interfejsu API i regionie zasobu.
- Zaktualizuj przykładowy plik Constants.cs .
Aby zapoznać się z przewodnikiem krok po kroku dotyczącym tworzenia zasobu, zobacz Tworzenie zasobu usług Cognitive Services.
Uwaga
Jeśli nie masz subskrypcji platformy Azure, przed rozpoczęciem utwórz bezpłatne konto. Po utworzeniu konta można utworzyć zasób z jedną usługą w warstwie Bezpłatna, aby wypróbować usługę.
Konfigurowanie aplikacji za pomocą usługi Mowa
Po utworzeniu zasobu usług Cognitive Services plik Constants.cs można zaktualizować przy użyciu regionu i klucza interfejsu API z zasobu platformy Azure:
public static class Constants
{
public static string CognitiveServicesApiKey = "YOUR_KEY_GOES_HERE";
public static string CognitiveServicesRegion = "westus";
}
Instalowanie pakietu usługi Rozpoznawanie mowy NuGet
Przykładowa aplikacja używa pakietu NuGet Microsoft.CognitiveServices.Speech w celu nawiązania połączenia z usługą Azure Speech Service. Zainstaluj ten pakiet NuGet w udostępnionym projekcie i każdym projekcie platformy.
Tworzenie interfejsu IMicrophoneService
Każda platforma wymaga uprawnień dostępu do mikrofonu. Przykładowy projekt udostępnia IMicrophoneService
interfejs w udostępnionym projekcie i używa go Xamarin.FormsDependencyService
do uzyskiwania implementacji platformy interfejsu.
public interface IMicrophoneService
{
Task<bool> GetPermissionAsync();
void OnRequestPermissionResult(bool isGranted);
}
Tworzenie układu strony
Przykładowy projekt definiuje podstawowy układ strony w pliku MainPage.xaml . Kluczowe elementy układu to element Button
, który rozpoczyna proces transkrypcji, element do Label
zawierania transkrypcji tekstu i do ActivityIndicator
pokazania, gdy transkrypcja jest w toku:
<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>
Implementowanie usługi Mowa
Plik MainPage.xaml.cs zawierający całą logikę wysyłania dźwięku i odbierania transkrypcji tekstu z usługi Azure Speech Service.
Konstruktor MainPage
pobiera wystąpienie interfejsu IMicrophoneService
z elementu DependencyService
:
public partial class MainPage : ContentPage
{
SpeechRecognizer recognizer;
IMicrophoneService micService;
bool isTranscribing = false;
public MainPage()
{
InitializeComponent();
micService = DependencyService.Resolve<IMicrophoneService>();
}
// ...
}
Metoda jest wywoływana TranscribeClicked
po naciśnięciu transcribeButton
wystąpienia:
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
wykonuje następujące czynności:
- Sprawdza, czy aplikacja ma dostęp do mikrofonu i kończy się wcześnie, jeśli nie.
- Tworzy wystąpienie
SpeechRecognizer
klasy, jeśli jeszcze nie istnieje. - Zatrzymuje ciągłą transkrypcję, jeśli jest w toku.
- Wstawia znacznik czasu i uruchamia ciągłą transkrypcję, jeśli nie jest w toku.
- Powiadamia aplikację o zaktualizowaniu wyglądu na podstawie stanu nowej aplikacji.
Pozostała część MainPage
metod klasy to pomocnicy wyświetlania stanu aplikacji:
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
zapisuje podany newText
string
element w elemecie Label
o nazwie transcribedText
. Wymusza to, aby ta aktualizacja miała miejsce w wątku interfejsu użytkownika, dzięki czemu może być wywoływana z dowolnego kontekstu bez powodowania wyjątków. Zapisuje InsertDateTimeRecord
bieżącą datę i godzinę transcribedText
wystąpienia, aby oznaczyć początek nowej transkrypcji. Na koniec metoda aktualizuje Button
elementy i ActivityIndicator
w celu odzwierciedlenia, UpdateDisplayState
czy transkrypcja jest w toku.
Tworzenie usług mikrofonu platformy
Aplikacja musi mieć dostęp do mikrofonu w celu zbierania danych mowy. Interfejs IMicrophoneService
należy zaimplementować i zarejestrować DependencyService
na każdej platformie, aby aplikacja działała.
Android
Przykładowy projekt definiuje implementację IMicrophoneService
dla systemu Android o nazwie 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);
}
}
}
}
Ma AndroidMicrophoneService
następujące funkcje:
- Atrybut
Dependency
rejestruje klasę za pomocą klasyDependencyService
. - Metoda
GetPermissionAsync
sprawdza, czy uprawnienia są wymagane w oparciu o wersję zestawu Android SDK, i wywołujeRequestMicPermissions
metodę , jeśli nie udzielono jeszcze uprawnień. - Metoda
RequestMicPermissions
używaSnackbar
klasy do żądania uprawnień od użytkownika, jeśli wymagane jest uzasadnienie, w przeciwnym razie bezpośrednio żąda uprawnień do nagrywania dźwięku. - Metoda jest wywoływana
OnRequestPermissionResult
zbool
wynikiem, gdy użytkownik odpowiedział na żądanie uprawnień.
Klasa MainActivity
jest dostosowywana do aktualizowania wystąpienia po zakończeniu AndroidMicrophoneService
żądań uprawnień:
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;
}
}
}
Klasa MainActivity
definiuje statyczne odwołanie o nazwie Instance
, które jest wymagane przez AndroidMicrophoneService
obiekt podczas żądania uprawnień. Zastępuje metodę OnRequestPermissionsResult
w celu zaktualizowania AndroidMicrophoneService
obiektu, gdy żądanie uprawnień zostanie zatwierdzone lub odrzucone przez użytkownika.
Na koniec aplikacja systemu Android musi zawierać uprawnienia do rejestrowania dźwięku w pliku AndroidManifest.xml :
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>
iOS
Przykładowy projekt definiuje implementację IMicrophoneService
dla systemu iOS o nazwie 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);
});
}
}
}
Ma iOSMicrophoneService
następujące funkcje:
- Atrybut
Dependency
rejestruje klasę za pomocą klasyDependencyService
. - Metoda
GetPermissionAsync
wywołujeRequestMicPermissions
żądanie uprawnień od użytkownika urządzenia. - Metoda
RequestMicPermissions
używa udostępnionegoAVAudioSession
wystąpienia do żądania uprawnień rejestrowania. - Metoda
OnRequestPermissionResult
aktualizujeTaskCompletionSource
wystąpienie przy użyciu podanejbool
wartości.
Na koniec aplikacja systemu iOS Info.plist musi zawierać komunikat informujący użytkownika, dlaczego aplikacja żąda dostępu do mikrofonu. Edytuj plik Info.plist, aby uwzględnić następujące tagi w elemecie <dict>
:
<plist>
<dict>
...
<key>NSMicrophoneUsageDescription</key>
<string>Voice transcription requires microphone access</string>
</dict>
</plist>
Platforma UWP
Przykładowy projekt definiuje implementację IMicrophoneService
platformy UWP o nazwie 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
}
}
}
Ma UWPMicrophoneService
następujące funkcje:
- Atrybut
Dependency
rejestruje klasę za pomocą klasyDependencyService
. - Metoda
GetPermissionAsync
próbuje zainicjowaćMediaCapture
wystąpienie. Jeśli to się nie powiedzie, uruchomi żądanie użytkownika, aby włączyć mikrofon. - Metoda
OnRequestPermissionResult
istnieje, aby spełnić wymagania interfejsu, ale nie jest wymagana do implementacji platformy UWP.
Na koniec pakiet.appxmanifest platformy UWP musi określić, że aplikacja używa mikrofonu. Kliknij dwukrotnie plik Package.appxmanifest i wybierz opcję Mikrofon na karcie Możliwości w programie Visual Studio 2019:
Testowanie aplikacji
Uruchom aplikację i kliknij przycisk Transkrypcja . Aplikacja powinna zażądać dostępu do mikrofonu i rozpocząć proces transkrypcji. Animuje ActivityIndicator
, pokazując, że transkrypcja jest aktywna. Jak mówisz, aplikacja będzie przesyłać strumieniowo dane audio do zasobu usług Azure Speech Services, który odpowie za pomocą transkrypcji tekstu. Transkrypowany tekst pojawi się w elemecie w miarę Label
odbierania.
Uwaga
Nie można załadować emulatorów systemu Android i zainicjować bibliotek usługi Mowa. Testowanie na urządzeniu fizycznym jest zalecane dla platformy Android.