設計原則をデザインパターンで考える

はじめに

こちらは Voicy Advent Calendar 2021 13日目の記事です。

はじめまして、株式会社Voicyでバックエンドエンジニアをしているなだまるです。

みなさん、設計してますか? 「設計」っていうと難しいこと考えがちですが、普遍的に言われていることを組み合わせてみてみると、あ、こんなもんかと思ったりします。

今回はそんなアプリケーションの設計に関するお話をしてみます。

設計の原則

広く知られる設計の原則として、SOLID原則があります。

この原則の目的は主に以下のような性質を持つ中間レベルのソフトウェア構造を作ることです。

  • 変更に強いこと
  • 理解しやすいこと
  • コンポーネントの基盤として、多くのソフトウェア・システムを利用できること

SOLID原則は以下の各原則の頭文字をとってSOLIDです。 今回は各原則について詳しくは記述しませんが、軽く紹介までに。

  • Single Responsibility Principle(単一責任の原則)
  • Open-Closed Principle(オープン・クローズドの原則)
  • Liskov Substitution Principle(リスコフの置換原則)
  • Interface Segregation Principle(インターフェイス分離の原則)
  • Dependency Inversion Principle (依存関係逆転の原則)

これらだけ読んでも「ほうほう」くらいはなるんですが、具体イメージは湧きづらいですよね。

デザインパターンと合わせて考える

ここで言うデザインパターンGoFデザインパターンを指します。 デザインパターンは23種あり、よく出会う問題とそれに対処する良い設計としてまとめらた指針のようなものです。 こちらの各パターンの紹介も今回は割愛しますが、前半で紹介した原則と合わせて理解することで、どういったところに肝があるのかを掴みやすくなります。

本記事はこの部分を扱います。 説明にクラスと言う言葉を使いますが、便宜上そうしているだけでモジュール等の一定の実装のかたまりの意味合いで捉えてください。

単一責任の原則とFacadeパターン

単一責任の原則はざっくり言うと「モジュールを変更する理由はひとつにすべきだ」というヤツで、ユースケースのアクターが異なるのであればコードは分割しましょうねということです。

Facadeパターンはモジュールの窓口を担う、システムの外側に対するシンプルなAPIを提供するパターンで、クラス図にすると以下のようなものです。

f:id:natacon:20211213223702p:plain
Facadeパターン

Facade パターン - Wikipedia

実装コードを扱うクラスがあったとして、それぞれアクターが異なるメソッドが実装されているとします。(例が雑でごめんなさい) implement()は実装者、review()はレビューする人、release()はシステム管理者が行うとします。 このままだとどういうユースケースの変更であったとしてもCodeクラスを変更することになります。

f:id:natacon:20211213223845p:plain

アクターが異なることがわかっているので、アクターごとにクラスを分けてます。

f:id:natacon:20211213223956p:plain

分けたら分けたで、利用者側からは3つのクラスを意識して上手に使ってあげないといけなくなります。 それは使いにくいので窓口としてFacadeクラスを配置します。

f:id:natacon:20211213224014p:plain

こうすることにより、実装者にかかわる変更はImplementerのみを変更すれば良くなり他のアクターのケースは影響を受けません(関数のシグネチャーが変更される場合などはFacadeも変更対象になります)。

このように、Facadeパターンを通じて、ユースケースのアクターごとに変更すべきクラスを分けることができ、かつ理解もしやすくすることができます。

依存関係逆転の原則とAbstract Factoryパターン

依存関係逆転の原則は、ソースコードの依存関係を抽象だけを参照するようにして、その名の通り依存関係を逆転させるヤツです。抽象クラスやインターフェイスに依存しましょうってことですね。

Abstract Factoryパターンは直訳すると「抽象的な工場」で、これだけだと意味が分かりづらいですが、工場で生産する部品の具体には触れず、インターフェイスだけを使って部品を組み立て製品にまとめようぜというヤツです。APIを定義するイメージですね。クラス図で表すと以下のようになります。

f:id:natacon:20211213224045p:plain
Abstract Factoryパターン
Abstract Factory パターン - Wikipedia

上側がAPIになっていて、下側に詳細の実装が配置されています。

ClientはProduct1のインターフェイス経由でConcreteProduct1を使用します。 Product1はAbstractFactoryインターフェイス経由ででProduct1を生成します。 このとき、AbstractFactoryの実装はConcreteFactoryで実装されていて、この実装がConcreteProduct1のインスタンスを戻す形になっている。

