Skip to content

feat(genmedia): provider-agnostic generative media layer - #13

Merged
ralyodio merged 1 commit into
masterfrom
feat/genmedia
Aug 13, 2026
Merged

feat(genmedia): provider-agnostic generative media layer#13
ralyodio merged 1 commit into
masterfrom
feat/genmedia

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

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-affiliate alone 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 fetch against a documented REST endpoint, using the global fetch in Node 20+.

Provider Capabilities Credentials
google image, video, speech, music GOOGLE_API_KEY (Lyria also needs GOOGLE_CLOUD_PROJECT + GOOGLE_ACCESS_TOKEN)
openai image, speech OPENAI_API_KEY
elevenlabs speech ELEVENLABS_API_KEY

Notable behaviour

  • Provider resolution picks the first preferred provider for a capability that actually has credentials configured. Overridable per call via provider, or globally via GENMEDIA_PROVIDER. Speech deliberately prefers ElevenLabs so shipped products don't silently change voice.
  • Veo returns synchronized audio, so the separate voiceover and mux stages can be dropped entirely from a short-video pipeline. Long-running operations are polled to completion with progress callbacks.
  • Google speech returns headerless PCM, which is wrapped in a WAV container automatically so ffmpeg needs no out-of-band format hints.
  • generateBatch bounds concurrency, preserves input order, and captures per-item errors rather than failing the run — an unbounded Promise.all over a storyboard is the fastest route to 429s.
  • Retries use exponential backoff with Retry-After support on 429/5xx; client errors such as a rejected prompt fail immediately rather than burning the retry budget.
  • Custom providers can be registered with registerProvider().

Testing

53 new tests, all green. Every provider call is exercised through an injected fetchImpl, so the suite runs offline and without credentials.

npm run test:genmedia   # 53 passing

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.js is a runnable walkthrough; it was syntax-checked but deliberately not executed, since it would make billable API calls.

🤖 Generated with Claude Code

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>
Comment thread test/genmedia.test.js

it('should generate music from a Vertex prediction', async function () {
process.env.GOOGLE_CLOUD_PROJECT = 'proj';
process.env.GOOGLE_ACCESS_TOKEN = 'ya29.test';
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

1 finding(s)

LOW: 1

Severity Rule Location
LOW secret-generic-credential test/genmedia.test.js:611

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit 53064c5 into master Aug 13, 2026
6 checks passed
@ralyodio
ralyodio deleted the feat/genmedia branch August 13, 2026 15:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants