An omitted speed no longer breaks synthesis on Hume and Smallest AI

A synthesis request that did not set speed serialized it as JSON null, which Hume and Smallest AI reject. On the streaming transports the 200 status line is sent before the provider replies, so the caller received a successful response carrying zero bytes.

An absent optional field was serialized as JSON null rather than omitted. Hume rejected the whole payload with a float_type parse error on speed, and Smallest AI rejected it as invalid input data. Absent optional fields are now left out, which lets the provider apply its own default. A request that sets speed explicitly is unchanged.

On POST /v1/audio/speech/stream and POST /v1/synthesize/stream the 200 status line and routing headers are committed before the provider answers, so this could not be reported as an error status: the response was a successful one carrying no audio.

The buffered and streaming WebSocket TTS paths each carried their own copy of these provider handshakes. Both now share one helper, so the two cannot drift apart.

Action: No migration is required.