質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Watson

Watsonは、IBMが開発した質問応答・意思決定支援を行うシステムです。人口知能と言われることもあるが、IBMは自然言語処理と機械学習を用いて人間の意思決定を支援するコグニティブコンピューティングプラットホームと呼んでいます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

Q&A

1回答

5621閲覧

Watson の speech to text を HTTP REST で呼び出す方法

rhas

総合スコア8

Watson

Watsonは、IBMが開発した質問応答・意思決定支援を行うシステムです。人口知能と言われることもあるが、IBMは自然言語処理と機械学習を用いて人間の意思決定を支援するコグニティブコンピューティングプラットホームと呼んでいます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

0グッド

0クリップ

投稿2017/01/20 06:40

###前提・実現したいこと
【IBM Watson音声認識のAPI呼び出し】
IBM Watson の HTTP REST API で speech to text の recognize を呼び出したいです。
呼び出す部分の処理はC#で書いてます。
sessionの作成はできていて、Responseは正常に返ってきました。
(以下のURLにsession_idが入った状態で返ってきました。)
"recognize": "https://stream.watsonplatform.net/speech-to-text/api/v1/sessions/<session_id>"
を使用してAPI呼び出しをしています。

Watson の Speech to text を REST API で呼び出すときに必要なヘッダやパラメータ、音声データの渡し方等ご指摘いただきたいです。

###発生している問題・エラーメッセージ

リモートサーバーがエラーを返しました:(401) 許可されていません

###該当のソースコード

C#

1String url = "https://stream.watsonplatform.net/speech-to-text/api/v1/sessions/<session_id>"; 2 3Dictionary<string, object> param = new Dictionary<string, object>(); 4 5// byte[] data 6param.Add("data", new FileParameter(data, "","audio/ogg;codec=opus")); 7 8HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); 9CreateRequestHeaders(wr, m_username, m_passwrd, "POST", null); 10wr.Proxy = GetWebProxy(); 11wr.ContentLength = size; 12 13using (Stream rs = wr.GetRequestStream()) 14{ 15 rs.Write(data, 0, size); 16 rs.Close(); 17} 18 19HttpWebResponse wres; 20try 21{ 22 wres = wr.GetResponse() as HttpWebResponse; 23} 24catch (WebException webEx) 25{ 26 Loggers.Output.Error(webEx.ToString()); 27}

###試したこと
リクエストに必要なヘッダやパラメータに過不足があるのではないかと思い、色々と試しましたが、状況は変わりませんでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

Watsonさわったことなくて興味があったので回答しようと試したのですが、...
オチから言うと
「WebSocketでやってもうた...Sessionの方を質問していたのか...」です。

Sessionでのやり方は試していないので回答にはなりませんが、
WebSocketはドキュメント通りやれば素直にできたので参考程度に書いておくと....

C#のClientWebSocketクラスを使ってます。
Basic認証でtoken取得(本家ドキュメントのここらへん)をして、
socketをConnectionを開く→
openのメッセージを投げる("action": "start","content-type": *****, "continuous": true, "interim_results": trueあたり。***は投げるデータのタイプを...)→
あとは音声を投げれば(本家ドキュメントのここあたり)簡単にテキストが取得できました。

WebSocketクラスでもできるとは思いますが、私の興味のままに..使ったことのないClientWebSocketでやってます....)

参考程度にコードを。。。(雑実装な点は触れずに頂けると...)
マイク使って音とるほど興味はなかったので、音声データ(wavファイル)のパスを指定して音声を送信→Consoleにテキストを表示するものです。

Consoleのアプリ作って以下のクラスをnewして、wavファイルのパスを指定してSendAudioFileAsyncメソッドを呼べば、コンソールにテキストが表示されます。

csharp

