Skip to content

ストリーミング処理の対応 #853

@Yosshi999

Description

@Yosshi999

内容

音声を逐次的に生成する機能を提供し、長い文章の音声を生成する際のレイテンシの短縮をめざす。

関連

Pros 良くなる点

  • レイテンシの短縮:現状の処理時間は生成する音声の長さに比例して増大するため、長い文章を入力したときにかなりの処理時間を要することがある。処理する部分を固定長のチャンクに分け、逐次的に音声を生成することで入力全体が生成されきる前に音声の再生などを行うことを可能にする。

Cons 悪くなる点

  • 機能の複雑化(どこまで凝った実装をするかによる。後述)

実現方法

現在の音声合成処理(synthesis)はaudio queryを入力としてスペクトログラム生成 -> 音声波形生成の順に処理されており、前半と後半の処理時間の比は大体1:10くらいである。また、スペクトログラム生成は内部のモデルの仕様上audio query全体を入力する必要があるが、後半の音声波形生成は十分にマージンを取っていれば任意の位置から任意の長さの音声を生成することができる。

参考:
https://github.com/Yosshi999/streaming_hifigan

そこで、現在 decode として処理されている関数を二つに分け、 generate_full_intermediate 関数によってえられる中間表現(現状ではスペクトログラム)をいったんユーザーに返し、その中間表現と指定区間を入力として音声を生成する render_audio_segment 関数によって最終的な音声を生成する。

実装が必要なもの

  • struct Intermediate : ユーザーにいったん返す中間表現。実態(スペクトログラム)には触れてほしくないが、lengthは後段の生成区間指定などのために参照可能にする必要がある。
  • blocking::Synthesizer::synthesis_intermediate(&self, &AudioQuery, StyleId, &SynthesisOptions) -> Result<Intermediate> : 現在のsynthesis()の途中(decodeの前半部)までを実行する。現在音声が途切れる問題のworkaroundとして前後にパディングがついており、これを音声生成時に取り除くためパディング長をどこかで共有する必要がある。
  • blocking::Synthesizer::render_audio_segment(&self, Intermediate, usize, usize) -> Result<Vec<u8>> : 中間表現から指定した区間の音声を生成する。
  • nonblocking::* も必要?
  • 各種api露出

あるとうれしいもの

  • とくに何も考えなくても音声チャンクが手に入るIterator
  • 理想的なチャンク長や、いまから音声バッファの再生を始めてもいいか判定してくれる関数
    • 処理時間よりも生成される音声長が長い場合(効率>1)、一個めのチャンクができ次第再生を開始してもよいが、効率が低い場合、再生バッファに詰める音声の生成が追い付かずつっかえるため気を付ける必要がある
    • 正直ユーザー側が実装するべきものかもしれない

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions