Twilioブログ

TwilioとAmiVoiceを利用して通話の内容を音声認識させる方法

こんにちは、Twilioマーケ部のkatsu.tです。

本記事では、音声認識市場シェアNo.1の「AmiVoice Cloud Platform」とTwilioを連携させて、通話内容を音声認識させる方法をご紹介いたします。

目次

AmiVoiceについて

Twilioで通話音声を取得する方法

TwilioとAmiVoice Cloud Platformを利用して通話内容を音声認識させる方法

AmiVoiceについて

「AmiVoice」は20年以上のノウハウ・データが蓄積された、高精度かつ高速の音声認識エンジンです。「日本語」や「専門用語」に強く、ビジネスシーンや専門性の高い作業現場など幅広いシーンで活用されています。

エンジンには最新のディープラーニング技術や、双方向型のディープラーニング技術「Bi-LSTM(Bidirectional Long Short-Term Memory)」を実装しています。これにより従来の音声認識エンジンと比較して、エラー改善率が最大25%向上しました。
優れた音響モデルと言語モデルを用い、話した言葉をリアルタイムにテキスト化します。

(※アドバンスト・メディア様サイトより)

Twilioで通話音声を取得する方法

Twilioで通話音声を取得する方法として、「通話を録音する」「音声ストリームを取得する」の2通りが挙げられます。

本章では、それぞれの方法で通話音声を取得する方法をご紹介いたします

①通話音声を録音する

Twilioで通話を録音するには、下記2通りの手段を用いることができます。

  • TwiMLを利用する
  • Twilio Studioを利用する

ここでは、それぞれの利用方法についてご紹介いたします。

TwiMLを利用する場合

TwilioのRecord動詞を利用して通話音声を録音する方法です。

最もシンプルな利用例

<Response>
    <Record/>
</Response>

※録音開始後にTwiMLを利用したい場合は、actionパラメータの後続に続くTwiMLを返すURLを設定してください。

また発信時に録音する場合は、recordパラメータにtrueを設定することで通話内容を録音できます。

 

const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const client = require('twilio')(accountSid, authToken);

client.calls
      .create({
         twiml: 'Ahoy there!',
         to: '+819012345678',
         from: '+1512345678',
         record: true
       })
      .then(call => console.log(call.sid));

そのほか、オプションでRecord動詞のtranscribe属性をtrueに設定しておけば、録音された通話音声をテキスト化することも可能です。

Twilio Studioを利用する場合

Twilio Studioを利用して録音する場合、転送した通話を録音する際はCall Recording ウィジェット、留守番電話のように一方的な音声を録音する際はRecord Voicemailウィジェットを利用します。

※Call RecordingウィジェットはTriggerウィジェットに直接つなぐことはできません。音声を録音する旨を音声として流し、その後Call Recordingウィジェットを接続しましょう。

Studioを利用する場合

②音声ストリームを取得する

Twilioでは、通話音声ストリームをリアルタイムに取り出してやり取りできるMedia Streamsを提供しています。これによりDialogflowやAmazon Lexなどと連携し、電話を利用した音声ボットを作成することも可能です。

音声ボットやリアルタイム音声認識など、さまざまなサンプルが公開されています。ご興味のある方はぜひご参照ください。

Media Streamsを利用する場合は、下記TwiMLを利用し、接続先のWebSocketのURLを指定します。

<Response>
   <Start>
       <Stream url="wss://mystream.ngrok.io/audiostream" />
   </Start>
</Response>

TwilioとAmiVoice Cloud Platformを利用して通話内容を音声認識させる方法

「AmiVoice Cloud Platform」における音声認識の方法は2種類あります。

  • HTTPリクエストで音声ファイルを音声認識する
  • Websocketを利用してリアルタイムに音声データを音声認識する

Twilioでは前述の「音声通話を録音する方法」を用いて作成した録音ファイルを音声認識する方法と、MediaStreamsを利用してWebsocket経由でリアルタイムに音声データを音声認識する方法のどちらも利用できます。

ここでは、それぞれの文字起こし方法について詳しくご説明いたします。

方法①:録音ファイルを音声認識

TwiMLとTwilio Studioのどちらを利用する場合でも、音声認識するためのコードは共通して利用できます。

どちらも録音終了後のステータスコールバックを受け取ることができ、このコールバックのパラメータに音声ファイルへのリンクURLが含まれます。
そのリンクURLをAmiVoice側に渡すことで、対象の音声ファイルを音声認識できます。

ステータスコールバックの設定方法

TwiML

TwiMLを利用する際はrecordingStatusCallbackにURLを設定することで、コールバックを受け取ることができます。
※他のパラメータや詳細についてはこちらをご覧ください。

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Record recordingStatusCallback="your url" />
</Response>
Twilio Studio

Twilio Studioを利用する際は、ウィジェットのRecording Status Callback欄にコールバックさせたいURLを設定します。

Studioのウィジェット

サンプルコード

本記事では、Twilio Functionsを利用したコード例を記載します。
※Twilio Functionsでは長時間の処理をおこなえません。音声ファイルが大きい場合は別のサービスをご利用ください。
※AmiVoiceのAPI仕様はこちらをご参照ください。

