
シェア:
ベンはセカンドキャリアの開発者で、以前は成人教育、コミュニティ組織化、非営利団体運営の分野で10年を過ごした。彼はVonageの開発者支援者として働いていた。コミュニティ開発とテクノロジーの交差点について定期的に執筆している。南カリフォルニア出身で、長年ニューヨークに住んでいたが、現在はイスラエルのテルアビブ近郊に在住。
Vonage Voice API WebSocketを使ってRubyで通話を録音する
所要時間:2 分
Vonage音声API Vonage Voice API ウェブソケット機能は最近ベータ版から一般版になりました。WebSocketsを使用すると、単一の永続的なTCP接続を介して双方向通信を作成することができます。WebSocketでは、複数のHTTPリクエストとレスポンスを処理する必要はありません。1つのWebSocket接続を開くだけで、テキストとバイナリのデータ通信を継続的に行うことができます。
WebSocketはHTTPレスポンスとリクエストのサイクルを簡素化できるが、アプリケーションを構築するには異なるパラダイムだ。ありがたいことに、一般的に使用されているプログラミング言語にはWebSocketツールがあり、プロセスの複雑さを軽減してくれる。
このチュートリアルでは、RubyでWebSocketを扱う小さなWebサーバーを構築します。このサーバーは、着信する音声通話、WebSocket接続を処理し、HTMLをレンダリングします。使用するのは Rackをウェブインターフェースとして使用し Thinを使用します。このチュートリアルでは、WebSocket の扱いに関する既存の知識は必要ありませんが、Ruby で Web サーバーを扱った軽い経験があることを前提としています。
tl;dr もしスキップしてアプリだけを実行したいのであれば、完全に動作するバージョンを GitHub.
前提条件
このチュートリアルでは、Ruby v2.7以上がマシンにインストールされている必要があります。また、このアプリケーションではいくつかのgemが使用されます。それぞれは後で作成する Gemfileに記載されており、コマンドラインから bundle installを実行することでインストールされます:
これでアプリケーションの実装に取りかかることができる。
Vonage API アカウント
Vonage API Account
To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.
このチュートリアルではバーチャル電話番号も使用します。購入するには 電話番号 > 電話番号の購入 番号を購入するにアクセスし、ニーズに合ったものを検索してください。
APIアカウントを設定する最後のステップは、Voice API Applicationを作成することです。プロビジョニングしたバーチャル電話番号をこのアプリケーションにリンクし、WebhookのURLを設定する。
Vonage API Dashboardから次の場所に移動します。 アプリケーションをクリックし 新しいアプリケーションを作成する.次のページが表示されます:
Dashboard Create Application
アプリケーションを作成するために重視すべき点は、紫色で強調表示されています:
名前アプリケーションに任意の名前を付けることができます。
公開鍵と秘密鍵:認証用の公開鍵と秘密鍵のペアを生成します。秘密鍵ファイルがあなたのマシンにダウンロードされます。私たちのアプリケーションは着信音声通話を処理するだけなので、この鍵で何かをする必要はありません。
機能:各アプリケーションは複数の機能を扱うことができる。今回の目的では、以下の機能をオンにするだけです。 Voice.
オプションの入力が終わったら 新規アプリケーションの作成ボタンを押して終了します。
アプリケーションが作成されたので、それを新しくプロビジョニングされた電話番号にリンクし、ウェブフックURLを設定しましょう。
前と同じように アプリケーションに移動し、アプリケーション名の横の楕円をクリックして 編集リンクをクリックします。
社内 機能セクションに以下のオプションが表示されます:
Application Webhook URL settings
を記入する必要があります。 イベントURLと 回答URL.前者は、Vonageが音声通話のすべてのイベントライフサイクルデータを送信する場所です。後者は、Vonageが新しい音声通話を開始するたびに送信する場所です。ここで提供されるURLは、Vonageが到達できるように、外部からアクセスできる必要があります。つまり localhostを使用することはできません。一般的な開発オプションはngrokで、以下のチュートリアルに従ってください。 チュートリアルを参照してください。
イベントURLとアンサーURLの末尾に /webhooks/eventと /webhooks/answerで終わることを確認してください。
また、Vonageの電話番号をこのアプリケーションに接続する必要があります。そのためには 番号>自分の番号に移動し、電話番号の横にある鉛筆のアイコンをクリックします。そしてオプションから新しいアプリケーションを選択し、電話番号をリンクさせます。保存 保存をクリックすると、この番号への着信はすべてあなたのアプリケーションに転送されます。
フォルダ構造の作成
Vonage APIアカウントと設定の準備ができたので、アプリケーションのフォルダ構造を作成しましょう。最終的には以下のようになります:
.
+-- recordings/
+-- views/
| +-- index.html.erb
+-- app.rb
+-- Gemfileアプリケーションのルートフォルダには app.rbが含まれ、これが音声通話の着信とWebSocket接続を処理するWebサーバーになります。また Gemfileここには依存関係を定義します。さらに2つのフォルダがあります: recordings/と views/.と. recordings/フォルダには Voice API WebSockets 接続からの通話記録が保存されます。.フォルダは、アプリケーションの1つのビューを保存する場所です。 views/フォルダは、アプリケーションの1つのビューを保存する場所です。
依存関係の定義
の中に Gemfileに、アプリケーションで使用する以下のgemを追加する:
source 'https://rubygems.org'
gem 'wavefile'
gem 'faye-websocket'
gem 'json'
gem 'rack'
gem 'thin'それぞれの宝石は特定の機能を果たす:
Wavefile:このgemを使って、生のオーディオデータをWAVファイルに変換します。
Faye: このgemを使ってWebSockets接続を処理します。
JSON: このgemは、Vonage Voice APIに送り返す通話命令をJSONに変換するために使用されます。
Rack: ウェブ・フレームワークとして Rack を使用します。
薄い:このgemは、Rackの上にWebサーバを提供します。
コマンドラインから bundle installをコマンドラインから実行することで、これらのgemをすべてアプリケーションで利用できるようになります。
サーバーの構築
依存関係と変数の定義
これでウェブ・サーバーを構築する準備が整った。サーバーの構築で最初にすることは、いくつかの requireと includeステートメントを追加することです:
require 'rack'
require 'erb'
require 'faye/websocket'
require 'json'
require "wavefile"
include Rack
include WaveFileこの時点で、WebSockets接続リクエストの外部アクセス可能なURLと等しい定数変数も定義します。このURLは、Vonage Voice APIに新しいコールを受信したときに送り返す命令で使用します:
EXTERNAL_WS_URL = 'ws://example.com/cable'上記のスニペットの example.comを外部からアクセス可能なURLに置き換えてください。
ヘルパーメソッド
このアプリケーションでは、2つのヘルパー・メソッドを利用する。今すぐ作成して、定数変数宣言の後に追加すればいい。
最初の方法です、 #create_wav_fileは、WebSocketを通じて受信したバイナリオーディオデータをWAVファイルに変換するプロセスを支援します。Wavefile gemの機能を利用してWAVファイルを作成し、後でアプリケーションで使用するファイル名を返します:
def create_wav_file(data, file_name)
buffer = Buffer.new(data, Format.new(:mono, :pcm_16, 16000))
puts "Audio Buffer Created..."
writer = Writer.new(file_name, Format.new(:mono, :pcm_16, 16000))
puts "New Audio File Created..."
puts "Writing to the Buffer..."
writer.write(buffer)
puts "Closing Buffer Writing..."
writer.close
puts "WAV File Created..."
file_name
end上記のメソッドは、入力される音声が monoソースではなく stereoソースからのものであることを指定します。違いは、データの配列の配列ではなく、バイナリデータのフラットな配列で定義された単一のオーディオトラックがあることです。オーディオは pcm_16これはソースがリニアPCM 16ビットであることを意味する。最後に、ソースは 16000これはサンプルレートが16KHzであることを意味する。新しいWAVファイルは、オーディオ・バイナリ・ソース・データと同じオーディオ設定で作成されます。
番目のメソッド、 #erbは、ERBテンプレート・ファイルをユーザーにレンダリングするために使う短いメソッドである:
def erb(template)
path = File.expand_path("#{template}")
ERB.new(File.read(path)).result(binding)
end残りのコードは、一連の mapステートメントで構成される。 Rack::Handlerミドルウェアにラップされます。
ルートの定義
アプリケーションのルートは、RackとThinをつなぐRackミドルウェアの内部で定義する必要があります。また Rack::Staticミドルウェアを使います。Faye WebSocketハンドラもここで初期化します:
Rack::Handler::Thin.run(Rack::Builder.new {
Faye::WebSocket.load_adapter('thin')
use(Rack::Static, urls: ["/recording"], root: 'recording')次の4つのルートを構築する必要がある。 mapステートメントを構築する必要があります: /cable, /, /webhooks/answerそして /webhooks/answer.では、それをやってみよう。
最初のルートはWebSocket接続を処理する:
map('/cable') do
run(->env{
if Faye::WebSocket.websocket?(env)
puts "WebSockets connection opened..."
@call_data = []
ws = Faye::WebSocket.new(env)
ws.on :message do |event|
if event.data.is_a?(Array)
@call_data.append(event.data.pack('c*').unpack('s*'))
else
puts event.data
end
end
ws.on :close do |event|
puts 'WebSocket connection closed...'
create_wav_file(@call_data.flatten, 'recording/recording.wav')
end
ws.rack_response
end
})
end
上記のルートでは、接続リクエストがWebSocketリクエストかどうかをチェックする。もしそうであれば、新しい Faye::WebSocket.WebSocketに送信されるデータには、テキストデータとバイナリデータの2種類があります。後者は常にバイトサイズの整数を配列にした形で送信されます。
このように event.dataが配列オブジェクトかどうかをチェックすることができる。配列であれば、WAVファイルの作成に使用するバイナリ音声データであることがわかる。そうでない場合は、Vonage Voice API からのステータス更新である。この場合は、コンソールにログを記録します。
重要な注意点があります:Faye WebSockets gemは、上で述べたようにバイナリデータをバイトサイズの整数に変換します。しかしこれは、正確に1バイトまたは8ビットサイズの整数に変換することを意味します。Vonage Voice APIは音声のバイナリデータを16ビット整数で送信する。つまり、アプリケーションは8ビットのバイナリ・データを16ビットに変換する必要がある。Ruby標準ライブラリの #packと #unpackインスタンス変数 @call_dataインスタンス変数に追加します。これは、理解しやすい音声を生成するために必要なステップです。
次のルートは indexビューを提供します。ファイルがあるかどうかをチェックし、ファイルがあればインスタンス変数でそれをビューに渡します:
map('/') do
if File.exist?('recording.wav')
@call_status = 'Audio Loaded!'
@file = 'recording.wav'
end
run(->env{
[200, { 'Content-Type' => 'text/html'}, [erb("views/index.html.erb")]]})
end
この /webhooks/answerルートは Vonage Voice API に特化した NCCO (Nexmo Call Control Object) と呼ばれる命令を返します。 NCCO (Nexmo Call Control Object)と呼ばれる特別な命令を返します。JSONとして送り返す命令は、Voice APIにWebSocket接続を開きたいことを伝え、接続を開始するためのWebSocket URLを提供します。また、Voice API には、発信者に短いメッセージを話し、まもなく通話がストリーミングされることを知らせたいことも伝えます:
map('/webhooks/answer') do
run(->env{
ncco = [
{
"action": "talk",
"text": "You will be streaming momentarily."
},
{
"action": "connect",
"endpoint": [
{
"type": "websocket",
"uri": "#{EXTERNAL_WS_URL}",
"content-type": "audio/l16;rate=16000",
}
]
}
].to_json
[200, { 'Content-Type' => 'application/json' }, [ncco]]
})
end
最後に作成するルートは、Voice APIがアプリケーションに送信するコールのイベントライフサイクルデータを処理します。私たちはこのデータに対して何もしたくありません。 200ステータスコード
map('/webhooks/event') do
run(->env{
[200, { 'Content-Type' => 'text/html'}, ['']]
})
end
最後に Rack::Builderブロックを閉じる:
}, Port: 9292)アプリケーションを実行する前に作成しなければならない最後の項目は、ビューです。
ビューの作成
このアプリケーションには1つのビューしかありません。このビューにはアプリケーションのルートURL、つまり localhost:9292もしくは 127.0.0.1:9292.このビューは、再生するオーディオを <audio>要素で表示します:
<html>
<head>
<title>Ruby Vonage WebSockets Demo</title>
</head>
<body>
<h1>Vonage WebSockets + Ruby == ♥</h1>
<p>Welcome to the Vonage WebSockets demo in Ruby</p>
<h2>Your Audio To Playback</h2>
<p>Once you have finished your call, your audio will be available to playback from here.</p>
<div id="audio-status">
<%= @call_status %>
<br />
<% if @file %>
<audio
controls
src="recording/<%= @file %>">
Your browser does not support the
<code>audio</code> element.
</audio>
<% end %>
</div>
</body>
</html>
ビューはルートで作成したインスタンス変数を使って <audio>要素を表示するかどうかを決定します。
これでアプリケーションを実行する準備ができた!
アプリケーションの実行
これでアプリケーションを実行する準備が整いました。実行するには、アプリのルート・フォルダーでコマンドラインから以下を実行する:
また、ngrokや同様のツールを使って、ウェブサーバーが外部からアクセス可能であることを確認することも忘れずに。
この時点で、Vonageバーチャル電話番号に電話をかけて、アプリケーションに電話をかけます。話し終わったら、電話を切ることができます。ウェブブラウザでアプリにアクセスすると、オーディオプレーヤーが表示され、録音した音声が再生されます。おめでとうございます!
さらに読む
このチュートリアルでは、Vonage Voice API の WebSockets 機能を Ruby で使えるようにするための基本的な機能を紹介しました。この機能でできることはまだまだたくさんあります。Vonage Voice API WebSockets についてもっと知りたい方は、以下をご覧ください:
