Как отправить запрос преобразования речи в текст с помощью google_speech1 в Rust?

#oauth-2.0 #rust #google-speech-api

#oauth-2.0 #Ржавчина #google-speech-api

Вопрос:

Я пытаюсь использовать google_speech1 для Rust, но в документации приведены неполные примеры, из-за чего мне, новичку как в Rust, так и в использовании Google Speech Api, очень сложно разобраться, как выполнить преобразование речи в текстовый запрос.

Более конкретно, я хотел бы иметь возможность отправлять локальный аудиофайл, указывать исходный язык и извлекать транскрипцию.

Вот самое близкое, что я смог найти в официальной документации (https://docs.rs/google-speech1/1.0.8 20181005/google_speech1/struct.SpeechRecognizeCall.html ):

 use speech1::RecognizeRequest;

// As the method needs a request, you would usually fill it with the desired information
// into the respective structure. Some of the parts shown here might not be applicable !
// Values shown here are possibly random and not representative !
let mut req = RecognizeRequest::default();

// You can configure optional parameters by calling the respective setters at will, and
// execute the final call using `doit()`.
// Values shown here are possibly random and not representative !
let result = hub.speech().recognize(req)
             .doit();
  

Обновить
Делая шаг назад, даже простые примеры, представленные на веб-сайте, похоже, не выполняются должным образом. Вот несколько примеров очень простого кода:

 pub mod speech_api_demo {
    extern crate google_speech1 as speech1;
    extern crate hyper;
    extern crate hyper_rustls;
    extern crate yup_oauth2 as oauth2;
    use oauth2::{ApplicationSecret, Authenticator, DefaultAuthenticatorDelegate, MemoryStorage};
    use speech1::Speech;
    use speech1::{Error, Result};
    use std::fs::File;
    use std::io::Read;

    #[derive(Deserialize, Serialize, Default)]
    pub struct ConsoleApplicationSecret {
        pub web: Option<ApplicationSecret>,
        pub installed: Option<ApplicationSecret>,
    }

    pub fn speech_sample_demo() {
        /*
           Custom code to generate application secret
        */

        let mut file =
            File::open("C:\Users\YOURNAME\.google-service-cli\speech1-secret.json").unwrap();
        let mut data = String::new();
        file.read_to_string(amp;mut data).unwrap();

        use serde_json as json;
        let my_console_secret = json::from_str::<ConsoleApplicationSecret>(amp;data);

        assert!(my_console_secret.is_ok());
        let unwrappedConsoleSecret = my_console_secret.unwrap();
        assert!(unwrappedConsoleSecret.installed.is_some() amp;amp; unwrappedConsoleSecret.web.is_none());

        let secret: ApplicationSecret = unwrappedConsoleSecret.installed.unwrap();

        /*
           Custom code to generate application secret - END
        */

        // Instantiate the authenticator. It will choose a suitable authentication flow for you,
        // unless you replace  `None` with the desired Flow.
        // Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about
        // what's going on. You probably want to bring in your own `TokenStorage` to persist tokens and
        // retrieve them from storage.
        let auth = Authenticator::new(
            amp;secret,
            DefaultAuthenticatorDelegate,
            hyper::Client::with_connector(hyper::net::HttpsConnector::new(
                hyper_rustls::TlsClient::new(),
            )),
            <MemoryStorage as Default>::default(),
            None,
        );
        let mut hub = Speech::new(
            hyper::Client::with_connector(hyper::net::HttpsConnector::new(
                hyper_rustls::TlsClient::new(),
            )),
            auth,
        );

        let result = hub.operations().get("name").doit();

        match result {
            Err(e) => match e {
                // The Error enum provides details about what exactly happened.
                // You can also just use its `Debug`, `Display` or `Error` traits
                Error::HttpError(_)
                | Error::MissingAPIKey
                | Error::MissingToken(_)
                | Error::Cancelled
                | Error::UploadSizeLimitExceeded(_, _)
                | Error::Failure(_)
                | Error::BadRequest(_)
                | Error::FieldClash(_)
                | Error::JsonDecodeError(_, _) => (println!("{}", e)),
            },
            Ok(res) => println!("Success: {:?}", res),
        }
    }
}

  

Запуск этого кода (вызов speech_sample_demo) выдает следующую ошибку:

Ошибка при извлечении токена: недопустимая область: ‘описание не предоставлено’

Я также попробовал какой-то очень уродливый код, чтобы принудительно ввести область видимости в запрос, но это не имело никакого значения. Мне трудно понять, что означает эта ошибка. Я что-то упускаю в своем запросе или это что-то еще мешает на другом конце? Или, может быть, эта библиотека кода api просто сломана?

Пожалуйста, также обратите внимание, что идентификатор клиента и секрет клиента, предоставленные по умолчанию, больше не работают, когда я использовал их, было бы сказано, что учетная запись удалена.

Затем я настроил клиент OAuth 2.0 и сгенерировал файл json, который скопировал в папку по умолчанию, а затем начал получать ошибку, описанную выше. Возможно, это просто я неправильно настраиваю учетную запись Google Api, но в любом случае было бы здорово, если бы кто-нибудь другой мог попробовать это, чтобы увидеть, единственный ли я, у кого возникают эти проблемы.

Как только я закончу выполнение такого простого запроса, у меня будет готов к тестированию еще немного кода, который отправляет аудиофайл, но пока что он завершается сбоем на самом раннем этапе процесса.

Комментарии:

1. Вы пробовали делать то, что написано в комментариях? А именно заполнение полей RecognizeRequest соответствующей информацией?

2. @Jmb попробовал только сейчас, но надеялся, что если кто-то использовал это раньше, сможет предоставить какой-нибудь базовый рабочий код. Повторю попытку позже. Спасибо.

3. @Jmb это действительно доставляет мне немало хлопот. Я создал некоторый код для запроса преобразования речи в текст, но даже не могу его протестировать, потому что застрял на следующей ошибке: » Ошибка извлечения токена с ошибкой: недопустимая область: ‘описание не предоставлено’ «.

4. Можете ли вы добавить код, который вы пробовали, к вопросу вместе с полным сообщением об ошибке?

5. @Jmb Я обновил вопрос, добавив запрошенную информацию.

Ответ №1:

Ошибка, которую вы получаете, происходит из here и означает, что область OAuth, которую вы использовали при создании файла учетных данных, не позволяет вам получить доступ к Google speech API. Таким образом, проблема не в вашем коде Rust, а в скрипте, который вы использовали для генерации токенов доступа OAuth.

По сути, это означает, что когда вы создавали свой файл OAuth json, вы запросили доступ к Google API общим способом, но вы не сказали, какие конкретные API вы намеревались использовать. Согласно этому документу, вам необходимо запросить доступ к https://www.googleapis.com/auth/cloud-platform области видимости.

Комментарии:

1. Я просмотрел исходный код библиотеки, и он вводит этот URL в каждый запрос (или этот код поврежден?), Я даже пытался вводить его сам, но в любом случае это то, что должно быть в запросе (насколько я понимаю). Вы пробовали заставить этот код работать с вашей стороны или можете конкретно указать шаги, которые я пропустил, если таковые имеются? Я ценю ваши усилия, но это остается вопросом о библиотеке Rust, которая позволяет использовать Google Api, и я ищу доказательства того, что это работает (и что исправить, чтобы это заработало), поскольку в Интернете так мало информации об этом.

2. Библиотека правильно вставила этот URL. Шаг, который вы пропускаете, находится перед переходом к части rust, когда вы генерируете файл json, содержащий токены доступа OAuth. Как именно вы сгенерировали этот файл json? С помощью какого кода или какого инструмента и с какими параметрами?

3. Я вошел в консоль Google API, создал проект, включил для него API преобразования речи в текст, затем создал клиент oauth2 с типом other, а затем, как только он был создан, я смог загрузить файл JSON, затем загружаю его из приложения с помощью опубликованного мной кода.

4. Я не уверен, что вы называете » клиентом oauth2 с типом other «. Согласно разделам RFC OAuth2 4.1.1 и 3.3 , когда клиент запрашивает авторизацию, он должен указать scope эту авторизацию. Итак, вы указали https://www.googleapis.com/auth/cloud-platform URL где-нибудь в вашем » клиенте oauth2 с типом other «?

5. Как было сказано с самого начала, я надеялся получить от кого-нибудь подтверждение того, что эта библиотека действительно работает, но я не могу спорить с тем фактом, что, похоже, с моим клиентом Oauth2 действительно что-то не так, пытаюсь разобраться. Теперь я должен добавить к нему область видимости, но следующий шаг требует проверки, но запрашивает URL-адрес подтверждения, и я понятия не имею, что указать, становится ясно, что я мало что знаю об использовании этих Api Google… сообщу здесь, если у меня получится, а пока, если у вас есть шаги для создания клиента oauth2, совместимого с этой библиотекой, это было бы неплохо :).

