- 印刷する
- PDF
CLOVA Speechリアルタイムストリーミング API
- 印刷する
- PDF
Classic/VPC環境で利用できます。
CLOVA Spechリアルタイムストリーミング APIを通じて、リアルタイムで音声を認識し、テキストに変換する方法を説明します。
バージョン
Version | Date | Changes |
---|---|---|
v1.0.0 | 2023.12. | 最初に作成 |
v1.1.0 | 2024.07. | ガイドをアップデート |
API URL
Host | Port |
---|---|
clovaspeech-gw.ncloud.com | 50051 |
CLOVA Speech gRPCの使い方
- Clova Speechリアルタイムストリーミング APIは、gRPCを介してのみアクセスできます。
- システムが提供するすべての機能設定リクエストとレスポンスは、JSON形式で行われます。
- 現在、16kHz、1channel、16bits per sampleの PCM(headerのない raw wave)形式のみサポートします。
- 次は、Rocky Linuxを基準に Protoc Compilerをインストールし、APIを使用するための全般的な初期設定方法を説明します。
1. Protoc Compilerのインストールと準備
- Protoc Compilerをインストールします。
- Protoc Compilerを通じて言語を選択し、CLOVA Speechリアルタイムストリーミング APIインターフェースが定義された「nest.proto」ファイルを使用してCompilerを呼び出します。
- Protoc Compilerをインストールするサーバにリモートアクセスします。
- gRPC使用のためのパッケージとプラグインをインストールします。
- Rocky Linux: Python
# 最新状態の確認
sudo dnf update
# Pythonのインストール: Linuxサーバに Pythonをインストールします。
sudo dnf install python3
# pipのインストールとアップグレード: pipは Python用パッケージインストールプログラムです。
sudo dnf install python3-pip
pip3 install --upgrade pip
# grpcio-toolsのインストール: pipを使用して「grpcio-tools」をインストールします。
pip3 install grpcio-tools
# nest.protoファイルの作成
touch nest.proto
# protoc compilerで nest.protoファイルをコンパイル
python3 -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. nest.proto
- Rocky Linux: Java
# protoc-gen-grpc-javaプラグインのダウンロード(バージョン番号は確認が必要 https://github.com/grpc/grpc-java/releases)
curl -OL https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/1.36.0/protoc-gen-grpc-java-1.36.0-linux-x86_64.exe
# PATHに追加
mv protoc-gen-grpc-java-1.36.0-linux-x86_64.exe /usr/local/bin/protoc-gen-grpc-java
# 実行権限に変更する
chmod +x /usr/local/bin/protoc-gen-grpc-java
# インストールの確認
protoc-gen-grpc-java --version
# nest.protoファイルの作成
touch nest.proto
# protoc compilerで nest.protoファイルをコンパイル
protoc --proto_path=. --java_out=output/directory --grpc-java_out=output/directory nest.proto
- nest.protoファイルを開き、以下のコードを入力して保存します。
syntax = "proto3";
option java_multiple_files = true;
package com.nbp.cdncp.nest.grpc.proto.v1;
enum RequestType {
CONFIG = 0;
DATA = 1;
}
message NestConfig {
string config = 1;
}
message NestData {
bytes chunk = 1;
string extra_contents = 2;
}
message NestRequest {
RequestType type = 1;
oneof part {
NestConfig config = 2;
NestData data = 3;
}
}
message NestResponse {
string contents = 1;
}
service NestService {
rpc recognize(stream NestRequest) returns (stream NestResponse){};
}
2. Authorization
ヘッダ名 | 説明 |
---|---|
Authorization | Bearer ${secretKey} |
Protoc Compilerで grpcコードの作成が完了したら、次は認証を行う番です。
gRPC channeを設定し、nest_grpc_pb2にある client side proxyの stubを作成します。
Stubの作成後に recognizeメソッドで目的の関数を実行するには、認証キーがある metadataも一緒に含める必要があります。
- リアルタイムストリーミング APIの secretKeyは、長文認識 APIの secretKeyを使用し、NAVERクラウドプラットフォームコンソールで長文認識ドメイン > ビルダー実行 > 設定で確認できます。
- リアルタイムストリーミング APIは、Basic長文認識プランでのみサポートします。(Freeプランは不可)
Rocky Linux: Python
- Pythonファイルを1つ作成します。(demoを行うたまに nameを「main」に指定)
touch main.py
- 作成した Pythonファイルに以下の内容を追加します。
import grpc
import json
import nest_pb2
import nest_pb2_grpc
channel = grpc.secure_channel(
'clovaspeech-gw.ncloud.com:50051',
grpc.ssl_channel_credentials()
)
client = NestServiceStub(channel)
metadata = (("authorization", f"Bearer {secretKey}"),) #小文字 authorizationは必須 / secretkeyは長文認識ドメインで確認
call = client.YourMethod(YourRequest(), metadata=metadata)
- Rocky Linux: Java
- Javaファイルを1つ作成します。(demoを行うたまに nameを「main」に指定)
touch main.java
- 作成した Javaファイルに以下の内容を追加します。
ManagedChannel channel = NettyChannelBuilder
.forTarget("clovaspeech-gw.ncloud.com:50051")
.useTransportSecurity()
.build();
NestServiceGrpc.NestServiceStub client = NestServiceGrpc.newStub(channel);
Metadata metadata = new Metadata();
metadata.put(Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER),
"Bearer ${secretKey}");
client = MetadataUtils.attachHeaders(client, metadata);
3. Config JSONのリクエスト
- ストリーミング APIを初めて呼び出す際は、以下のような config jsonを先に送る必要があります。
- protocで作成された nest_pb2の NestRequestオブジェクトを使って config JSONをストリーミングエンドポイントに送ります。
- Config JSONには以下の4つのフィールドがあります。4つが全部必須データではありませんが、明確な音声認識のために、transcriptionは認識をリクエストする言語を設定することをお勧めします。
- transcription: 音声認識言語の設定
- keywordBoosting: 入力された単語の認識率を高める設定
- forbidden: 禁止語を設定
- semanticEpd: 音声認識結果生成基準を設定
- サンプルコードは下段にあります
{
# Transcriptionの設定情報
"transcription": { # optional, top level key
"language": string
}
# Keyword Boostingの設定情報
"keywordBoosting": { # optional, top level key
"boostings": [
{
"words": string,
"weight": float64
}
]
},
# Forbiddenの設定情報
"forbidden": { # optional, top level key
"forbiddens": string
}
}
# semanticEpdの設定情報
"semanticEpd": {
"skipEmptyText": bool,
"useWordEpd": bool,
"usePeriodEpd": bool,
"gapThreshold": int,
"durationThreshold": int,
"syllableThreshold": int
}
}
1) Transcription
language
音声認識対象の言語コードです。明確な音声認識のために、認識をリクエストする言語を設定することをお勧めします。- 韓国語(ko)
- 英語(en)
- 日本語(ja)
Transcription JSON Format
# transcription設定リクエスト json format
{
"transcription": {
"language": string # required key
}
}
- 設定例
# transcription設定リクエスト例
{
"transcription": {
"language": "ko"
}
}
2) Keyword Boosting
- あらかじめ登録したキーワードの認識率を高めることができます。
- キーワードの重み付け(weight)は0~5.0の間の実数範囲です。
- 重み付けが0の場合、ブースティングしません。
- すべてのキーワードの重み付けは同じでなければなりません。
- 同じ重み付けに設定する単語の集まりは、
words
key string内でコンマ(,
)で繋げて転送することができます。
- 同じ重み付けに設定する単語の集まりは、
- キーワードの重み付け(weight)は0~5.0の間の実数範囲です。
- Keyword Boosting実行時、単語の前後のスペース(space)も考慮されます。
- 機能の設定方法の詳細は、Keyword Boosting設定 JSON Formatをご参照ください。
Keyword Boosting JSON Format
# keyword boosting設定リクエスト json format
{
"keywordBoosting": {
"boostings": [
{
"words": string,
"weight": float64
}
]
}
}
- 設定例
# keyword boostingの設定リクエスト例
{
"keywordBoosting": {
"boostings": [
{
"words": "test,test1,test2",
"weight": 1
},
{
"words": "テスト,テスト1,テスト2",
"weight": 0.5
}
]
}
}
3) Forbidden
- あらかじめ登録したキーワードの認識結果に禁止語タグを提供する機能です。
- 禁止語タグ:
<forbidden>禁止語</forbidden>
- 禁止語タグ:
- 禁止語タグは認識結果の
text
keyの valueにのみ追加されます。 - 追加された禁止語タグは、認識結果の
position
、periodPosition
、alignInfo
に影響を与えません。 - 2つ以上の禁止語を登録する場合、
forbiddens
key string内でコンマ(,
)で繋げて転送することができます。 - 禁止語処理時、禁止語の前後のスペース(space)も考慮されます。
- 機能の設定方法の詳細は、禁止語設定 JSON Formatをご参照ください。
Forbidden JSON Format
# forbidden設定リクエスト json format
{
"forbidden": {
"forbiddens": string
}
}
- 設定例
{
"forbidden": {
"forbiddens": "禁止語1,禁止語2"
}
}
4) SemanticEpd
- 音声認識結果の生成基準を設定するオプションです。
- 各オプションの基準に基づいて認識結果を生成し、発話形態に合わせてオプションを設定できます。
- 機能の設定方法の詳細は、SemanticEpd JSON Formatをご参照ください。
- 各属性の基準は次の通りです。
skipEmptyText
- 認識結果がない結果値を転送するかどうかを選択するオプションです。
- 基本設定は
false
です。true
に設定する場合、認識された結果がないと転送しません。
useWordEpd
- 単語に基づいて認識結果を生成するオプションです。
- 基本設定は
false
です。
usePeriodEpd
- 句読点に基づいて認識結果を生成するオプションです。
- 基本設定は
false
です。
gapThreshold
gapThreshold
以上の黙字が発生した場合に認識結果を生成するオプションです。- 基本設定は
false
で、単位はミリ秒です。
durationThreshold
durationThreshold
に基づいて、認識結果の durationに応じて認識結果を生成するオプションです。- 基本設定は
false
で、単位はミリ秒です。
syllableThreshold
- 音節数に基づいて認識結果を生成するオプションです。
- スペース「 」とピリオド「.」も1つの音節として処理されます。
SemanticEpd JSON Format
# semanticEpd設定リクエスト json format
{
"semanticEpd": {
"skipEmptyText": bool,
"useWordEpd": bool,
"usePeriodEpd": bool,
"gapThreshold": int,
"durationThreshold": int,
"syllableThreshold": int
}
}
- 設定例
{
"semanticEpd": {
"skipEmptyText": false,
"useWordEpd": true,
"usePeriodEpd": true,
"gapThreshold": 500,
"durationThreshold": 5000,
"syllableThreshold": 20
}
}
4.Config JSONレスポンス形式
{
"uid": string, # required
"responseType": [ "config" ], # required
"config": { # required
"status":string, # required
# configの設定によっては、以下の fieldsが存在しない場合があります。
# 例) 禁止語を設定していない場合、「forbidden」keyは存在しません。
"keywordBoosting": { # optional, top level key
"status":string,
},
"forbidden": { # optional, top level key
"status":string,
},
"semanticEpd": { # optional, top level key
"status":string,
}
}
}
1) 補足説明
- Config JSONレスポンスは次のように構成されます。
- Config JSONレスポンスの
config.status
keyの valueは以下のような値を持つことができます。Success
- Config JSONリクエストが成功し、正常に gRPC Serviceに目的の設定が保存された場合
Failure
- Config JSONリクエストが含む機能はサーバで認識されたが、詳細設定に失敗した場合
top_level_key
:transcription
keywordBoosting
forbidden
- Config JSONレスポンスの
config.${top_level_key}.status
は以下のような値を持つことができます。- 共通
Unknown key: ${top_level_key}-${unknown_key}
- Config JSONリクエストが、サーバがサポートしない sub level keyを持っている場合
Invalid type: ${top_level_key}-${invalid_type_key}
- Config JSONリクエストが、サーバがサポートしない sub level value typeを持っている場合
- transcription
Invalid language code: ${invalid_language_code}
- Config JSONリクエストで、languageが事前に定義された言語コードではない場合
- keywordBoosting
Internal system error
- サーバ内部で問題が発生した場合
- 共通
"${message}"
- Config JSONリクエストが正常に認識されなかったか、Config JSONリクエストが正常に処理できない場合
- ${message}内容の候補になれるのは以下の通りです。
Invalid request json format
- Config JSONリクエストが正常な JSON形式ではない場合
Unknown key: ${unknown_key}
- Config JSONリクエストが、サーバがサポートしない top level keyを持っている場合
Invalid type: ${invalid_type_key}
- Config JSONリクエストが、サーバがサポートしない top level value typeを持っている場合
Required key is not provided
- Config JSONリクエストが、サーバで定義した Required keyを含まない場合
No more slot
- 現在、サーバで収容可能なリソースがない場合
ConfigRequest did not complete
- Config JSONリクエストの処理が完了していない状態でサーバが認識リクエストを受けた場合
Lifespan expired
- gRPC Serviceの使用時間が期限切れになった場合
- gRPC Serviceの使用時間は100時間に設定されます。
Failed to received request msg
- サーバがリクエストメッセージを正常に受信できなかった場合
Model server is not working
- サーバ内部で問題が発生した場合
Internal server error
- サーバ内部で問題が発生した場合
- Config JSONレスポンスの
2) Config JSON例
# Config JSONリクエスト例
# Keyword Boosting && 禁止語機能設定をリクエストする場合
{
"keywordBoosting": {
"boostings": [
{
"words": "test,test1,test2",
"weight": 1
},
{
"words": "テスト,テスト1,テスト2",
"weight": 0.5
}
]
},
"forbidden": {
"forbiddens": "禁止語1,禁止語2"
}
}
# Config JSONレスポンス例
# Keyword Boosting && 禁止語機能設定をリクエストし、成功した場合
{
"uid": "2023-03-02_13-13-16_b49f35ec-7cf0-434b-9489-30b0b66f6d58",
"responseType": [ "config" ],
"config": {
"status": "Success",
"keywordBoosting": {
"status": "Success"
},
"forbidden" : {
"status": "Success"
}
}
# Keyword Boosting && 禁止語機能設定をリクエストし、失敗した場合 1
# 禁止語リクエスト jsonに top level keyをサポートしない「forbidden」に設定してリクエストした場合
{
"uid": "2023-03-02_13-13-16_b49f35ec-7cf0-434b-9489-30b0b66f6d58",
"responseType": [ "config" ]
"config": {
"status": "Unknown key: forbidden"
}
}
5. Recognizeリクエスト
- Config JSONで目的の設定値を指定したら、次は音声認識を行う番です。
- protocで作成してくれたコードにある NestRequestと上で設定した認証メタデータを stubのメソッドである recognizeを通じて音声認識 APIを呼び出します。
- サンプルコードは下段にあります。NestRequestを呼び出す際は、次のような Optional設定も一緒に呼び出すことができます。
Recognize Request JSON Format (ExtraContents)
{
"epFlag": bool # optional
"seqId": int # optional
}
recognizeリクエストで使用される JSON Formatです。
epFlag
- recognizeリクエストのうち、一時停止または最後の認識リクエストで使用される flagです。
- 一時停止または最後のリクエストの場合、
epFlag
をtrue
に設定するとエンジンに溜めておいた認識リクエスト Bufferを直ちに返して認識を終了し、delayなく認識結果を受け取ることができます。(コネクション接続は維持) - 設定せずに転送する場合は
false
に設定されます。unvoiceTime
(10秒)を超えるまで認識リクエストがない場合、溜めておいた認識リクエスト Bufferを直ちに返して認識を終了し、delayなく認識結果を受け取ることができます。(コネクション接続は維持) - optionalフィールドです。
seqId
- Recognize接続後に送信する認識リクエストごとに持つ固有の IDです。
epFlag
をtrue
に設定してリクエストした場合、その後に受け取った認識結果で、本リクエストに対する結果かどうかを確認する用途に使用できます。seqId
を設定して転送しない場合、認識結果のseqId
は0に設定されます。seqId
使用時は0ではない値に設定して転送することをお勧めします。- optionalフィールドです。
参考事項
epFlag
とseqId
のどちらも使用しない場合、リクエスト JSONを""(empty string)
に設定できます。
6. Recognizeレスポンス
- ストリーミング APIを呼び出すと、次のようなレスポンスをサーバから受け取ることができます。
Transcription JSON Format
{
"uid": string
"responseType": [ "transcription" ]
"transcription": {
"text": string,
"position": int,
"periodPositions": [ int ],
"periodAlignIndices": [ int ],
"epFlag": bool,
"seqId": int,
"epdType": string, // 結果が生成された epd基準
"startTimestamp": int,
"endTimestamp": int,
"confidence": float64,
"alignInfos": [
{
"word": string, // 音節
"start": int, // StartTimestamp in ms
"end": int, // EndTimestamp in ms
"confidence": float64 // 認識信頼度
}
]
}
}
- 設定例
{
"uid": "2023-03-02_13-13-16_b49f35ec-7cf0-434b-9489-30b0b66f6d58"
"responseType": [ "transcription" ]
"transcription": {
"text": "これはテキストです。",
"position": 0,
"periodPositions": [3],
"periodAlignIndices": [3],
"epFlag": false,
"seqId": 0,
"epdType": "durationThreshold",
"startTimestamp": 190,
"endTimestamp": 840,
"confidence": 0.997389124199423,
"alignInfos": [
{"word":"これは","start":190,"end":340,"confidence":0.9988637124943075},
{"word":"テキスト","start":341,"end":447,"confidence":0.9990018488549978},
{"word":"です","start":448,"end":580,"confidence":0.9912501264550316},
{"word":".","start":581,"end":700,"confidence":0.9994397226648595},
{"word":" ","start":701,"end":840,"confidence":0.9984142043105126}
]
}
}
Failed Recognize Response JSON Format
{
"uid": string, # required
"responseType": [ "recognize" ], # required
"recognize": { # required
"status": string, # required
"epFlag": { # optional
"status": string
},
"seqId": { # optional
"status": string
},
"audio": { # optional
"status": string
}
}
}
認識リクエストが失敗したか、認識リクエストが正常に処理できない場合、レスポンスの JSON形式です。
recognize.status
は recognizeリクエスト失敗の理由または処理できない理由を表す keyで、以下のような値を持ちます。Invalid Type
epFlag
またはseqId
value typeが事前に定義された typeと合致しない場合
recognize.status
は recognizeリクエスト失敗の理由または処理できない理由を表す keyで、以下のような値を持ちます。Required key is not provided
extraContents
の required keyであるepFlag
を渡さなかった場合
Invalid request json format
extraContents
が json formatではない場合
Unknown key
extraContents
に protocol specにない keyを作成した場合無効な keyを入力した場合には、ユーザーの便宜のために、statusの末尾に無効な key情報を付けて渡す
# invalid extraContents { "test1": "test-val1", "test2": "test-val2" } # response msg { "uid": "2023-03-02_13-13-16_b49f35ec-7cf0-434b-9489-30b0b66f6d58" "responseType": ["recognize"], "recognize": { "status": "Unknown key: test1, test2" } }
ConfigRequest is already called
- サーバで configリクエストの処理が完了した状態で再度 configリクエストを受けた場合
Lifespan expired
- gRPC Serviceの使用時間が期限切れになった場合
- gRPC Serviceの使用時間は100時間に設定されます。
Failed to received request msg
- サーバでリクエストメッセージを正常に受信できなかった場合
Model server is not working
- サーバ内部で問題が発生した場合
Internal server error
- サーバ内部で問題が発生した場合
Invalid format
- 転送したオーディオ形式が無効な形式の場合
Failure
- recognizeリクエスト jsonに
extraContents
が無効な形式の場合 epFlag.status
またはseqId.status
に、失敗の詳細な理由が表示されます。
- recognizeリクエスト jsonに
epFlag.status
は epFlagの入力に失敗した理由を表し、以下のような値を持ちます。Not found
- required keyの epFlagに対して作成しなかった場合
Invalid type
- value typeが事前に定義された typeと合致しない場合
seqId.status
は seqIdの入力に失敗した理由を表し、以下のような値を持ちます。Invalid type
- value typeが事前に定義された typeと合致しない場合
audio.status
はオーディオデータの処理に失敗した理由を表し、以下のような値を持ちます。Invalid format
- Audio formatが事前に定義された formatと合致しない場合
- 参考事項
recongnize.status
の値によって、epFlag
、seqId
、audio
keyは省略されることがあります。
分析方法
text
- 認識結果を担当する keyです。
position
渡された full textに対し、
text
で渡された textの offsetを担当する keyです。text
とposition
を使用して、full textを構成する方法渡された順序 認識結果 full text 1 {text: "ABC", position: 0, ...} 2 {text: "DEFG", position: 3, ...}
periodPositions
- 渡された full textに対し、
text
で渡された.
(句読点)の offsetを担当する keyです。 text
に句読点がない場合、空の listで渡されます。
- 渡された full textに対し、
periodAlignIndices
text
で渡された.
(句読点)のalignInfos
での index情報を担当する keyです。text
に句読点がない場合、空の listで渡されます。
epFlag
は- リクエストで epFlagを Trueに設定し、送信した音源の認識結果を含めるかどうかを表す keyです。
seqId
- 本認識結果が含む最後のリクエストの
seqId
を表す keyです。 epFlag
keyの valueが falseの時は0が返されます。epFlag
keyの値が trueのときは、処理された最後の認識リクエストの seqIdが返されます。
- 本認識結果が含む最後のリクエストの
epdType
- 認識結果を生成するのに使用された epd基準を担当する keyです。
- epd基準に基づいた
epdType
値黙字
に基づいて認識結果が生成された場合、gap
最後の audio chunk
が含まれて認識結果が生成された場合、endPoint
時間
に基づいて認識結果が生成された場合、durationThreshold
句読点
に基づいて認識結果が生成された場合、period
音節数
に基づいて認識結果が生成された場合、syllableThreshold
unvoiceTime
実行(サーバ設定)により認識結果が生成された場合、unvoice
startTimestamp
,endTimestamp
- 認識結果のタイムスタンプ情報です。
- 単位は
ms
(ミリ秒)を使用します。
confidence
- 認識結果(
text
)に対する信頼度を表す keyです。 - 認識結果に含まれるすべての音節信頼度(
alignInfos.confidence
)値の幾何平均で計算されます。
- 認識結果(
alignInfos
text
を構成する各音節のalign情報
を担当する keyです。text
に認識された音節がない場合、""(empty text)
のalign情報
を追加して渡します。- align情報の説明
word
- 音節情報を担当する keyです。
start
- 音節の開始 timestampを担当する keyです。
- 単位は
ms
を使用します。
end
- 音節の終了 timestampを担当する keyです。
- 単位は
ms
を使用します。
confidence
- 音節が認識された結果に対する信頼度を表す keyです。
- 0から1の間の値を持ちます。
Demo [Python]
import grpc
import json
import nest_pb2
import nest_pb2_grpc
AUDIO_PATH = "path/to/audio/file" #認識対象の Audioファイルがあるパスを入力してください。(16kHz、1channel、16 bits per sampleの PCM(headerがない raw wave)形式)
CLIENT_SECRET = "長文認識 secretKey"
def generate_requests(audio_path):
# 初期設定リクエスト: 音声認識設定
yield nest_pb2.NestRequest(
type=nest_pb2.RequestType.CONFIG,
config=nest_pb2.NestConfig(
config=json.dumps({"transcription": {"language": "ko"}})
)
)
# オーディオファイルを開いて32,000バイトずつ読み取る
with open(audio_path, "rb") as audio_file:
while True:
chunk = audio_file.read(32000) # オーディオファイルのチャンクを読み取る
if not chunk:
break # データがなくなったらループ終了
yield nest_pb2.NestRequest(
type=nest_pb2.RequestType.DATA,
data=nest_pb2.NestData(
chunk=chunk,
extra_contents=json.dumps({"seqId": 0, "epFlag": False})
)
)
def main():
# Clova Speechサーバに対するセキュリティ gRPCチャンネルを設定
channel = grpc.secure_channel(
"clovaspeech-gw.ncloud.com:50051",
grpc.ssl_channel_credentials()
)
stub = nest_pb2_grpc.NestServiceStub(channel) # NestServiceのスタブを作成
metadata = (("authorization", f"Bearer {CLIENT_SECRET}"),) # 認証トークンと一緒にメタデータを設定
responses = stub.recognize(generate_requests(AUDIO_PATH), metadata=metadata) # 作成されたリクエストで recognizeメソッドを呼び出す
try:
# サーバからのレスポンスを繰り返し処理
for response in responses:
print("Received response: " + response.contents)
except grpc.RpcError as e:
# gRPCエラー処理
print(f"Error: {e.details()}")
finally:
channel.close() # 作業が終わったらチャンネルを閉じる
if __name__ == "__main__":
main()
Demo [Java]
Project Structure
├───pom.xml
│ │
└───src
│ ├───main
│ │ ├───java
│ │ │ └───com
│ │ │ └───example
│ │ │ └───grpc
│ │ │ GRpcClient.java
│ │ │
│ │ ├───proto
│ │ │ nest.proto
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>clova-speech-grpc</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<netty.version>4.1.52.Final</netty.version>
<grpc.version>1.35.0</grpc.version>
<protoc.version>3.14.0</protoc.version>
</properties>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.12</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<showDeprecation>true</showDeprecation>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
grpcClient.java
package com.example.grpc;
import java.io.FileInputStream;
import java.util.concurrent.CountDownLatch;
import com.google.protobuf.ByteString;
import com.nbp.cdncp.nest.grpc.proto.v1.NestConfig;
import com.nbp.cdncp.nest.grpc.proto.v1.NestData;
import com.nbp.cdncp.nest.grpc.proto.v1.NestRequest;
import com.nbp.cdncp.nest.grpc.proto.v1.NestResponse;
import com.nbp.cdncp.nest.grpc.proto.v1.NestServiceGrpc;
import com.nbp.cdncp.nest.grpc.proto.v1.RequestType;
import io.grpc.ManagedChannel;
import io.grpc.Metadata;
import io.grpc.StatusRuntimeException;
import io.grpc.netty.NettyChannelBuilder;
import io.grpc.stub.MetadataUtils;
import io.grpc.stub.StreamObserver;
public class GRpcClient {
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
ManagedChannel channel = NettyChannelBuilder
.forTarget("clovaspeech-gw.ncloud.com:50051")
.useTransportSecurity()
.build();
NestServiceGrpc.NestServiceStub client = NestServiceGrpc.newStub(channel);
Metadata metadata = new Metadata();
metadata.put(Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER),
"Bearer ${secretKey}");
client = MetadataUtils.attachHeaders(client, metadata);
StreamObserver<NestResponse> responseObserver = new StreamObserver<NestResponse>() {
@Override
public void onNext(NestResponse response) {
System.out.println("Received response: " + response.getContents());
}
@Override
public void onError(Throwable t) {
if(t instanceof StatusRuntimeException) {
StatusRuntimeException error = (StatusRuntimeException)t;
System.out.println(error.getStatus().getDescription());
}
latch.countDown();
}
@Override
public void onCompleted() {
System.out.println("completed");
latch.countDown();
}
};
StreamObserver<NestRequest> requestObserver = client.recognize(responseObserver);
requestObserver.onNext(NestRequest.newBuilder()
.setType(RequestType.CONFIG)
.setConfig(NestConfig.newBuilder()
.setConfig("{\"transcription\":{\"language\":\"ko\"}}")
.build())
.build());
java.io.File file = new java.io.File("~/media/42s.wav");
byte[] buffer = new byte[32000];
int bytesRead;
FileInputStream inputStream = new FileInputStream(file);
while ((bytesRead = inputStream.read(buffer)) != -1) {
requestObserver.onNext(NestRequest.newBuilder()
.setType(RequestType.DATA)
.setData(NestData.newBuilder()
.setChunk(ByteString.copyFrom(buffer, 0, bytesRead))
.setExtraContents("{ \"seqId\": 0, \"epFlag\": false}")
.build())
.build());
}
requestObserver.onCompleted();
latch.await();
channel.shutdown();
}
}
FAQs
- Recognize APIの
extraContents
フィールドで epFlag、seqId項目はどのように活用できますか?- 一時停止の目的で活用したり、送信したリクエストに対するレスポンスをすべて受け取ったかどうかを確認する用途に使用できます。
- gRPC Serviceで一時停止機能をサポートしますか?
- 一時停止機能は提供していません。ただし、Recognize APIで
extraContents
フィールドのepFlag
項目をtrue
に設定してリクエストを転送した後、一定時間 Recognizeリクエストを行わない方法で実装が可能です。epFlag
項目の説明をご参照ください。 - epFlagを trueに設定せずに Recognizeをリクエストして一定時間再リクエストしない場合、サーバ内部で設定された
unvoiceTime
(10秒)に基づいてバッファリングされている認識リクエストを処理し、レスポンス結果を表示します。
- 一時停止機能は提供していません。ただし、Recognize APIで
- Recognize APIはどんな音源データ形式をサポートしますか?
- 現在、16kHz、1channel、16bits per sampleの PCM(headerのない raw wave)形式のみサポートします。
- Close APIを呼び出す前に、Recognize APIの extraContentsに
epFlag
項目をtrue
に設定するのは必須ですか?epFlag
項目をtrue
に設定する必要はありません。ただし、最後の Recognizeリクエストに対して迅速なレスポンス結果を受け取りたい場合は、epFlag
項目をtrue
に設定することをお勧めします。epFlag
項目の説明をご参照ください。
- 送ったリクエストに対するレスポンスをすべて受け取ったかどうかはどのように確認できますか?
- Recognize APIを呼び出す際に、
extraContents
フィールドのepFlag
とseqId
項目を活用できます。epFlag
項目をtrue
に設定し、seqId
項目を0ではない任意の値に設定した Recognizeリクエストの処理結果は、RecognizeレスポンスのepFlag
、seqId
を照合すると確認できます。Recognize Responseのレスポンス JSON形式をご参照ください。
- Recognize APIを呼び出す際に、
- gRPC Serviceの Connection Lifetime制限がありますか?
- gRPC Serviceは、Connection Lifetimeの制限を100時間に設定していますが、ネットワーク問題などで切断が発生する場合があります。安定的なサービス利用のために retryロジックを反映することをお勧めします。