Fix for long text inputs, send text as payload, not url parameter.#149
Fix for long text inputs, send text as payload, not url parameter.#149bioluminesceme wants to merge 1 commit intomicrosoft:mainfrom
Conversation
|
@microsoft-github-policy-service agree |
|
Error on my side. |
|
That looks like you are still using the old code that sends the text as a URL parameter? My URL is "WebSocket /stream without the long |
|
If you have both the changed demo/web/app.py and demo/web/index.html that url should not have the parameters in it anymore in the index.html this ``` const wsUrl = was changed to
|
There was a problem hiding this comment.
Pull request overview
This PR fixes 400 Bad Request errors when streaming long TTS text in the demo Web UI by moving the input text/config from WebSocket URL query parameters into an initial WebSocket message payload.
Changes:
- Frontend: stop appending
text/cfg/steps/voiceas URL query params; send them as the first WebSocket JSON message after connect. - Backend: stop reading
ws.query_params; insteadreceive_text()+json.loads()to obtain initial stream configuration.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| demo/web/index.html | Sends TTS request configuration as a JSON WebSocket message instead of URL query params. |
| demo/web/app.py | Reads the initial JSON configuration message from the WebSocket rather than query params. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| socket.onopen = () => { | ||
| // Send configuration as first message after connection opens | ||
| socket.send(JSON.stringify(config)); |
There was a problem hiding this comment.
socket.onopen closes over the mutable global socket variable, but closeSocket() sets socket = null even when the WebSocket is still CONNECTING. If the user stops quickly (or other code calls closeSocket) around the time the connection opens, this handler can run with socket === null and throw when calling socket.send(...). Capture the WebSocket instance in a local const (or use the event.target) inside the handler to avoid races with socket being reassigned/nullified.
| socket.onopen = () => { | |
| // Send configuration as first message after connection opens | |
| socket.send(JSON.stringify(config)); | |
| socket.onopen = event => { | |
| // Send configuration as first message after connection opens | |
| const ws = event.target; | |
| ws.send(JSON.stringify(config)); |
| try: | ||
| config_message = await ws.receive_text() | ||
| config = json.loads(config_message) | ||
| except Exception as e: | ||
| print(f"Error receiving config: {e}") | ||
| await ws.close(code=1003, reason="Invalid configuration") | ||
| return | ||
|
|
||
| text = config.get("text", "") | ||
| cfg_param = config.get("cfg") | ||
| steps_param = config.get("steps") | ||
| voice_param = config.get("voice") | ||
|
|
||
| print(f"Client connected, text length={len(text)}, cfg={cfg_param}, steps={steps_param}, voice={voice_param}") |
There was a problem hiding this comment.
After json.loads, config can be any JSON type (string/list/null/etc). The subsequent config.get(...) calls and len(text) will raise (AttributeError/TypeError) for valid-but-unexpected payloads like "foo" or { "text": null }, resulting in a 500 and leaving the socket in a bad state. Validate config is a dict and that text is a string (or coerce/reject) before accessing .get/len, and close the websocket with an appropriate code/reason on invalid types.
If you paste in too much text, the webui of VibeVoice-Realtime TTS errors with a 400 Bad Request.
Fix: send all the text as a websocket payload, not as a URL parameter. Then streaming the text works great again.
I used Claude Code for part of this.