AWS日記⑩ (Transcribe)

# はじめに
今回は Amazon Transcribeの文字起こしを試します。

[今回作成したAmazon Transcribe の文字起こし機能を試すページ](https://labo.systems/transcribe)

# 準備
[Lambda , API Gatewayの準備をします。]
(https://qiita.com/tanaka_takurou/items/3f93295de6cff060ec09)
[S3の準備をします。]
(https://qiita.com/tanaka_takurou/items/de897b0906087cec1a86)

[Amazon Transcribeの資料]
[音声を文字起こしする](https://aws.amazon.com/jp/getting-started/hands-on/create-audio-transcript-transcribe/)
[Amazon Transcribe 日本語版で遊んでみた](https://qiita.com/zkick/items/8ef11be9bd397fcbaa59)
[Amazon Transcribeで音声の文字起こしを行う。](https://qiita.com/kooohei/items/2580addd6c1bbc8f1c34)

# WEBページ・API作成
GO言語のAWS Lambda関数ハンドラー aws-lambda-go を使用してHTMLやJSONを返す処理を作成します。
また、Transcribe を使用するため aws-sdk-go を利用します。

[参考資料]
[AWS SDK for Go API Reference](https://docs.aws.amazon.com/sdk-for-go/api/service/transcribeservice/)


##### 全体の処理の流れ

1.  音声ファイルをS3にアップロード
2.  文字起こしの処理を開始
3.  処理の進捗を確認
4.  処理完了（S3に結果ファイルが配置される）
5.  結果ファイルをS3からダウンロード


##### 文字起こし処理を開始するには StartTranscriptionJob を使う。

```golang:main.go
func startTranscription(filedata string)(string, error) {
        t := time.Now()
        b64data := filedata[strings.IndexByte(filedata, ',')+1:]
        data, err := base64.StdEncoding.DecodeString(b64data)
        if err != nil {
                return "", err
        }
        sess, err := session.NewSession(&aws.Config{
                Region: aws.String(bucketRegion)},
        )
        if err != nil {
                return "", err
        }
        contentType := "audio/mp3"
        filename := t.Format(layout2) + ".mp3"
        uploader := s3manager.NewUploader(sess)
        _, err = uploader.Upload(&s3manager.UploadInput{
                ACL: aws.String("public-read"),
                Bucket: aws.String(bucketName),
                Key: aws.String(S3MediaPath + "/" + filename),
                Body: bytes.NewReader(data),
                ContentType: aws.String(contentType),
        })
        if err != nil {
                return "", err
        }
        url := "s3://" + bucketName + "/" + S3MediaPath + "/" + filename

        svc := transcribeservice.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })

        input := &transcribeservice.StartTranscriptionJobInput{
                TranscriptionJobName: aws.String(filename),
                LanguageCode: aws.String(languageCode),
                OutputBucketName: aws.String(bucketName),
                MediaFormat: aws.String(mediaFormat),
                Media: &transcribeservice.Media{
                        MediaFileUri: aws.String(url),
                },
        }
        _, err = svc.StartTranscriptionJob(input)
        if err != nil {
                return "", err
        }

        return filename, nil
}
```


##### 文字起こし処理の進捗を確認するには ListTranscriptionJobs を使う。

```golang:main.go
func checkProgress(jobName string)(string, error) {
        svc := transcribeservice.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })

        input := &transcribeservice.ListTranscriptionJobsInput{
                JobNameContains: aws.String(jobName),
        }
        res, err := svc.ListTranscriptionJobs(input)
        if err != nil {
                return "", err
        }
        return aws.StringValue(res.TranscriptionJobSummaries[0].TranscriptionJobStatus), nil
}
```


##### 文字起こし処理の結果を確認するには GetTranscriptionJob を使う。

```golang:main.go
func getTranscriptionJob(jobName string)(string, error) {
        svc := transcribeservice.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })

        input := &transcribeservice.GetTranscriptionJobInput{
                TranscriptionJobName: aws.String(jobName),
        }
        res, err := svc.GetTranscriptionJob(input)
        if err != nil {
                return "", err
        }
        url := aws.StringValue(res.TranscriptionJob.Transcript.TranscriptFileUri)
        rep := regexp.MustCompile(`\s*/\s*`)
        tmp := rep.Split(url, -1)
        svc_ := s3.New(session.New(), &aws.Config{
                Region: aws.String("ap-northeast-1"),
        })
        obj, err2 := svc_.GetObject(&s3.GetObjectInput{
                Bucket: aws.String(bucketName),
                Key:    aws.String(tmp[len(tmp) - 1]),
        })
        if err2 != nil {
                return "", err2
        }
        defer obj.Body.Close()

        buf := new(bytes.Buffer)
        buf.ReadFrom(obj.Body)
        res_ := buf.String()

        jsonBytes := ([]byte)(res_)
        var data interface{}

        if err3 := json.Unmarshal(jsonBytes, &data); err3 != nil {
                return "", err3
        }
        results := data.(map[string]interface{})["results"]
        results_, err4 := json.Marshal(results)
        if err4 != nil {
                return "", err4
        }

        return string(results_), nil
}
```

文字起こしの結果は一旦ファイルに出力されますが、その内容を文字列としてWebページ上に、結果表示する方法をとりました。


# 終わりに
今回はAmazon Transcribeの文字起こし機能を試しました。
Rekognition、Comprehend、Pollyに比べて処理時間が長い印象がありました。