Amazon Transcribe Streaming API без SDK - PullRequest
       34

Amazon Transcribe Streaming API без SDK

0 голосов
/ 12 декабря 2018

Я пытаюсь использовать новый API потоковой транскрипции от Go 1.11.В настоящее время Amazon предоставляет только Java SDK, поэтому я пробую низкоуровневый способ.

Единственный релевантный документ - это здесь , но он не показывает конечную точку.Я обнаружил в Java-примере , что это https://transcribestreaming.<region>.amazonaws.com, и я пробую регион Ирландии, т. Е. https://transcribestreaming.eu-west-1.amazonaws.com.Вот мой код для открытия двунаправленного потока HTTP / 2:

import (
    "crypto/tls"
    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/aws/external"
    "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
    "golang.org/x/net/http2"
    "io"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "time"
)

const (
    HeaderKeyLanguageCode   = "x-amzn-transcribe-language-code"  // en-US
    HeaderKeyMediaEncoding  = "x-amzn-transcribe-media-encoding" // pcm only
    HeaderKeySampleRate     = "x-amzn-transcribe-sample-rate"    // 8000, 16000 ... 48000
    HeaderKeySessionId      = "x-amzn-transcribe-session-id"     // For retrying a session. Pattern: [a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}
    HeaderKeyVocabularyName = "x-amzn-transcribe-vocabulary-name"
    HeaderKeyRequestId = "x-amzn-request-id"
)

...

region := "eu-west-1"

cfg, err := external.LoadDefaultAWSConfig(aws.Config{
    Region: region,
})
if err != nil {
    log.Printf("could not load default AWS config: %v", err)
    return
}

signer := v4.NewSigner(cfg.Credentials)

transport := &http2.Transport{
    TLSClientConfig: &tls.Config{
        // allow insecure just for debugging
        InsecureSkipVerify: true,
    },
}
client := &http.Client{
    Transport: transport,
}

signTime := time.Now()

header := http.Header{}
header.Set(HeaderKeyLanguageCode, "en-US")
header.Set(HeaderKeyMediaEncoding, "pcm")
header.Set(HeaderKeySampleRate, "16000")
header.Set("Content-type", "application/json")

// Bi-directional streaming via a pipe.
pr, pw := io.Pipe()

req, err := http.NewRequest(http.MethodPost, "https://transcribestreaming.eu-west-1.amazonaws.com/stream-transcription", ioutil.NopCloser(pr))
if err != nil {
    log.Printf("err: %+v", err)
    return
}
req.Header = header

_, err = signer.Sign(req, nil, "transcribe", region, signTime)
if err != nil {
    log.Printf("problem signing headers: %+v", err)
    return
}

// This freezes and ends after 5 minutes with "unexpected EOF".
res, err := client.Do(req)
...

Проблема заключается в том, что выполнение запроса (client.Do(req)) останавливается на пять минут, а затем заканчивается ошибкой «неожиданный EOF».

Есть идеи, что я делаю не так?Кто-то успешно использовал новый API потоковой транскрипции без Java SDK?

РЕДАКТИРОВАТЬ (11 марта 2019 г.):

Я протестировал это снова, и теперь это не времявне, но немедленно возвращает 200 OK ответ.В теле ответа есть «исключение»: {"Output":{"__type":"com.amazon.coral.service#SerializationException"},"Version":"1.0"}

Я попытался открыть поток HTTP2 с io.Pipe (как в коде выше), а также с телом JSON, описанным в документации:

{
    "AudioStream": { 
        "AudioEvent": { 
            "AudioChunk": ""
        }
    }
}

Результат был таким же.

РЕДАКТИРОВАТЬ (13 марта 2019 г.):

Как упомянуто @gpeng, удаление content-typeиз заголовков исправим SerializationException.Но затем возникает исключение IAM, и необходимо добавить разрешение transcription:StartStreamTranscription вашему пользователю IAM.Это, однако, нигде в консоли AWS IAM и должно быть добавлено вручную в качестве настраиваемого разрешения JSON: /