真ん中にアーキテクチャの境界を意味するものとして一本線を引いてみると見通しが良くなります。

f:id:natacon:20211213224137p:plain

この線を横切る依存性はすべて具象側から抽象側に向かっています。 この曲線を横切る処理の流れは、依存性とは逆向きになるため「依存関係逆転」と呼ばれてるんですね。

最後に

今回は設計原則をデザイパターンで考えてみました。

概念をざっくり理解したものについて、違う観点・粒度を合わせ絵考えてみると理解が深くなったりします。 こういう点と点を"意識的に"つなげにいく活動を今後も続けたいですね。

さて次はAndroidエンジニアの @horitamon さんです!お楽しみに!

Web Speech APIの音声認識を使ってWebページを作ってみる

Voicyアドベントカレンダー2021 12日目の記事です。

はじめに

こんにちは、学生インターンとしてVoicyのWebフロントエンド開発をしている、きーくん(komura-c)です。

みなさんは、手を使わず音声でブラウザを操作したいなと思ったことはありませんか?僕はあります。それを実現する手段の一つとして、音声認識があります。この記事は、現状のWeb技術においての音声認識で、自分でもできそうな技術を使ってみようといった趣旨の記事です。

Webブラウザ上での音声認識について調べてみるとTensorflow.jsか、Web Speech APIが出てきます。今回は、機械学習のモデルを用意せずとも日本語で音声認識ができるWeb Speech APIを使ってみました。

Web Speech APIとは

Web Speech APIは、音声合成(Text-to-Speech)と非同期音声認識(Asynchronous Speech Recognition)の2つをウェブアプリに組み込むことを可能にするブラウザのAPIです。

developer.mozilla.org

このAPIは、Web技術の標準化団体W3Cのコミュニティグループの一つであるWICGが策定しており、現在はドラフトの段階で実験的な機能となっています。

各ブラウザの対応状況は、以下の通りです。

https://caniuse.com/speech-recognition

自分で試した環境では、GoogleChrome(MacOS)とSafari(MacOS, iOS)で動きました。

Web Speech APIを使ってみる

今回は、音声認識の方を使い、実際に以下のコードを書いてみました。 (TypeScriptで書きたかったため若干型が書いてありますが、ネイティブのJavaScriptでも変わりません)

https://github.com/komura-c/web-voice-recognizer/blob/main/src/scripts/index.ts

  // ブラウザAPIのインターフェースを取得
  const Recognition = window.SpeechRecognition || window.webkitSpeechRecognition;
  const recognizer = new Recognition();
  // 言語設定を日本語に
  recognizer.lang = 'ja-JP';
  // 解析中の結果を表示する
  recognizer.interimResults = true;
  // 認識のたびに継続的に結果を返す
  recognizer.continuous = true;
  ...
  // 結果表示用のHTML要素を取得
  const resultDiv = document.getElementById('js-result');
  let prevResultText: string;
  recognizer.onresult = function (event) {
    const results = event.results;
   // 中でも最終的な確実性の高い結果を取得
    const resultText = results[results.length - 1][0].transcript.trim();
   // interimResults, continuousをtrueにすると素早く多くの結果が返ってくるため、一つ前と同じテキストは弾いている
    if (prevResultText === resultText) {
      return;
    }
    prevResultText = resultText;
    console.log(resultText);
    resultDiv.textContent = resultText;
    actionByResult(resultText);
    startRecognizer();
  }
  ...

やっていることは単純で、SpeechRecognitionという用意された音声認識サービス用の制御インターフェイスを利用して、startやstop、各イベント後の処理を書いています。

SpeechRecognition - Web API | MDN

音声ボタンを再度クリックして止めるまで認識し続けたかったため、認識完了後も再度認識させるようにしています。

公開したWebページは以下です。

https://komura-c.github.io/web-voice-recognizer/

f:id:komura_c:20211213044538p:plain

初めは音声認識をトリガーにして何らかの動作を行うこと、例えば、ブラウザを操作できたら良いなと考えていたのですが、音声認識により受け取った文字を正しくハンドルすること、解析することが結構難しいなと考え、文字起こしだけのページになりました。この辺は、形態素解析など自然言語処理と組み合わせて一緒に使ってみるともっとできることは増えそうだと思いました。

