Google Cloud Speech-to-Text sobre gRPC en Delphi

· Componentes

Speech-to-Text convierte audio hablado en texto escrito. Google Cloud lo expone como un servicio gRPC, y sgcWebSockets Enterprise incluye un cliente de Speech tipado construido sobre el genérico TsgcGRPCClient, así que puedes transcribir audio directamente desde Delphi y C++Builder. Ensamblas una petición de reconocimiento con unas pocas propiedades, la envías por gRPC y lees la transcripción de vuelta, sin necesidad de runtime externo ni protobufs escritos a mano.

Cómo funciona

gRPC son mensajes de Protocol Buffers enmarcados sobre HTTP/2, así que el cliente de Speech viaja sobre el mismo transporte que el resto de la librería. Un TsgcHTTP2Client abre una conexión TLS a speech.googleapis.com:443, un TsgcGRPCClient gestiona el enmarcado gRPC y los trailers por encima, y los mensajes tipados de Speech en sgcGRPC_Google_Speech serializan y analizan la petición y la respuesta por ti.

Las APIs de Google Cloud están autenticadas. Te autenticas con una cuenta de servicio, intercambiando su clave JSON por un bearer token de corta duración, y envías ese token como metadata gRPC en cada llamada. La petición en sí es un RecognitionConfig (idioma, codificación, frecuencia de muestreo) más el audio, ya sean bytes en línea o una URI de Cloud Storage. El servicio responde con uno o más resultados, cada uno con alternativas de transcripción ordenadas con una puntuación de confianza.

Autenticación con una cuenta de servicio

El cliente de Google Cloud convierte una clave JSON de cuenta de servicio en un bearer token. Carga la clave, establece las propiedades JWT, y vincula la audiencia al endpoint de Speech para que el token autofirmado sea aceptado. Una vez que llega el token, añádelo al DefaultMetadata del cliente gRPC como una cabecera authorization, que entonces viaja en cada llamada.

uses
  sgcHTTP2_Client, sgcGRPC_Client, sgcGRPC_Types,
  sgcHTTP_Google_Cloud, sgcGRPC_Google_Speech;

// service-account JWT authentication
Cloud.GoogleCloudOptions.Authentication := gcaJWT;
Cloud.GoogleCloudOptions.JWT.ClientEmail := ClientEmail;
Cloud.GoogleCloudOptions.JWT.PrivateKeyId := PrivateKeyId;
Cloud.GoogleCloudOptions.JWT.PrivateKey.Text := PrivateKey;
Cloud.GoogleCloudOptions.JWT.ProjectId := ProjectId;
// self-signed service-account JWT is audience-bound to the Speech endpoint
Cloud.GoogleCloudOptions.JWT.API_Endpoint := 'https://speech.googleapis.com/';

// once the token is acquired, send it on every gRPC call
GRPC.DefaultMetadata.Clear;
GRPC.DefaultMetadata.Add('authorization', 'Bearer ' + Token);

Conectar el cliente gRPC

El canal es una conexión HTTP/2. Apunta un TsgcHTTP2Client al host de Speech con TLS habilitado, asígnalo a la propiedad Client del componente gRPC, y selecciona el content type del protocolo. El servicio de Speech habla Protocol Buffers, así que usa grpcProto sin compresión.

HTTP2 := TsgcHTTP2Client.Create(nil);
HTTP2.Host := 'speech.googleapis.com';
HTTP2.Port := 443;
HTTP2.TLS  := True;

GRPC := TsgcGRPCClient.Create(nil);
GRPC.Client := HTTP2;
GRPC.ChannelOptions.ContentType := grpcProto;
GRPC.ChannelOptions.Compression := grpcNoCompression;

HTTP2.Active := True;

Reconocer audio y leer la transcripción

Para transcribir, construye un TsgcGRPCSpeechRecognizeRequest. Rellena el Config con el código de idioma, la codificación y la frecuencia de muestreo, apunta Audio.Uri a un objeto de Cloud Storage (o establece Audio.Content con bytes en línea), y llama a Recognize en el servicio google.cloud.speech.v1.Speech. La petición se serializa a sí misma con ToBytes, y la respuesta se analiza de vuelta en una respuesta tipada que puedes recorrer para obtener resultados y alternativas.

