Amazon Transcribe Streaming API без SDK

Я пытаюсь использовать новый 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?

0 ответов

Я обратился в службу поддержки 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)

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

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

У меня было аналогичное требование для использования сервиса транскрибирования AWS с их API WebSocket в узле js. Поскольку в официальном пакете еще не было поддержки для этого, я пошел дальше и написал пакет, который называется AWS-transcribe, и его можно найти здесь. Надеюсь, это поможет.

Он предоставляет потоковый интерфейс вокруг WebSocket и может использоваться, как в примере ниже.

import { AwsTranscribe, StreamingClient } from "aws-transcribe"

const client = new AwsTranscribe({
    // if these aren't provided, they will be taken from the environment
    accessKeyId: "ACCESS KEY HERE",
    secretAccessKey: "SECRET KEY HERE",
})

const transcribeStream = client
    .createStreamingClient({
        region: "eu-west-1",
        sampleRate,
        languageCode: "en-US",
    })
    // enums for returning the event names which the stream will emit
    .on(StreamingClient.EVENTS.OPEN, () => console.log(`transcribe connection opened`))
    .on(StreamingClient.EVENTS.ERROR, console.error)
    .on(StreamingClient.EVENTS.CLOSE, () => console.log(`transcribe connection closed`))
    .on(StreamingClient.EVENTS.DATA, (data) => {
        const results = data.Transcript.Results

        if (!results || results.length === 0) {
            return
        }

        const result = results[0]
        const final = !result.IsPartial
        const prefix = final ? "recognized" : "recognizing"
        const text = result.Alternatives[0].Transcript
        console.log(`${prefix} text: ${text}`)
    })

someStream.pipe(transcribeStream)

Я все еще сражаюсь с 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, которая может пролить некоторый свет на то, как должна выполняться эта кодировка.

Другие вопросы по тегам