一応GoogleChrome拡張機能も作ってみました。 拡張機能のボタンを押すことで、上、下という音声を認識してブラウザ上でスクロールを行うことができます。 拡張機能として公開してはいないのですが、以下のコードをダウンロードし、extentionフォルダをchrome://extensions/にあるパッケージ化されていない拡張機能を読み込むで指定すると、使ってみることができます。自分なりに色々カスタムして遊んでみると面白いかもしれません。

github.com

Web Speech APIのさらに深い仕様については、以下の仕様書が公開されています。

https://wicg.github.io/speech-api/

終わりに

Webブラウザ標準のAPIで音に関するものは多くあるので、今後も追って試していきたいと思いました。

おまけ

今回、Chrome拡張機能の作成も視野に入れていたため、React, Vue, AngularなどのSPAフレームワークをあえて使わずに、実行環境を整えるためにParcelを使いました。

https://ja.parceljs.org/

Parcelは設定不要なWebアプリケーションバンドラーを謳っており、Webpackなどと違い設定ファイルが不要ですぐに開発環境が用意できます。 以前Parcelを使ったことはあったのですが、こういった複雑なアプリケーションではない使用用途にはとても体験が良かったです。

ics.media

最近のRustとOSの状況についてざっくり紹介

はじめに

こちらは Voicy Advent Calendar 2021 10日目の記事です。

Rustは近年、Stack Overflow Developer Surveyで「最も愛されているプログラミング言語」らしいです。

リソース管理に所有権という独特の機能があったり、マルチパラダイムで機能も豊富なので学習難易度は高いですが、C++に似た構文でかけ、C言語と同等速度で実行でき、かつメモリ安全性が保証されいます。

C++のメモリの管理は色々気にしないといけないことが多いので、早くてメモリ安全というとC/C++に起き変わりそうな予感がして、俄然習得意欲が沸いてきます。

C/C++が長らく独占している領域といえば、とりあえず浮かぶのはOSですが、今回は、RustとOSの状況について少し調べたことを紹介します。

続きを読む

エンジニアリングマネージャーからテックリードに戻ってみて役に立った3つの考え方

こちらは Voicy Advent Calendar 2021 9日目の記事です。

こんにちは、Voicyの元エンジニアリングマネージャーで現テックリードのみっきーです。2020年1月に入社して紆余曲折があり、2020年8月からはテックリードの役割で働いています。 紆余曲折な出来事は、人事勝村がAdvent Calendarの6日目の記事モチクラ偏差値47だったVoicyがAAA獲得までにやった5つのことで書かれており、 いろいろ会社に変化があったのでご興味がある方はこちらを読むのをオススメします。個人的な変化は会社のブログで書くのもアレなので気になる方はMeetyでお話しましょう。

本記事では、一度会社でマネージャーになると、現場に戻る道がたたれ、再度新しい技術を習得するには、転職するしかない!と考える人に向けて今後のキャリアの参考になることを書きました。 数多くの面接をしていると、転職理由の中にマネージャーになってしまい技術力が足りなくなると思い、このままエンジニアとしてのキャリアが詰めないと考えて転職する方が少なからずいます。 自分もマネージャーからエンジニアに戻るキャリアチェンジを複数回しているので気持ちはよくわかります。最近、巷では、エンジニアリングマネージャーからIC(Individual Contributor)にキャリアチェンジになることも話題になりました。

私も40代間近のシニアエンジニアですので、40歳以降のキャリアを考えるきっかけにもなりました。新卒からWeb開発をしてもう16年、最新のテクノロジーの進化に対して自分の技術の伸び悩みには強く共感しました。ICはメンバーの管理責任を追わない専門職の従業員のことだそうです。会社によってはテックリードと呼ばれていることもあると思います。管理者ではないとはいえマネージメントの仕事がすべてなくなってコードだけを書いているわけではなく、マネージメント対象の割合が変わったと考えるのが適切です。そして、マネージメントと一言で言いがちですが、実際はいくつかに分けることができます。自分がマネージメントをするときに、非常に参考になったnoteのマガジンにVPoE Handbookというのがあります。この中ではVPoEの仕事は4つに分解しています。VPoEとは、エンジニアリング部門のマネージメント責任者で、会社にCTOがいる場合は、テックとピープルのマネージメントを分けたりします。

  1. Project Management
  2. Process Managmenet
  3. Team Build
  4. People & Culture Managemenet

これらはVPoEに必要な役割として定義されており、自分の経験の中でマネージメントに必要な役割は5つに分類しています。

  1. Project Management
  2. Process Managmenet
  3. Team/People Management
  4. Culture Management
  5. Technology Management