Здесь также есть новый / другой документ документации , который показывает неверные host иновый content-type (не используйте этот content-type, запрос вернет 404 с ним).

После удаления content-type и добавления нового разрешения, теперь я получаю исключение {"Message":"A complete signal was sent without the preceding empty frame."}.Также пишу в трубу навсегда, поэтому я снова застрял.Сообщения, описанные в новой документации, отличаются от старых, теперь, наконец, двоичные, но я их не понимаю.Любые идеи, как отправить такие сообщения HTTP2 в Go?

РЕДАКТИРОВАТЬ (Match 15, 2019): *

Если вы получаете ошибку HTTP 403 о несоответствии сигнатур, затем выполнитене устанавливать заголовки HTTP transfer-encoding и x-amz-content-sha256.Когда я их устанавливаю, подписываю запрос подписчиком AWS SDK V4, затем я получаю HTTP 403 The request signature we calculated does not match the signature you provided.

Ответы [ 3 ]

0 голосов
/ 09 апреля 2019

Я все еще сражаюсь с Node.js.Что не ясно в документах, так это то, что в одном месте говорит, что Content-Type не должно быть application/json, а в каком-то другом месте , это выглядит такполезная нагрузка должна быть закодирована как application/vnd.amazon.eventstream.Похоже, что полезная нагрузка должна быть тщательно отформатирована в двоичном формате вместо объекта JSON следующим образом:

Amazon Transcribe использует формат, называемый потоковым кодированием событий, для потоковой транскрипции.Этот формат кодирует двоичные данные с информацией заголовка, которая описывает содержимое каждого события.Вы можете использовать эту информацию для приложений, которые вызывают конечную точку Amazon Transcribe без использования Amazon Transcribe SDK.Amazon Transcribe использует протокол HTTP / 2 для потоковой транскрипции.Ключевые компоненты для запроса потоковой передачи:

  • Кадр заголовка.Он содержит заголовки HTTP для запроса и подпись в заголовке авторизации, которую Amazon Transcribe использует в качестве исходной подписи для подписи следующих фреймов данных.

  • Один или фреймы сообщений в потоке событийкодирование.Кадр содержит метаданные и необработанные аудио байты.

  • Конечный кадр.Это подписанное сообщение в кодировке потока событий с пустым телом.

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

0 голосов
/ 01 июля 2019

Я обратился в службу поддержки AWS, и теперь они рекомендуют использовать веб-сокеты вместо HTTP / 2, когда это возможно (сообщение в блоге здесь )

Если это соответствует вашему сценарию, я настоятельно рекомендую проверитьновый пример репо: https://github.com/aws-samples/amazon-transcribe-websocket-static, который показывает решение на основе браузера в JS.

Я также заметил, что у автора демонстрационного примера есть личный пример на его личном Github по адресу: https://github.com/brandonmwest/amazon-transcribe-websocket-express, но я не подтвердил, работает ли он.

Ценю, что эти примеры не в Python, но я думаю, что вам повезет больше, если использовать клиент Websocket, а не HTTP / 2 (что, честно говоря, все еще немного страшно: P)

0 голосов
/ 13 марта 2019

Попробуйте не устанавливать заголовок типа контента и посмотрите, какой ответ вы получите.Я пытаюсь сделать то же самое (но в Ruby), и это "исправлено" SerializationException.Все еще не могу заставить его работать, но у меня теперь есть новая ошибка, чтобы думать :)

ОБНОВЛЕНИЕ: у меня это работает сейчас.Моя проблема была с подписью.Если оба заголовка host и authority пройдены, они соединяются с , и обрабатываются как host на стороне сервера, когда подпись проверяется, поэтому подписи никогда не совпадают.Это не похоже на правильное поведение на стороне AWS, но не похоже, что это будет проблемой для вас в Go.

...