Ответ №2:

Вам не хватает параметра потока для аутентификатора. Вот как вы получаете токен доступа. Вы создаете перечисление, используя FlowType.

пример:

     use oauth2::{ApplicationSecret, Authenticator, DefaultAuthenticatorDelegate, MemoryStorage,FlowType};



let Flo = FlowType::InstalledInteractive;
let auth = Authenticator::new(
                amp;secret,
                DefaultAuthenticatorDelegate,
                hyper::Client::with_connector(hyper::net::HttpsConnector::new(
                    hyper_rustls::TlsClient::new(),
                )),
                <MemoryStorage as Default>::default(),
                None,)
  

Смотрите здесь: https://docs.rs/yup-oauth2/1.0.3/yup_oauth2/enum.FlowType.html

Разобраться не совсем просто.

Ответ №3:

Я выполнил эту работу через учетные записи служб, выполнив это

     let https = hyper_rustls::HttpsConnectorBuilder::new()
        .with_native_roots()
        .https_only()
        .enable_http1()
        .build();

    let service_account_key: oauth2::ServiceAccountKey = oauth2::read_service_account_key(
        amp;"PATH_TO_SERVICE_ACCOUNT.json".to_string(),
    )
    .await
    .unwrap();

    let auth = oauth2::ServiceAccountAuthenticator::builder(service_account_key)
        .build()
        .await
        .unwrap();

    let hub = Speech::new(hyper::Client::builder().build(https), auth);