それぞれ

  • 1は、目標どおりに機能などをリリースするために開発計画を立て期限までに実行すること。
  • 2は、開発の生産性やデリバリー速度をあげるために、標準化や仕組み化をおこない改善すること。
  • 3は、採用したエンジニアのチームの配置、仕事のアサイン、採用、育成すること。
  • 4は、エンジニア組織の文化づくり。最近だと社内勉強会や輪読会、テックイベントの開催、テックブログ執筆などでお互い切磋琢磨できる仕組みを作ること。
  • 5は、技術負債の返済、技術標準化、技術選定、システム連携など複数のサービスを結合したり、連携したりすること

これらは別のスキルであり、役割によって求められる期待値レベルが異なります。エンジニアリングマネージャやVPoEだと1,2,3,4で特に3と4にかなり時間をさくことが多く、テックリードは5が中心で会社全体の技術に底上げをおこないます。これらは、私は1がかなり苦手で、4,5,3,2,1の順で強みを発揮してきました。CTOになると経営視点にたち全体をバランスよく見ながら、それぞれの役割にもっとも強みを持った人に仕事を移譲できると気持ちも楽になっていきます。今後、マネージメントを学んでいくなかで、エンジニアとしてコードを書き続けるとしても、フリーランスではなく、組織の中で働くことを選んだ人に向けて、なかなか仕事をこなす中では身につきにくいが、意識すると視座が上がることを3つご紹介します。

1. 技術選定と面接は似ている。ソフトウェアのように柔軟に変化する人が活躍する

面接経験は会社が面接担当官に指名しないと経験を積むことが難しいのですが、技術選定は割と簡単に機会を得ることが出来ます。例えば、個人サービスを作ろうと思ったときにどの技術を採用するかは1人でも考えることができるからです。活躍できる人を選ぶことと、自社のサービスにSaaSやライブラリのインストールをしてプログラムに活躍してもらう点では同じ感覚になると思っています。(ただ勘違いしてほしくないのは、優秀な学生を安くバイトで使うという発想になるのはダメです)会社もOSと考えると、OSにソフトウェアをインストールすることと、組織に人を採用することは同じです。どちらも優秀な人/ソフトウェアを入れると、出来ることが増えますし、古い考え方/バージョンが残ったままだと時代の流れに対応できないこともあります。組織にインストールしたときに自らバージョンアップできれば活躍できる機会は増えますし、アップデートできなければ時代の変化に対応できないですが、安定したソフトウェアとして保守される続けることもあるので一長一短です。会社をOSで見たときに、自分がホーム画面に選ばれるようなソフトウェアになれるか、OSとして基盤を支えるものを作っていくかを考えると見方が変わります。マネージャーになることはわりとOSやライブラリを作ることに近く、より高度な技術を磨くためにも一度マネージャーを経験すると良いと思います。

2. コンウェイの法則を意識する

コンウェイの法則とは、「システムを設計する組織は、そのコミュニケーション構造をそっくりまねた構造の設計を生み出してしまう」ことです。「エンジニアリング組織論への招待」などいろんな開発マネージメントの本に出てくる法則です。1つのサービスに閉じて作っていると、拡大していく中で必要な開発人数も多くなるが、人が増えるとコミュニケーションするパスが増えて開発効率は落ちます。最近のマイクロサービス化の流れも、コミュニケーションパスを小さくするために、一つのチームサイズを小さくする必要があり、その結果サービスを分割せざるをえないことになります。システム構造に合わせて組織を作ることをを逆コンウェイの法則と呼び、組織の拡大に合わせて人やソフトウェアを柔軟に変えていく必要があります。より上流工程に関わりたい人は、人を見ることとソフトウェアをうまく分割することの両方の経験が必要になります。そのためにもマネージャーとしてエンジニアリング組織を作るの経験と横断的なソフトウェア開発する経験を2つを意識して経験をつむと良いです。

3. 1人目のフォロワーになる

私の好きなTEDの動画にデレク・シヴァーズさんの「社会運動をどうやっておこすか」があります。ここで大事なことは、1人目のフォロワーになってサポートしていくことです。1人でなにかを始めることは非常に大変ですが、2人が参加すると続いて3人4人と続くことで交代で回せるので継続率を高まります。

1人目のフォロワーとして参加

1回目から参加