// 必要なライブラリをインポート
var Axios = require('axios');
var Fs = require('fs');
const FormData = require("form-data");
// main処理
exports.handler = async function(context, event, callback) {
  const filePath = await download(event.RecordingUrl);
  // APIキーは事前に環境変数に設定してください。
  const result = await postToAmivoice(filePath,context.AMIVOICE_API_KEY);
  console.log(result.text);
  callback(null,result);
};

// Twilioの録音ファイルをファイルに一時保存
async function download(url) {
  return new Promise(async (resolve, reject) => {
    try {
      const tmp_file = require('os').tmpdir() + '/tmp.wav';

      const writer = Fs.createWriteStream(tmp_file);

      const response = await Axios({
        url:url,
        method: 'GET',
        responseType: 'stream'
      })

      response.data.pipe(writer);
    
      writer.on('finish', resolve(tmp_file))
      writer.on('error', reject)
    } catch(error) {
      reject(error);
    }
  })

}

// 音声ファイルをAmiVoiceへ投げて音声認識を行う
async function postToAmivoice(filePath,apikey) {
  return new Promise(async (resolve, reject) => {
    try {
      const amivoiceUri = 'https://acp-api.amivoice.com/v1/recognize?d=-a-general&c=8k&u=' + apikey;
    
      const data = new FormData();
      data.append('a',Fs.createReadStream(filePath));

      const response = await Axios({
        url: amivoiceUri,
        method: 'POST',
        headers: {
          "Content-Type": data.getHeaders(),
        },
        data:data
      })

      console.log(response.data);
      resolve(response.data);
    } catch(error) {
      reject(error)
    }
  })
}

通話内容をリアルタイム音声認識

AmiVoiceではリアルタイムでも音声認識できるよう、Websocketを用いた方法も提供されています。
TwilioのMedia Streamsで取得した音声ストリームをWebsocketを利用してAmiVoiceへ流すことで、リアルタイムに音声認識をおこなえます。

本記事ではMedia Streamsに設定するURLのソースコードの例をご紹介いたします。
※コードのAmiVoiceにデータを連携する部分をご紹介いたします。
Media Streamsとの連携の全コードはこちらをご参照ください。

~~中略~~

connect() {
        if (!this.isReady) {
            const client = new WebSocketClient();

            client.on('connectFailed', error => {
                console.log('Connect Error: ' + error.toString());
                this.isReady = false;
            });

            client.on('connect', connection => {
                this.connection = connection;
                console.log('amivoice connected');

                connection.on('message', message => {
                    if (message.type === 'utf8') {
                        const tag = message.utf8Data.charAt(0);
                        if (tag == 's') {
                            // 認識スタート
                            console.log('amiVoice started.');
                            this.isStarted = true;
                        } else if (tag === 'S') {
                            // サーバ内で発話区間の先頭が検出された S 
                        } else if (tag === 'E') {
                            // サーバ内で発話区間の終端が検出された E 
                        } else if (tag === 'C') {
                            // サーバ内で検出した発話区間に対する認識処理が開始された
                        } else if (tag === 'U') {
                            // サーバ内で検出した発話区間に対する認識処理中に、認識途中結果を知らせる
                            const data = JSON.parse(message.utf8Data.substring(2));
                            console.log('認識中 track:' + this.track + ' message:' + data.text);
                        } else if (tag === 'A') {
                            // 認識処理が完了し、認識結果が受容されたとき
                            const data = JSON.parse(message.utf8Data.substring(2));
                            console.log('確定  track:' + this.track + ' message:' + data.text);
                            this.emit('transcription', {track:this.track,body:data});
                        } else if (tag === 'G') {
                            // サーバ内で生成されたアクション情報 ※このイベントは無視する
                            //https://acp.amivoice.com/main/manual/g-%e3%82%a4%e3%83%99%e3%83%b3%e3%83%88%e3%83%91%e3%82%b1%e3%83%83%e3%83%88/
                        } else if (tag == 'e') {
                            this.isStarted = false;
                            console.log('amiVoice closed.');
                        }
                    }
                });
                
                connection.on('error', error => {
                    console.log("Connection Error: " + error.toString());
                });
                
                connection.on('close', () => {
                    this.isStarted = false;
                    this.isReady = false;
                    console.log('echo-protocol Connection Closed');
                });
                
                this.isReady = true;
                this.start();
            });

            client.connect('wss://acp-api.amivoice.com/v1/');
        }
    }
    ~~中略~~

 

 

まとめ

本記事ではTwilioで音声を録音する方法と、録音した音声をAmiVoiceに連携して音声認識させる方法をご紹介させていただきました。

TwilioとAmiVoiceを活用することで、簡単に電話の通話内容をテキスト化できます。
通話音声を音声認識させたい!という方はぜひ、TwilioとAmiVoiceの利用をご検討ください。

アプリケーションエンジニア 葛 智紀
アプリケーションエンジニア 葛 智紀

前職でiOS、Androidのネイティブアプリケーション開発、AngularやLaravelを用いたウェブアプリケーション開発に従事。KDDIウェブコミュニケーションズではTwilioの最新情報の発信やTwilioを用いた地域課題解決を担当。 個人では、Google Developer Group Tokyoのオーガナイザーを務める。

お問い合わせはこちら

Share!!

  • お役立ち情報
  • イベント情報
  • 相談会申込
  • 導入事例