var
  oRequest: TsgcGRPCSpeechRecognizeRequest;
  oResponse: TsgcGRPCResponse;
  oSpeech: TsgcGRPCSpeechRecognizeResponse;
  oResult: TsgcGRPCSpeechRecognitionResult;
  oAlt: TsgcGRPCSpeechRecognitionAlternative;
  i, j: Integer;
begin
  oRequest := TsgcGRPCSpeechRecognizeRequest.Create;
  try
    oRequest.Config.Encoding := 0;             // 0 = ENCODING_UNSPECIFIED, let the API detect
    oRequest.Config.SampleRateHertz := 16000;
    oRequest.Config.LanguageCode := 'en-US';
    oRequest.Config.EnableAutomaticPunctuation := True;
    oRequest.Audio.Uri := 'gs://my-bucket/audio.flac';

    oResponse := GRPC.Call('google.cloud.speech.v1.Speech', 'Recognize',
      oRequest.ToBytes);
  finally
    oRequest.Free;
  end;

  if oResponse.StatusCode <> grpcOK then
  begin
    ShowMessage('gRPC error: ' + oResponse.StatusMessage);
    Exit;
  end;

  oSpeech := TsgcGRPCSpeechRecognizeResponse.Create;
  try
    oSpeech.LoadFromBytes(oResponse.Data);
    for i := 0 to oSpeech.ResultCount - 1 do
    begin
      oResult := oSpeech.ResultItem(i);
      for j := 0 to oResult.AlternativeCount - 1 do
      begin
        oAlt := oResult.Alternative(j);
        Memo1.Lines.Add('Transcript: ' + oAlt.Transcript);
        Memo1.Lines.Add('Confidence: ' + FloatToStr(oAlt.Confidence));
      end;
    end;
  finally
    oSpeech.Free;
  end;
end;

Configuración del reconocimiento

El objeto Config de la petición se corresponde directamente con el mensaje RecognitionConfig de Google. Más allá del idioma y la frecuencia de muestreo, puedes establecer MaxAlternatives para pedir variantes ordenadas, ProfanityFilter para enmascarar palabras ofensivas, AudioChannelCount para audio multicanal, EnableAutomaticPunctuation para una salida legible, y Model para elegir un modelo de reconocimiento ajustado. Cada propiedad es opcional y solo se emite en el cable cuando se establece, así que envías solo lo que necesitas.

Audio en línea o una URI de Cloud Storage

Los clips cortos pueden viajar dentro de la petición: asigna los bytes de audio en bruto a Audio.Content y el cliente los incrusta en el protobuf. Para archivos más largos, sube el audio a un bucket y establece Audio.Uri a una ruta gs:// en su lugar, lo que mantiene la petición pequeña y permite que Google lea el objeto directamente. Las dos son mutuamente excluyentes, estableces una u otra en una petición dada.

Resultados y alternativas

Una respuesta es una lista de resultados, uno por cada segmento de audio reconocido. Cada resultado lleva una o más alternativas ordenadas por probabilidad, con la transcripción más probable primero y una puntuación de Confidence entre 0 y 1. Itera ResultCount y AlternativeCount para leerlos todos, o simplemente toma la primera alternativa del primer resultado para la mejor suposición. Los helpers tipados hacen el análisis del protobuf, así que trabajas con strings y floats de Delphi corrientes.

Disponibilidad

El cliente gRPC de Speech-to-Text tipado forma parte de la edición Enterprise de sgcWebSockets y se ejecuta en Windows, macOS, Linux, iOS y Android. Un ejemplo listo para ejecutar, el que sirve de base a este artículo, está en Demos\21.GRPC\11.Speech_to_Text, y la referencia completa está en la página de producto del Cliente gRPC.

¿Preguntas o comentarios? Ponte en contacto. Recibirás respuesta de las personas que escribieron el código.