自分は起業家としてたくさんの人を引っ張るよりも、投資家として優秀な若手をサポートしていくほうが楽しみを感じるタイプだということが40年間生きてきてわかったことです。 自分がどこに一番熱量を感じられるか体験した上で、ポジションどりがうまく出来ると幸せになれるのではと思いました。

最後に

まだマネージメント経験がなくこれからマネージャーの役割も担いそうな人はぜひ参考にしてみてください。

最後に自分が読んで良かったマネージメントのおすすめの書籍を紹介します。

  • エンジニアのためのマネジメントキャリアパス ―テックリードからCTOまでマネジメントスキル向上ガイド
  • エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング
  • More Effective Agile ~“ソフトウェアリーダー"になるための28の道標
  • Scaling Teams 開発チーム 組織と人の成長戦略 ~エンジニアの採用、マネジメント、文化や価値観の共有、コミュニケーションの秘訣~

まだ、自分は読んでないですが、どういうチームを作っていくかで最近話題になっている本です。次回、読んだ感想を別の記事に書きたいと思います。

  • ユニコーン企業のひみつ ―Spotifyで学んだソフトウェアづくりと働き方
  • チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計

巷で話題の「音声 x AI」の技術をいろいろ紹介

こちらは Voicy Advent Calendar 2021 8日目の記事です。

こんにちは、Voicyのバックエンドエンジニアのせんちゃんです。学生時代に音声の研究をしていたこともあり、先日Voicyにジョインしました。この度入社1週間ほどでアドベントカレンダーの執筆に携わらせていただいております。がんばります。

はじめに

とても正直に申しますと、入社1週間なのでVoicyのシステムについてはまだ全然分かっておりません!

というわけで本記事では、自分が行なっていた音声に関する研究を踏まえ、最近の「音声 x AI」の技術をカジュアルに紹介していきます。

AIってなんのこと

本題に入る前に、AIというざっくりしすぎた単語について軽く触れておきます。

「音声 x AI」と聞くと、多くの人の第一想起は音声アシスタントではないかと思います。GoogleアシスタントやSiri, Alexa等が有名ですね。もちろんこれらも今回紹介する内容に該当しますが、他にもいろいろな技術があります。

キャッチーなタイトルにしたくてAIと書いてしまいましたが、ここでは主に機械学習、特にディープラーニングをイメージしています。機械学習という技術を音声の世界に持ち込んだときにどんなことができるのか、読者の方のイメージが膨らみましたら幸いです。

機械学習に詳しくない方へ

私は「機械学習ってなんですか?」と聞かれたら「ざっくり言うと単なる入出力装置です」と答えています (この装置をモデルと呼びます) 。画像認識で有名ないわゆる「Googleの猫」はなんらかの画像をモデルに入力すると、1 or 0 (猫が写っている or 写っていない) が出力されます。

では何がすごいのかと言うと、入力データと、正解となる出力データのペアをたくさん用意しておけば、それらの関係性を自動的に学習してくれます。

上記の例では、

  • 入力: なんらかの画像
  • 正解データ: その画像に猫が写っているか否かの情報

のペアをたくさん用意することで、それをもとに学習したモデルは猫が写っているかどうかを判断できるようになります。

それでは本題に進みましょう。


音声認識: Speech Recognition

まずは、音声認識です。これはコンピュータに音声を認識させる技術です。より具体的には音声を文字に起こす技術を指すことが多いです。先ほどの入出力に当てはめるのであれば、音声を入力としてそれに対応するテキストを出力する、と考えることができます。音声とその発話内容を書いたテキストのペアのデータを使用して学習したモデルによって実現されます。

・音声 => テキスト

音声認識の精度は飛躍的に向上してきており、ほとんどのパソコンやスマートフォンに音声入力機能が搭載されています。また、時間に追われるビジネスマンなどを中心に音声入力を使用する方も増えてきている印象があります。例えば、勝間和代さんはVoicy上でもたびたび音声入力がいかに効率的かという話をしてくださっています。 voicy.jp

Voicyでの音声認識技術の活用方法としては、各放送を文字に起こすことでより高精度なレコメンドを実現するなどが考えられます。

話者認識 (わしゃにんしき)

音声認識の分野のひとつに話者認識があります。これは音声を入力としてその話し手を認識する技術です。話者照合と話者識別の2種類に大別されます。

話者照合は、その音声が本人のものか否かを判断する技術です。人の声質や話し方はひとりひとり異なっているため、指紋と同じように声紋という概念があり、声による認証に応用されます。

