LoginSignup
4
1
お題は不問!Qiita Engineer Festa 2023で記事投稿!

Windows端末+Slack+VOICEVOXによる音声読み上げ

Last updated at Posted at 2023-07-06

件名の通り、Windows端末でSlackのメッセージが書き込まれたらVOICEVOXで音声読み上げをやる記事です。
※記事はたくさん出てきたのですが、細かい内容の記載がなかったりしたので備忘録的に。。。
※前回同様、割と雑な記事ですみません。

1. Slack設定

以下のサイトを参考にさせていただきました。(Slackの設定はまんま下記の記事通りです)
https://dev.classmethod.jp/articles/slack-api-bolt-js-getting-start/

2. nodejsのインストール

下記サイトより推奨版をインストールしました。
https://nodejs.org/ja/

3. Visual Studioインストール(インストール後は再起動しましょう)

下記サイトを参考にインストールしました。
https://resanaplaza.com/visual-studio-2022-%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%89%8B%E9%A0%86/
※必ず「C++によるデスクトップ開発」ワークロードを選択してインストールしましょう。
C++.png

4. VOICEVOXインストール

下記サイトよりダウンロードしてインストールします。
https://voicevox.hiroshiba.jp/
※自分はGPU/CPU版をインストールしました。

5. VOICEVOX起動

GUIでもコマンドプロンプトでもどちらでも。
もし、別ノードからアクセスさせることを前提にするなら下記の通り実施。

cd AppData\Local\Programs\VOICEVOX
run.exe --host [ローカルIP]

6. ライブラリインストール

適当なフォルダを作成して、下記コマンドを実行

npm init
npm install @slack/bolt
npm install node-fetch@2.6.1
npm install speaker
npm install web-audio-api

7. コード実装(app.js)

const { App } = require('@slack/bolt');
const fetch = require('node-fetch');
const { AudioContext } = require('web-audio-api');
const context = new AudioContext();
const Speaker = require('speaker');

const app = new App({
  token: "xoxb-XXXXXXXXXXXXXXXXXXXX",       #自分が取得した値に置き換えてください
  signingSecret: "XXXXXXXXXXXXXXXXXXXX",    #自分が取得した値に置き換えてください
  socketMode: true,
  appToken: "xapp-XXXXXXXXXXXXXXXXXXXX",    #自分が取得した値に置き換えてください
  port: process.env.PORT || 3000
});

app.message(async ({ message }) => {
  // 読み上げたいメッセージを Slack から取得
  const msg = message.text;

  // メッセージが存在しない場合は処理を終了
  if (!msg) {
    return;
  }

  // クエリ作成
  const audio_query_response = await fetch(
    "http://xx.xx.xx.xx:50021/audio_query?text=" + encodeURIComponent(msg) + "&speaker=0",
    {
      method: 'post',
      headers: {'Content-Type': 'application/json'}
    }
  );
  const audio_query_json = await audio_query_response.json();

  // 音声合成
  const synthesis_response = await fetch(
    "http://xx.xx.xx.xx:50021/synthesis?speaker=0",
    {
      method: 'post',
      body: JSON.stringify(audio_query_json),
      headers: {"accept": "audio/wav", 'Content-Type': 'application/json'},
    }
  );
  const synthesis_response_buffer = await synthesis_response.buffer();

  // 再生
  context.outStream = new Speaker({
    channels: context.format.numberOfChannels,
    bitDepth: context.format.bitDepth,
    sampleRate: context.sampleRate
  });

  context.decodeAudioData(synthesis_response_buffer, function(audioBuffer) {
    // サンプルレートを一致させる
    const sourceSampleRate = audioBuffer.sampleRate;
    const destinationSampleRate = context.sampleRate;
    const ratio = sourceSampleRate / destinationSampleRate;
    const length = audioBuffer.length / ratio;
    const targetBuffer = context.createBuffer(
      audioBuffer.numberOfChannels,
      length,
      destinationSampleRate
    );

    for (let channel = 0; channel < audioBuffer.numberOfChannels; channel++) {
      const inputData = audioBuffer.getChannelData(channel);
      const outputData = targetBuffer.getChannelData(channel);

      for (let i = 0; i < length; i++) {
        const index = i * ratio;
        const floor = Math.floor(index);
        const ceil = Math.ceil(index);
        const fraction = index - floor;
        const value = inputData[floor] + (inputData[ceil] - inputData[floor]) * fraction;
        outputData[i] = value;
      }
    }

    var bufferNode = context.createBufferSource();
    bufferNode.connect(context.destination);
    bufferNode.buffer = targetBuffer;
    //bufferNode.loop = true;
    bufferNode.start(0);
  });

});

(async () => {
  // Start your app
  await app.start();

  console.log('⚡️ Bolt app is running!');
})();

8. アプリ起動

作成したアプリを起動します。

node app.js

9. Slackへメッセージ書き込み

1番の手順で、作成したアプリを参加させたチャネルでメッセージを書き込んでみてください。うまく動作すればスピーカーから音声が聞こえてきます。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1