Introduction
I replaced the voiceover worker’s npm SDK integration with a direct, synchronous HTTP POST to the TTS synthesize endpoint. The worker still runs in an SQS-driven Lambda, so the workflow remains asynchronous for the caller: the script is queued, and the worker handles synthesis. The previous implementation used the Resemble npm package with a streaming-oriented interaction model. The replacement receives base64-encoded audio in the HTTP response and saves the generated chunks to S3 for playback through CloudFront URLs in the UI.
With that change, the application became responsible for building the request. I added an explicit newline transformation and removed three audio-related fields from the payload. Those are implementation changes, not proof that every downstream behavior stayed the same. I separately confirmed the UI’s playback path, but the available evidence does not show a single demonstrated run from a queued script through synthesis, storage, and playback.
The Rule That Shipped
Before any chunk is sent to the synthesize endpoint, the worker replaces newline characters in its text with spaces. It also leaves output_format, sample_rate, and precision out of the request payload entirely. The fields are absent—not present with empty or replacement values. The worker then makes the synchronous HTTP POST with the sanitized text.
The implementation also splits oversized script sections to keep each part within a maximum character limit. The evidence does not specify that limit, so I cannot give an exact threshold or demonstrate what happens at the boundary. The supported rule is precise about newline handling and the omitted fields, but not the numerical chunk-size constraint. Beyond replacing newlines before building the outgoing request body, the evidence does not establish the order of every text-processing operation.
Inline voice tags need a separate qualification. Tag sanitization is within the stated scope, but the supplied evidence does not establish a shipped validation or transformation rule. I cannot say which tags are accepted, which forms are rejected, or what happens to malformed markup. Newline replacement is not a complete account of text sanitization.
Worked Example
Consider a script part with two lines: “Welcome back.” followed by a newline and then “Let’s begin.” Assume it has already been queued for synthesis as one chunk. Before building the HTTP request body, the worker replaces the newline with a space. The text sent for synthesis is “Welcome back. Let’s begin.” The payload contains no output_format, sample_rate, or precision fields.
In the supported processing flow, the synchronous POST returns base64 audio content. The worker decodes it and saves the audio to S3. The resulting clip is served through a CloudFront URL and used by the UI’s chunked audio player. This shows how the text transformation fits into storage and playback without inventing a request schema or character threshold.
The example illustrates the documented rule; it is not a recorded execution of those particular words. It also says nothing about whether the previous SDK path preserved or transformed newlines. The supported before-and-after comparison is narrower: the old worker used the SDK, while the replacement explicitly transforms newlines before making its direct HTTP request. Clip identity remains unresolved too. The synthesize endpoint does not return a clip UUID, and the replacement tracking mechanism is unknown.
Challenges and Tradeoffs
Moving from the SDK to direct HTTP puts more responsibility in application code. I now build the request and handle the returned audio explicitly. That makes the outgoing fields and newline transformation visible in the implementation, but it does not by itself prove greater reliability or equivalent output. Keeping the SDK was an alternative. The evidence does not support a comparison of performance, maintenance cost, or audio quality.
The synchronous request is distinct from the asynchronous job. SQS separates submission from processing, but the Lambda worker waits for the synthesis response. Receiving one audio payload means this implementation does not have to manage a streaming response. It also means this request path does not deliver incremental audio while synthesis is still running. The supplied evidence establishes no latency improvement, timeout behavior, or retry policy.
Leaving out the three format-related fields simplifies the request, but the compatibility question is still open. I have not verified whether removing them changed the resulting audio format or quality. I cannot say they were proven unnecessary or that the endpoint defaults were checked and found equivalent.
Clip identity is another open issue. Saving audio bytes to S3 does not establish how a database record identifies a clip when the endpoint returns no clip UUID. I recognized that gap, but the evidence does not show it being resolved. Storage location, playback URL, and application-level identity need to remain distinct.
Verification Process
I distinguish completed implementation work from runtime verification. The recorded work includes wiring the processing queue and Lambda, updating GraphQL mutations for enqueueing and synthesis, adding generation-job and job-status models, and adding a migration to clear legacy data. The planned tasks were marked complete without changing the source plan file. That establishes the scope of the work, not that every execution path succeeded.
The playback check was narrower: I confirmed that the UI’s chunked audio players use CloudFront URLs to play S3-backed clips. That supports the playback arrangement described here. It does not show a newly queued script passing through the replacement HTTP integration, producing stored audio, and playing successfully in the same observed run.
Other checks remain unestablished. The exact chunk-size limit is unspecified, and boundary testing for oversized scripts is not documented. Clip UUID tracking remains unresolved in the evidence. There is no verified comparison of audio format or quality after removing the three payload fields, and no established inline-tag validation rule. A fuller verification pass would need to trace a queued input through to its generated object and playback result, then separately check those boundaries and identity handling. Those are checks still needed, not completed tests.
Conclusion
I built a direct-HTTP replacement for SDK-based synthesis inside an SQS-driven Lambda worker. Before sending each chunk, it replaces newlines with spaces and omits output_format, sample_rate, and precision from the request. The returned base64 audio is persisted as S3 chunks for the UI’s CloudFront-backed playback path.
I confirmed the playback path separately; full queued-synthesis-to-playback verification was not established. The remaining limits are specific: the chunk-size threshold is unspecified, clip UUID tracking is unknown, effects on audio format and quality are unverified, and no inline-tag rule is supported by the evidence. Keeping those limits explicit separates what shipped from what I have not yet verified.