一方、話者識別は、聞こえてきた声があらかじめ登録しておいた誰のものであるかを識別する技術です。会議の議事録を自動でとってくれるソフトなどで使用されます。これにより、話された内容だけでなく誰の発言であったかまで記録しておくことができます。


音声合成 Speech Synthesis

コンピュータで音声を作り出す技術を音声合成と呼びます。特に、テキストを入力として音声を出力する、テキスト音声合成 (Text-to-Speech; TTS) を指すことが多いです。音声合成には、波形接続型の手法と機械学習に基づく手法の2種類があります。

・テキスト => 音声

波形接続型では、あらかじめ音の素片を作って保持しておき、合成時にそれを並べて言葉にします。事前に用意する音の素片というのは a, i, u, e, o, ... といった母音や k, s, t, n, h, m, y, ... といった子音です。これは実際に録音された音声から作られる場合が多いですが、なんと手作業で波形を作っている場合もあります。

そして、例えば「おんせい」という言葉を作りたければ、この中から必要なものを選んで

o - n - s - e - i

と並べるイメージです。

この方式のソフトウェアとしてはVOICEROIDや、「ゆっくりボイス」として親しまれているAquesTalkなどが有名です。 nlab.itmedia.co.jp

一方、機械学習に基づく手法では、テキストと音声の関係を学習したモデルを使用します。ちょうど、音声認識と入出力のデータが反対になっているため、学習に使用するデータ自体は同様に音声とテキストのペアです。あるテキストが入力されたときに、それに対応する音声が出力されるように学習させます。

従来の機械学習に基づく手法はなんと言っているかは理解できるものの、あまり人間らしくない機械的な音声しか合成することができませんでした。

しかしながら、2016年にGoogle傘下のDeepMindWaveNetというモデルを発表し、合成音声の自然性が飛躍的に向上しました。 deepsquare.jp

最近では公共交通機関のアナウンスなどは、人間が話した声なのか合成音声なのかを判別することすらなかなか難しくなってきています。

私はアナウンスが聞こえてくると無意識のうちに「これは合成」「これは録音」と判断してしまう病気にかかっています。

歌声合成

音声合成の応用として、歌声合成という技術があります。

歌声合成と言えば、初音ミクを代表とするVOCALOIDが有名ですね。VOCALOIDYAMAHAが開発する歌声合成ソフトウェアです。波形接続型の手法を採用しており、声の素片を並べて加工していくことでひとつの楽曲を作り上げます。

一方で、歌声合成にも機械学習に基づくアプローチが存在します。 音符や歌詞といった楽譜情報を入力とし、機械学習を用いて自動的に歌声を合成する方法です。国内では、テクノスピーチ社等が中心となって開発を進めてきたCeVIO Creative Studioが牽引役となっています。 cevio.jp

VOCALOID機械学習ベースの手法を使用したソフトウェアを開発し、2019年にVOCALID:AIとしてリリースしました。以下はその技術により、美空ひばりさんの歌声を再現した際のニュースリリースです。NHKで放送され業界ではなかなか大きなニュースでした。 www.yamaha.com

以上のような音声合成/歌声合成の技術は、音声や歌声のデータが多く残っていれば、すでに亡くなっている方の声を再現することもできてしまいます。故人の声で新曲を歌わせることができるなど、大きな可能性がある一方で、使用者の倫理観も考えさせられます。


音声対話

冒頭に述べたGoogleアシスタント等がイメージしやすいですね。音声アシスタントが搭載されていないスマートフォンを探す方が難しい時代になってきていますし、自宅にスマートスピーカーを置いている方も徐々に増えてきたのではないでしょうか。

音声認識音声合成の技術を使うと対話ができるように、、とは、残念ながらなりません。ざっくり言うと、音声対話には以下の機能が必要です。

音声認識 => 発話理解 => 応答文生成 => 音声合成

かけられた言葉の意味を理解しなければなりませんし、その上で適切な返答文を作らなければなりません。しかも上記の流れは、一問一答形式のシンプルな対話システムを想定しています。話の流れによって動的に応答が変わる対話を実現するためには、対話状態を保持しておく必要があるなど、考慮すべきことが膨大になります。みなさんご存知のとおり、現時点で人間レベルの音声対話ができるシステムは実現されていません。

