AWS Lambdaで音声合成(OpenJTalk)&エンコード(ffmpeg)

  • 6
    Like
  • 0
    Comment

探求室の@junya108です。
HameeAdventCalendar2016の21日目です。
AmazonDashButtonを買ったのでボタンを押したら電気、エアコン、テレビetc.が全部つくボタンの記事にしようと思ってたけど、変更。
先日、リリースされたAmazon Pollyを試して感じた問題点を解決してみたいと思います。

Amazon Pollyの問題点

喋りも滑らかで日本語にも対応している点は非常に良いのですが、声色がイマイチ。

解決策

lambda上で音声合成やエンコードをやって声色の自由度を増やしてみようと思います。

やることのまとめ

今回は音声合成にはopenjtalk、エンコードにはffmpegを利用します。
これをamazon linuxでコンパイルしてlambdaにアップロードしてテスト実行。という感じです。

音声合成

macを新調したばかりでdockerが入ってなかったので、まずは、docker for macをインストール。

amazonlinuxのイメージをpullしてrun。
lambdaの実行環境よりもdockerイメージが新しいけど大丈夫かな。

$ docker pull amazonlinux:2016.09
$ docker run -i -t amazonlinux:2016.09 /bin/bash

パッケージをupdateして、必要なライブラリをinstall。

bash-4.2# yum update -y
bash-4.2# yum install gcc44 gcc-c++ libgcc44 cmake wget git aws-cli autoconf automake libtool npm epel-release yasm -y

hts_engine_APIをコンパイル&インストール

bash-4.2# cd /tmp
bash-4.2# wget http://downloads.sourceforge.net/hts-engine/hts_engine_API-1.08.tar.gz
bash-4.2# tar zxvf hts_engine_API-1.08.tar.gz
bash-4.2# cd hts_engine_API-1.08
bash-4.2# ./configure
bash-4.2# make
bash-4.2# make install

OpenJTalkをコンパイル&インストール

bash-4.2# wget http://downloads.sourceforge.net/open-jtalk/open_jtalk-1.07.tar.gz
bash-4.2# tar zxvf open_jtalk-1.07.tar.gz
bash-4.2# cd open_jtalk-1.07
bash-4.2# ./configure --with-charset=UTF-8
bash-4.2# make
bash-4.2# make install

エンコード

必要なコーデックをinstall

bash-4.2# mkdir /usr/local/src/ffmpeg_sources
bash-4.2# cd /usr/local/src/ffmpeg_sources
bash-4.2# git clone --depth 1 git://git.code.sf.net/p/opencore-amr/fdk-aac
bash-4.2# cd fdk-aac
bash-4.2# autoreconf -fiv
bash-4.2# ./configure --prefix="/usr/local/src/ffmpeg_build" --disable-shared
bash-4.2# make
bash-4.2# make install

ffmpegをコンパイル&インストール

bash-4.2# cd /usr/local/src/ffmpeg_sources
bash-4.2# git clone --depth 1 git://source.ffmpeg.org/ffmpeg
bash-4.2# cd ffmpeg
bash-4.2# PKG_CONFIG_PATH="/usr/local/src/ffmpeg_build/lib/pkgconfig" ./configure --enable-static --disable-shared --prefix="/usr/local/src/ffmpeg_build" --extra-cflags="-I/usr/local/src/ffmpeg_build/include" --extra-ldflags="-L/usr/local/src/ffmpeg_build/lib" --bindir="/usr/local/src/bin" --enable-gpl --enable-nonfree --enable-libfdk_aac
bash-4.2# make
bash-4.2# make install

lambdaで動かしてみる

テストでテキストを音声変換して、aacにエンコードしてS3に保存して見る。

exports.js
var AWS = require('aws-sdk');
var s3 = new AWS.S3({apiVersion: '2006-03-01'});
var https = require('https');
var fs = require('fs');
var OpenJTalk = require('openjtalk');

exports.myHandler = function(event, context, callback) {

  var voice = new OpenJTalk({htsvoice: './node_modules/openjtalk/voice/mei/mei_happy.htsvoice'});

  voice._makeWav('未来はいつも面白い。',0,function(err,result){

    var cmd = './ffmpeg -i "' + '/tmp/'+result.wav + '" -vn -ac 2 -ar 44100 -ab 128k -acodec libfdk_aac -f mp4 "'+ '/tmp/'+result.wav +'.m4a"';
    var exec = require('child_process').exec;
    var child = exec(cmd, function(error, stdout, stderr) {

      var audioFileName=result.wav + '.m4a';
      var s3Params = {
        ACL: 'public-read',
        Bucket: {BUCKET_NAME},
        Key: audioFileName,
        Body: new Buffer(fs.readFileSync('/tmp/'+audioFileName))
      };

      s3.putObject(s3Params, function(err, data) {
        callback(null, 'Success!');
      };

    });

  });

};

これと、node_modulesとコンパイルしたopenjtalk,ffmpegをzipでまとめる。
ここで問題発生。。ファイルサイズが60M超。。
lambdaの制限によると、lambdaで動かせるのはzipのサイズは50Mまで。
削減できそうなファイルを整理してもまだ50M超えてる。。
とりあえず、制限超えてるけど、S3にアップロードしてlambdaに登録して見る。
なんと!
怒られない、登録できちゃう。
テストしてみてちゃんとS3にファイルが作成されることを確認。

スクリーンショット 2016-12-21 7.54.33.jpg

まとめ

  • ちゃんと動いた。
  • メモリが128Mのlambda環境で50文字(150byte)を変換して音声合成で5000msec,エンコードで1200msecぐらい。
  • 計算上はAmazon Pollyよりも安い。
  • zipサイズが50M超えてもアップロード出来ちゃう。
This post is the No.21 article of Hamee Advent Calendar 2016