AWSを使った「なろう」をPollyで朗読させる

niwanos.hatenablog.com

前回は「なろう」WebAPIを作りましたが、今回はAWSの読み上げサービスPollyで 取得したチャプターを読み上げた音声ファイルをS3に保存してみます。

aws.amazon.com

const axios = require('axios')
const cheerio = require('cheerio')
const SocksProxyAgent = require('socks-proxy-agent');
const bookBaseUrl = 'https://ncode.syosetu.com/';
const proxyHost = '*******';
const proxyPort = '****';
const proxyOptions = `socks5://${proxyHost}:${proxyPort}`;
const httpsAgent = new SocksProxyAgent(proxyOptions);
const AWS = require("aws-sdk");
AWS.config.update({
  region: '*'
});
const S3 = new AWS.S3();
const Polly = new AWS.Polly();

let response;
/**
 *
 * Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
 * @param {Object} event - API Gateway Lambda Proxy Input Format
 *
 * Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
 * @param {Object} context
 *
 * Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
 * @returns {Object} object - API Gateway Lambda Proxy Output Format
 *
 */
exports.lambdaHandler = async (event, context) => {
    try {
        let bookId = event.pathParameters.bookId;
        let chapterId = event.pathParameters.chapterId;
        let chapter = await exports.getChapter(bookId, chapterId);

        let text = chapter.title + '\n\n' + chapter.contents.join('\n');

        const pollyParams = {
          OutputFormat: 'mp3',
          Text: text,
          VoiceId: 'Mizuki',
          TextType: 'text'
        };

        let data = await Polly.synthesizeSpeech(pollyParams).promise();

        var s3Params = {
          Bucket: '******', 
          Key: `${bookChapterId}.mp3`,
          Body: new Buffer(data.AudioStream)
        };

        // s3にputする
        let s3Resp = await S3.putObject(s3Params).promise();

        response = {
            'statusCode': 200,
            'body': JSON.stringify({
                'message': "ok"
            }),
            'headers': {
                'Access-Control-Allow-Origin': '*'
            }
        }
    } catch (err) {
        console.log(err);
        return err;
    }

    return response
};

exports.getChapter = async (bookId, chapterId)=> {
  const url = exports.makeChapterUrl(bookId, chapterId);
  let resp = await axios.get(url, {httpsAgent: httpsAgent});
  const $ = cheerio.load(resp.data);
  let title = $('p.novel_subtitle').text();
  let contents = [];

  for(let i = 1; ; i++ ){
    if ($(`#L${i}`).length == 0){
      break;
    }
    contents.push($(`#L${i}`).text());
  }
  return {
    title: title,
    contents: contents
  };
}

exports.makeChapterUrl = (bookId, chapterId)=> {
  return `${bookBaseUrl}${bookId}/${chapterId}/`;
}

結果

https://d2daztqdssi217.cloudfront.net/n7975cr_1.mp3

ラノベを読み上げる音声、なかなか斬新

参考文献 www.yamamanx.com

qiita.com