1using Newtonsoft.Json; 2using System; 3using System.IO; 4using System.Net.Http; 5using System.Net.WebSockets; 6using System.Text; 7using System.Threading; 8using System.Threading.Tasks; 9 10namespace WatsonDemo 11{ 12 public class SpeechToText 13 { 14 #region variables 15 16 private const string Password = "*****passwordを入力****"; 17 private const string UserName = "******usernameを入力******"; 18 19 private const string JajpModelString = "ja-JP_BroadbandModel"; 20 private const string SpeechToTextEndpoint = @"wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize?watson-token={0}&model={1}"; 21 22 private static readonly Uri AuthEndpointUri = new Uri(@"https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api"); 23 24 private static readonly ArraySegment<byte> OpenMessage = new ArraySegment<byte>(Encoding.UTF8.GetBytes("{\"action\": \"start\", \"content-type\": \"audio/wav\", \"continuous\" : true, \"interim_results\": true}")); 25 private static readonly ArraySegment<byte> CloseMessage = new ArraySegment<byte>(Encoding.UTF8.GetBytes("{\"action\": \"stop\"}")); 26 27 #endregion 28 29 //classをnewしてこのメソッド呼べば動きます。 30 //今回は、音声データ(wav)のファイルパスを指定する想定で書いてます。 31 public async Task SendAudioFileAsync(string filePath) 32 { 33 var token = await GetAuthTokenAsync(UserName, Password); 34 var uri = GetUri(token, JajpModelString); 35 36 var socket = new ClientWebSocket(); 37 // socket open 38 await socket.ConnectAsync(uri, CancellationToken.None); 39 // open message send 40 await Task.WhenAll(socket.SendAsync(OpenMessage, WebSocketMessageType.Text, true, CancellationToken.None), HandleCallback(socket)); 41 // send audio 42 await Task.WhenAll(SendAudioToWatson(socket, filePath), HandleCallback(socket)); 43 44 await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Close", CancellationToken.None); 45 46 } 47 48 private static async Task SendAudioToWatson(ClientWebSocket client, string filePath) 49 { 50 using (var fileStream = File.OpenRead(filePath)) 51 { 52 var bytes = new byte[1024]; 53 while (fileStream.Read(bytes, 0, bytes.Length) > 0) 54 { 55 await client.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Binary, true, CancellationToken.None); 56 } 57 await client.SendAsync(CloseMessage, WebSocketMessageType.Text, true, CancellationToken.None); 58 } 59 } 60 61 62 private static async Task HandleCallback(ClientWebSocket socket) 63 { 64 var buffer = new byte[1024]; 65 while (true) 66 { 67 var segment = new ArraySegment<byte>(buffer); 68 var result = await socket.ReceiveAsync(segment, CancellationToken.None); 69 70 if (result.MessageType == WebSocketMessageType.Close) return; 71 72 var count = result.Count; 73 while (!result.EndOfMessage) 74 { 75 if (count >= buffer.Length) 76 { 77 await socket.CloseAsync(WebSocketCloseStatus.InvalidPayloadData, "count >= buffer.Length!!!!!", CancellationToken.None); 78 return; 79 } 80 81 segment = new ArraySegment<byte>(buffer, count, buffer.Length - count); 82 result = await socket.ReceiveAsync(segment, CancellationToken.None); 83 count += result.Count; 84 } 85 86 var message = Encoding.UTF8.GetString(buffer, 0, count); 87 // logging 88 Console.WriteLine(message); 89 90 if (IsDelimeter(message)) return; 91 } 92 93 94 } 95 96 private static bool IsDelimeter(string json) => JsonConvert.DeserializeObject<dynamic>(json).state == "listening"; 97 98 private static async Task<string> GetAuthTokenAsync(string user, string pass) 99 { 100 var credential = Encoding.UTF8.GetBytes($"{user}:{pass}"); 101 using (var client = new HttpClient()) 102 { 103 client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(credential)); 104 var response = await client.GetAsync(AuthEndpointUri); 105 106 return await response.Content.ReadAsStringAsync(); 107 } 108 } 109 110 private static Uri GetUri(string token, string model) => new Uri(string.Format(SpeechToTextEndpoint, token, model)); 111 } 112}

投稿2017/01/24 09:27

BEACHSIDE

総合スコア294

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rhas

2017/01/24 23:29

websocket では send でバイナリデータを送信するのですね・・・! REST ではリクエストボディに音声データを含めればいいかと思ってるのですが、いまだうまくいかず。。 もう少し検討してみます。 ご回答ありがとうございました!
BEACHSIDE

2017/01/25 00:00 編集

音声データを扱う場合、大きなデータまたはリアルタイムに一定時間データを送信し続けることが想定されるため、socketを使うのが現時点ではベターという世の中の流れです。そのため、音声系のサービスはwssを提供してることが多く、素直にそれを使うのがプラクティスとしてベターだと思います。 また、C#的な話をさせていただくと、有名な流れではありますがWebRequestは機能的にDeadなので...HttpClient使って非同期処理を行った方がよいかと思います。(...と余計な情報ばかり提供してしまっていますね....すいません)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問