feat(genmedia): provider-agnostic generative media layer - #13
Merged
Conversation
Adds image, video, speech and music generation alongside the existing ffmpeg pipeline, behind one interface with swappable providers. Seven repos across the portfolio (viral-video, makedemo, amazon-affiliate, reeleel, brisk.news, bl0ggers, intr0s) have each independently rebuilt the same script -> image -> TTS -> mux pipeline. This is the shared layer they can all sit on. - Providers: google (Gemini Image, Veo, Gemini TTS, Lyria), openai (gpt-image-1, gpt-4o-mini-tts), elevenlabs (TTS) - No new runtime dependencies: every call is plain fetch against a documented REST endpoint, using the global fetch in Node 20+ - Provider resolution picks the first preferred provider for a capability that actually has credentials; overridable per call or via GENMEDIA_PROVIDER. Speech prefers ElevenLabs so shipped products do not silently change voice - Veo long-running operations are polled to completion; results carry native synchronized audio, removing the separate voiceover and mux stages - Google PCM speech output is wrapped in a WAV container so ffmpeg needs no out-of-band format hints - generateBatch bounds concurrency, preserves order and captures per-item errors instead of failing the run - Retries with exponential backoff and Retry-After on 429/5xx; client errors such as a rejected prompt fail immediately 53 new tests, all provider calls exercised through an injected fetch so the suite runs offline and without credentials. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
||
| it('should generate music from a Vertex prediction', async function () { | ||
| process.env.GOOGLE_CLOUD_PROJECT = 'proj'; | ||
| process.env.GOOGLE_ACCESS_TOKEN = 'ya29.test'; |
ThreatCrush Security Scan1 finding(s) LOW: 1
Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Seven repos in the portfolio —
viral-video,makedemo,amazon-affiliate,reeleel,brisk.news,bl0ggers,intr0s— have each independently rebuilt the same pipeline: script → images → TTS → ffmpeg mux → MP4.amazon-affiliatealone carries 331 ffmpeg references and 77 ElevenLabs references. This repo already owns 491 ffmpeg references and no generation at all, which makes it the natural place for the shared layer.What
One interface for generating images, video, speech and music, sitting next to the existing ffmpeg presets. Generated assets come back as ordinary files, so the current pipeline picks them up with no glue code.
No new runtime dependencies. Every provider is a plain
fetchagainst a documented REST endpoint, using the global fetch in Node 20+.googleGOOGLE_API_KEY(Lyria also needsGOOGLE_CLOUD_PROJECT+GOOGLE_ACCESS_TOKEN)openaiOPENAI_API_KEYelevenlabsELEVENLABS_API_KEYNotable behaviour
provider, or globally viaGENMEDIA_PROVIDER. Speech deliberately prefers ElevenLabs so shipped products don't silently change voice.generateBatchbounds concurrency, preserves input order, and captures per-item errors rather than failing the run — an unboundedPromise.allover a storyboard is the fastest route to 429s.Retry-Aftersupport on 429/5xx; client errors such as a rejected prompt fail immediately rather than burning the retry budget.registerProvider().Testing
53 new tests, all green. Every provider call is exercised through an injected
fetchImpl, so the suite runs offline and without credentials.The other 50 failures in the full suite are pre-existing and unrelated — this box has no ffmpeg installed, and the count is identical with and without this branch (47 pre-existing passing either way).
examples/genmedia.jsis a runnable walkthrough; it was syntax-checked but deliberately not executed, since it would make billable API calls.🤖 Generated with Claude Code