fix(text2speech): route synthesis through Smalruby CORS proxy (#859)#861
Conversation
Scratch's synthesis service (synthesis-service.scratch.mit.edu) is CORS-locked to scratch.mit.edu, so smalruby.app is blocked when calling it directly — same root cause as translate (#857). Route text2speech through a new Smalruby proxy endpoint. infra/smalruby-api: add scratch-api-synthesis Lambda + GET /scratch-api-proxy/synth route. Unlike translate (text), synthesis returns binary audio (mp3), so the proxy Base64-encodes it (isBase64Encoded: true) and API Gateway decodes it for the client (same approach as cors-proxy binary handling). Adds mocked-fetch unit tests. scratch-vm: override SERVER_HOST in scratch3_text2speech (upstream file) with Smalruby markers so ${SERVER_HOST}/synth targets the proxy. Guard test + smalruby-markers-vm.md entry so future upstream merges detect the override (as happened to translate). CDK deploy and real-device audio playback are left to a human (HITL) per the issue. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🤖 autopilot status
Linked issue #859. Maintained by autopilot (single writer); do not edit. |
|
🚀 Preview deployed: https://smalruby.jp/smalruby3-editor/topic/autopilot-859/ |
The synthesis proxy override (#859) turns text2speech into an upstream modification, but its feature doc still declared it upstream-as-is. Update the badge to 🔧 and document the CORS proxy routing, mirroring translate (#857) so the DoD upstream-divergence rule is satisfied. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🤖 敵対的レビュー結果(autopilot review フェーズ)別レビュアー視点で差分(8 ファイル、synthesis CORS プロキシ)を検証しました。 ✅ 確認できたこと
🔧 レビューで自分で修正した点(1 件)
⏳ 人間への依頼(HITL)PR 本文どおり CDK deploy(stg→prod)と実機での音声再生確認 は AWS SSO を要する人間作業です。手順は PR 本文に記載済み。 |
takaokouji
left a comment
There was a problem hiding this comment.
確認してほしいのですが fix(translate): 翻訳拡張が CORS で失敗(Scratch 直叩き→Smalruby プロキシ経由に)
#857 で利用しているプロキシは汎用的な proxy になっているはずで、サービスごとにつくらなくてもいいはずです。そのため、単純に同じ proxy を指定するだけで、パスが異なるために動作するはずです。確認して、私の認識があっていたら、実装を変更してください。
…d synth Lambda レビュー指摘 (#861) を受けて、音声合成 (text2speech) の CORS 回避を専用 Lambda では なく Smalruby の**汎用** cors-proxy (`GET /cors-proxy?url=<encoded 合成URL>`) の再利用に 切り替える。汎用 cors-proxy は既に `audio/*` をバイナリ判定して Base64 返却するため、 専用 `scratch-api-synthesis` Lambda・ルート・integration の追加もインフラの再デプロイも 不要になる。 - `scratch3_text2speech/index.js`: `SERVER_HOST` を upstream 値に戻し、合成 URL 組み立て 箇所だけを generic cors-proxy でラップ (Smalruby マーカーで囲む)。upstream 差分が最小化。 - `infra/smalruby-api`: 追加した `scratch-api-synthesis.ts` / そのテスト / stack のルートを削除。 - docs (extension-text2speech / smalruby-api / markers-vm) を汎用プロキシ方式に更新。 - ガードテスト `test/unit/extension_text2speech_proxy.js` を cors-proxy 経路の検証に更新。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@takaokouji ご指摘ありがとうございます。確認した結果を報告します。 確認結果ご認識はおおむね正しく、専用 Lambda は不要でした。実装を切り替えました 👍 ただし細部で 1 点補足があります:
変更内容 (commit
|
…ot-859 fix(text2speech): route synthesis through Smalruby CORS proxy (#859)
Summary
音声合成拡張(text2speech / 「音声で話す」)も翻訳(#857)と同じ CORS 構造で、Scratch の synthesis
サービス(
synthesis-service.scratch.mit.edu)直叩きが CORS で失敗する。#857 と同方針で Smalrubyプロキシ経由に切り替える。synthesis 用プロキシは未整備だったので新設した。
translate(テキスト)との最大の違いは 応答がバイナリ音声(mp3) な点。プロキシは Base64 で返却し
(
isBase64Encoded: true)、API Gateway HTTP API v2 がクライアントへバイト列にデコードする(既存cors-proxyのバイナリ Base64 化と同じ考え方)。Changes Made
1. synthesis プロキシ Lambda を新設(
infra/smalruby-api)lambda/scratch-api-synthesis.tsを新規作成(scratch-api-translate.tsを雛形に)。GET /scratch-api-proxy/synth?locale=&gender=&text=を受け、https://synthesis-service.scratch.mit.edu/synth?...へサーバ側 fetch。成功時はバイナリ音声を Base64 返却(
Content-Type: audio/mpeg)、上流エラーは status を透過して JSON で返す。
locale/gender欠落は 400、fetch 失敗は 502。lib/smalruby-api-stack.tsに Lambda + ルート/scratch-api-proxy/synth(GET) を追加。lambda/tests/scratch-api-synthesis.test.ts(mocked fetch): 400/正常 Base64/URL エンコード/上流エラー透過/502 の 6 ケース。2. text2speech 拡張をプロキシに向ける(
scratch-vm)scratch3_text2speech/index.jsのSERVER_HOSTをhttps://api.smalruby.app/scratch-api-proxyに上書き。拡張が
${SERVER_HOST}/synth?...を組むため base 差し替えのみで proxy 経由になる。docs/maintenance/smalruby-markers-vm.mdに記録。マーカー無し上書きが v13.7.2 マージで静かに revert された translate(fix(translate): 翻訳拡張が CORS で失敗(Scratch 直叩き→Smalruby プロキシ経由に) #857) の再発を防ぐガードテスト
test/unit/extension_text2speech_proxy.jsを追加。Test Coverage
infra/smalruby-api:npm test -- scratch-api-synthesis→ 6/6 passscratch-vm:npm exec tap -- test/unit/extension_text2speech_proxy.js→ 3/3 passscratch-vmlint: 0 errors / prettier OK、infra/smalruby-apitsc --noEmitclean🙋 HITL — 人間にお願いしたいこと(deploy + 実機確認)
issue の制約どおり、autopilot はコード実装まで。以下は人間の作業(devpod ワークフロー、AWS SSO 要):
api.smalruby.appは既存カスタムドメイン import 方式なのでルート追加のみ。.env/CI への影響は無し。Related Issues
Closes #859
関連: #857(translate。同じ根本原因・方針)