[iOS][Swift 3] Microsoft Cognitive Services APIsのSpeech Translation API (音声翻訳) をSwiftで利用してみました。
1 はじめに
MicrosoftのCognitive Services APIs(マイクロソフト認知サービスAPI)では、AI技術を利用した、たくさんのサービスが提供されていますが、Translator APIは、そのうちの翻訳に関するものです。
https://www.microsoft.com/cognitive-services/en-us/translator-api
Translator APIでは、「テキスト」を入力とするものと、「音声」を入力とするものが提供されていますが、現在では、どちらも日本語に対応しています。
「音声から音声への翻訳」というニーズの場合は、Text Translation APIでは、別途、「音声」から「テキスト」への変換が必要になるため、断然、Speech Translation APIの方がお勧めとなるでしょう。
また、Speech Translation APIでは、入出力が「音声」になるだけでなく、入力(翻訳前)と出力(翻訳後)の内容を「テキスト」として取り出せるので、軽易に表示等に利用することもできます。
下図は、Speech Translation APIにおける処理の流れです。
https://www.microsoft.com/ja-jp/translator/speech.aspxより
今回は、このSpeech Translation API をiOS (Swift 3) で動作させて見ましたので、その紹介をさせて下さい。
最初に、作成したサンプルアプリを操作している様子です。下のセグメンテッドスイッチで、翻訳の言語を指定し、あとはボタンを押して話すだけです。
2 アプリの登録
Speech Translation APIを利用するためには、アプリの登録が必要です。
(1) リソ一スの作成
Microsoft Azureのポータルサイトにログインし、新規 > Intelligence + analytics > Cognitive Services APIs(プレビュー) とたどります。
Account name 、Resource group に、適当な名前を指定し、API typeでTranslator Speech APIを選択します。
なお、価格レベルについては、初めて利用する場合は、F0を選択すると、2時間/月まで無料で試すことができます。
https://azure.microsoft.com/ja-jp/pricing/details/cognitive-services/translator-speech-api/ より
(2) KEYの取得
すべてのリソース から、作成したリソースを選択します。
Keysを選択して表示されるKEY 1 及び KEY 2 が、次の認証トークンを取得する処理で必要になります。
3 認証トークン
Speech Translator API を呼び出すたびに認証トークンが必要です。
認証トークンは、パラメータ(Subscription-Key)に、先程のKEY (KEY 1若しくはKEY 2のどちらでも良い) を指定して取得できます。(有効期間は10分間)
下記は、認証トークンを取得している例です。
fileprivate var tokenString = "" func token(completionHandler: @escaping (String) -> Void) { if tokenString != "" { completionHandler(tokenString) } let key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" let url = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken?Subscription-Key=\(key)" let request = NSMutableURLRequest(url: NSURL(string: url)! as URL) request.httpMethod = "POST" let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {data, response, error in if (error == nil) { let str = String(data: data!, encoding: .utf8) if str != nil { self.tokenString = str! completionHandler(str!) } else { completionHandler("ERROR: Failed to convert to String") } } else { completionHandler("ERROR: \(error.debugDescription)" } }) task.resume() }
参考:Cognitive Services DocumentationAuthentication Token API
4 Starscream
Speech Translation APIのエンドポイントは、WebSocket で提供されています。SwiftでWebSocketを扱う場合、Starscreamというフレームワークがあり、これを利用させて頂くのが簡単でお薦めです。
Starscreamは、CocoaPodsで組み込み可能ですが、現在のmasterは、まだ、Swift 3.0 対応となっていません。
最新のXcode 8.3を利用する場合は、Siwft 3.1一択となってしまいますが、この場合、swift3というブランチが利用可能です。
pod 'Starscream',:git => 'https://github.com/daltoniam/Starscream', :branch => 'swift3'
5 APIの使い方
(1) エンドポイントへのアクセス
Speech Translation APIの基本的な使用例は、下記のとおりです。
GET wss://dev.microsofttranslator.com/speech/translate?from=en-US&to=it-IT&features=texttospeech&voice=it-IT-Elsa&api-version=1.0 Authorization: Bearer {access token} X-ClientTraceId: {GUID}
そして、これを、Starscreamフレームワークを利用してSwiftで記述すると、次のようになります。
let to = "en" let from = "ja" let features = "partial,texttospeech" let url = URL(string: "wss://dev.microsofttranslator.com/speech/translate?from=\(from)&to=\(to)&features=\(features)&api-version=1.0") socket = WebSocket(url: url!, protocols: nil) socket.headers["Authorization"] = "Bearer " + (tokenString as String) socket.headers["X-ClientTraceId"] = UUID.init().uuidString socket.delegate = self socket.connect()
ヘッダ Authorizationに設定しているのは、認証トークンです。パラメータ features に TextToSpeechを設定しておくと、翻訳後の音声も取得できます。
(2) オーディオ送信
翻訳したい音声データは、RIFFフォーマットでクライアントからサーバへ送信されますが、その内容は、RIFFヘッダ、fmtチャンク、dataチャンクの順で並んでいます。 最初にデータを生成するためのクラスとして、下記のようなものを作成しました。[UInt8]のバッファに文字列や数値を順に配置して、最後にDataで受け取るクラスです。
class Buffer { var offset = 0 var buffer: [UInt8] init(size: Int) { buffer = [UInt8](repeating : 0, count : size) } func append(short: Int16) { (0..<2).forEach { buffer[$0 + offset] = UInt8((Int(short) >> ($0 * 8)) & 0xff) } offset += 2 } func append(int: Int) { (0..<4).forEach { buffer[$0 + offset] = UInt8((int >> ($0 * 8)) & 0xff) } offset += 4 } func append(_ str: String) { str.utf8.enumerated().forEach { buffer[$0 + offset] = $1 } offset += str.utf8.count } var data: Data { return Data(bytes: buffer) } }
そして、上記のクラスを利用して、各チャンクを生成しているコードは下記のとおりです。
//Riff Chunk fileprivate func riff() -> Data { let size = 4 let buffer = Buffer(size: size + 8) buffer.append("RIFF") buffer.append(int: size) buffer.append("WAVE") return buffer.data } // Wave Format Chunk fileprivate func waveFormat() -> Data { let size = 16 let buffer = Buffer(size: size + 8) buffer.append("fmt ") buffer.append(int: size) buffer.append(short: 1) // Audio Format buffer.append(short: 1) // Channels buffer.append(int: 16000) // SamplePerSecond buffer.append(int: 32000) // BytesPerSecond buffer.append(short: 2) // BlockAlign buffer.append(short: 16) // BitsPerSample return buffer.data } // Wave Data Chunk (Header) fileprivate func dataHeader(count: Int) -> Data { let buffer = Buffer(size: 8) buffer.append("data") buffer.append(int: count) return buffer.data }
そして、サーバとの接続完了後に、これを送信しているコードです。
func websocketDidConnect(_ socket: WebSocket) { let channels = UnsafeBufferPointer(start: audioFileBuffer?.int16ChannelData, count: 1) let length = Int((audioFileBuffer?.frameCapacity)! * (audioFileBuffer?.format.streamDescription.pointee.mBytesPerFrame)!) let audioData = NSData(bytes: channels[0], length: length) if length > 50000 { // これ以下のサイズは、エラーとして送信しない socket.write(data: riff()) socket.write(data: waveFormat()) socket.write(data: dataHeader(count: length)) socket.write(data: audioData as Data) socket.write(data: Buffer(size: 100000).data) // 最後に、いくらかの0データを送る必要がある } else { socket.disconnect() } }
送受信処理は、StarscreamのWebSocketDelegateの各メソッドで実装しています。 コードを置きましたので、不明な点があればご参照ください。
[GitHub] https://github.com/furuya02/TranslatorSpeechAPISample
参考: Documentation Translation Speech API
6 最後に
今回は、Speech Translation APIについて、試してみましたが、非常に流暢で、かつ、優れていると実感しました。
時間を見つけて、Microsoftの Cognitive Services APIs の他の「認知」サービスも、色々試してみたいと思います。
7 参考リンク
最大100人まで同時通訳ーーMS、日本語の音声リアルタイム翻訳を提供開始
Microsoft 機械翻訳
Translator API を使い始める
Microsoft Translator のよくあるご質問
MicrosoftTranslator/InfoCenter-Speech-To-Speech-IOS-Swift
Microsoft Translator Documentation
Speech Translation API Document
StarScream
[iOS] 翻訳機能付Twitterクライアント
ios