音声対話の実証実験の例として、名古屋工業大学の正門には「メイちゃん」というデジタルサイネージ (大型ディスプレイの中の3Dキャラクター) がいます。来訪者に対して校内の道案内や、イベントの告知などをしてくれます。

www.nitech.ac.jp


音声変換 Voice Conversion

こちらは、名探偵コナンの蝶ネクタイをイメージしていただけると分かりやすいかと思います。いわゆるボイスチェンジャーとは少し異なっています。ボイスチェンジャーは声の高さや声質などのパラメータを調整して元の声を加工するだけであるのに対し、機械学習を使った音声変換は特定の誰かになりきったような声に変換をすることができます。

・音声 => 音声

音声変換の分野で博士号を取得されているドワンゴのヒホさんは、自分の声をVOICEROIDの結月ゆかりに変換した動画をニコニコ動画にアップロードし、一部界隈で人気を博しています。おもしろい上に音声変換の理解も深まるのでぜひ一度観てみてください。 www.nicovideo.jp

また、2021年にDeNAがリリースした「VOICE AVATAR 七声ニーナ」(ななこえにーな) を使えば、ブラウザから誰でも簡単に音声変換を試すことができます。 nanakoe-nina.dena.ai

その他、標準語の音声を関西弁に変換するなどの発話スタイルの変換も広い意味では音声変換の一種と言えるでしょう。

余談ですが、スタートアップ界隈ではベンチャーキャピタル (Venture Capital) の意味でVCという言葉がよく使われます。私の身の回りでは音声変換 (Voice Conversion) を略してVCと言っていたので慣れるまで時間がかかりました。


むずび

いかがだったでしょうか。音声からの感情認識など、まだまだいろいろな技術がありますが、全て紹介し切ることはできないのでこのあたりで終わります。音声に関する技術に興味を持ってくださる方が増えれば嬉しい限りです。

Voicyでは多くのパーソナリティの方々が日々、声で発信をしてくださっています。これらの財産からさらなる価値を生み出していくためにも、常に最先端の音声技術にアンテナを張っていきます!

Voicyのエンジニアリングチームでは、音声でも発信を行なっています。気が向いた方は聞きにきてください! voicy.jp


非エンジニアが音響知識だけでffmpegのコードサンプル作ってみた

 


この記事はVoicy Advent Calendar 2021 7日目の記事です。

初めまして、Voicyのプロダクトマネージャーのエモジマです。

同時並行で走るVoicyの開発のプロジェクトにおいて、リソースが効率的に配分され、レビュー漏れがなく、コンフリクトせず、最速で高品質のアプトプットをするというような ”無理ゲーパズル” をミッションとして課せられています。

ボクはPMなので業務上コードを書いたりすることはありません。(見え張った、できません。)
しかし、レコーディング・ミックス技術者としてのキャリアがあり、音声処理において基本的な知見を持っています。
音声に対する理解が深いからこそ、Voicyの音声処理について何かコミットできることはないかと思い、ffmpegくらいは触ってみたところ、これがまぁ面白い。

というわけで、非エンジニアがffmpeg触って、ちょっとした音声処理のテンプレを作ってみたのでご紹介します。

※ 以下は社内ハッカソンの際に、アプリエンジニアに渡した設計書が元になっています。コントロール に記載されたパラメータをフロントで入力する想定です。
また、サンプルの音源は変化がわかりやすいように極端な設定にしています。

 

1. Gain調整

音量を調節する機能。設定したdBだけ音量を増減させる。
家庭用オーディオの音量つまみを上げるのと同じようなやつ。

   f:id:a-fridge-on-heatisland:20211206193226p:plain

$ffmpeg -i input.mp3 -af volume=10dB output.wav
//増加の場合単位なし、低減の場合-10dBを指定する。0dBを超える増幅の場合、0dBになる。

・元ファイル

・音量上げ済 (+5dB)

参考: https://www.ffmpeg.org/ffmpeg-filters.html#volume

2. コンプレッサー

音量を圧縮して音圧を調整する機能。 thresholdで閾値を決め、指定したdb以上の音を圧縮する。

ratioで超えた音の圧縮率を決める1:2の場合、4dB超えると2dBに圧縮される。1:20になるとリミッターと呼ばれ、そこ以上は絶対に超えないようにするアプローチ。

makeupで圧縮された後に全体の音量を増減させる。大きい音を圧縮した後、全体の音量を上げると、相対的に音量の小さい部分が大きくなり音量のバラツキを調整できる。

コントール:

  • threshold = -20dB
  • ratio = 1:4、1:8、1:20
  • makeup = 3dB

以下デフォルト設定値

  • attack = 5ms
  • release = 100ms

   

$ffmpeg -i input.mp3 -af acompressor=threshold=-21dB:ratio=20:makeup=3:attack=5:release=100 output.wav 
//thresholdは数値を{-〇}dBで入れ、ratioは1:◯側の数値を入れる。 

・元ファイル

・コンプ済 (threshold -30dB, ratio 1:20, makeup 5dB)

参考: https://www.ffmpeg.org/ffmpeg-filters.html#acompressor

3. フィルター

指定した周波数以下の音を除去(ハイパス)、もしくは指定した周波数以上の音を除去(ローパス)する。
軽くハイパスかけておくと部屋のブォーンっていうノイズ低減になり、ローパスをかけておくと高周波のノイズが消える。かけ過ぎると声質に影響する。

コントール:

  • highpass = 200Hz
  • lowpass = 3000Hz

 

$ffmpeg -i input.mp3 -af highpass=f=200,lowpass=f=3000 output.wav

・元ファイル

・ハイパス (500Hz)

・ローパス (1000Hz)

・ハイパス&ローパス (highpass 500Hz, lowpass 1000Hz)

参考: https://www.ffmpeg.org/ffmpeg-filters.html#highpass

4. ノイズ除去

ホワイトノイズを除去する機能。 ノイズフロアで除去の感度を決める(通常、ホワイトノイズは音が小さく何dB以下をノイズとするかの閾値を決める)
ノイズリダクションで何dB分ノイズ音を低減させるか決める。かけ過ぎると変な変化をする。

コントール:

  • ノイズリダクション = 12dB
  • ノイズフロア = -50dB

以下デフォルト設定値

  • ノイズタイプ = ホワイトノイズ
  • 出力モード = ノイズを除去する

 

$ffmpeg -i input.mp3 -af afftdn=nr=12:nf=-50:nt=w:om=o output.wav
//ノイズフロア(nf)は{-◯}dBの形で入力する。

・元ファイル

・ホワイトノイズ除去済 (リダクション 12dB, ノイズフロア -50dB, タイプ ホワイトノイズ)

参考: https://www.ffmpeg.org/ffmpeg-filters.html#afftdn

5. 音量レベル測定

現在の音量を測定する機能。
オーディオファイルを読み込ませて、以下の数値を表示させたい

  • 音量("max_volume" dB)
  • ラウドネス値("input_i" / LUFS)
  • True Peak("input_tp" / dB)

 

$ffmpeg -i input.mp3 -af volumedetect -f null -
結果
[Parsed_volumedetect_0 @ 0x7fb450004180] n_samples: 441000
[Parsed_volumedetect_0 @ 0x7fb450004180] mean_volume: -21.1 dB 
[Parsed_volumedetect_0 @ 0x7fb450004180] max_volume: -18.1 dB ←これ
[Parsed_volumedetect_0 @ 0x7fb450004180] histogram_18db: 128000
$ffmpeg -i input.wav -af loudnorm=print_format=json -f null -
結果

[Parsed_loudnorm_0 @ 0x7fec77104080] 
{
	"input_i" : "-20.91",←これ
	"input_tp" : "-0.98",←これ
	"input_lra" : "12.40",
	"input_thresh" : "-32.76",
	"output_i" : "-25.16",
	"output_tp" : "-2.86",
	"output_lra" : "4.90",
	"output_thresh" : "-36.36",
	"normalization_type" : "dynamic",
	"
target_offset" : "1.16"
}

参考: https://www.ffmpeg.org/ffmpeg-filters.html#afftdn

 

まとめ

実用化とか全然考えず、とりあえずコマンド叩くと音が変わるってことが確認できただけでも、ボクとしては長〜いウィニングランが出来るほど豪快なゴール達成なわけで。

ffmpegPythonなんかを習得、音声エンジニアになって、早いとこプロダクトマネージャー卒業したいです(嘘)

音を再生するのは簡単、停止と再開は闇というおはなし

この記事は Voicy Advent Calendar 2021 4日目の記事です。

Androidアプリエンジニアのぬまさんです。2020年9月にVoicyにジョインし早1年が過ぎました。仲間と切磋琢磨しながら開発しています。


はじめに

VoicyのAndroid収録アプリでどのように音を再生しているか、長時間音声を再生する対応を行った際得た知見を共有します。

続きを読む