VOICEVOX/voicevox_engine

`GET /speaker_info` が生バイト列でなく Base64 文字列を返す理由が知りたい

tarepan opened this issue · 2 comments

質問の内容

概要: GET /speaker_info が生バイト列でなく Base64 文字列を返す理由が知りたい

Base64 エンコードは POSTリクエスト時に Blob を URL パラメータとして扱うために Web で重宝される。
現在の VOICEVOX ENGINE は wav ファイルや png ファイルを Base64 エンコードして返している。これは一見すると奇妙で、Resnpose Body に Blob (バイト列)をそのまま詰めるだけでも良さそうに見える。なお、Pydantic は bytes を受け入れ可能である (ref)。

エディタ立ち上げ速度の文脈で GET /speaker_info 高速化が求められており(#1129)、「Base64 エンコード負荷が高そう (#1129 (comment) )」「GET /speaker_info は実は遅くない (#1129 (comment) )」「とりあえず URL 化すればいい(#1208)」など様々な検証と提案がなされている。
ただ、その前提として、そもそもの設計意図を再確認することが肝要である。
再確認ができれば、想像ベースで破壊的 API 変更をしなくても、当初設計意図を微修正し段階的にまだまだ改良できる。

このような背景から、次の質問があります:

  • GET /speaker_info はなぜ生バイト列でなく Base64 文字列を返すのか

VOICEVOXのバージョン

0.19.0

なお、Pydantic は bytes を受け入れ可能である

Pydantic自体は受け入れ可能ですがJSON側の仕様でバイト列は受け入れ不可能です。
モデルにutf-8でデコード不可能なバイト列がある場合BaseModel.json()を呼ぶとUnicodeDecodeErrorが発生します。

関係ありそうなPR(/speaker_info実装の経緯のPR?)

JSON側の仕様でバイト列は受け入れ不可能

👍️
理解しました。ありがとうございます!
FastAPI が return BaseModel を 暗示的に JSONResponse 化しているため(出典: ref)、JSON仕様(= 文字列ベースで bytes を扱えない)に従う必要があるということですね。

となると、生バイト列を送るのであれば非 JSON のレスポンス (例: FileResponse) を使うのが必須になると理解しました。
このアプローチを取るのが #1208 と整理できそうです。