Skip to content

feat(openrouter): sync video generation models as v2-only - #10605

Merged
rekram1-node merged 1 commit into
devfrom
openrouter-video
Oct 21, 2026
Merged

rekram1-node merged 1 commit into
devfrom
openrouter-video

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

OpenRouter lists 30 video-only models (output_modalities=["video"]) that the sync skips. /models reports "0" prices for them; the real prices are the pricing_skus in GET /api/v1/videos/models, which use about 45 SKU names. This follows #10593 (speech, transcription, embedding and rerank) and #10603 (images, merged). It's built on top of the image code and reuses its fetch helper, base-model resolution and price-entry builder.

Change

 fetchModels
   GET /models?output_modalities=text,decisions
-  GET /models?output_modalities=speech,transcription,embeddings,rerank
+  GET /models?output_modalities=speech,transcription,embeddings,rerank,video
+  GET /videos/models  → pricing_skus attached to each video model
 translateModel
   mediaType(model)
+    "video" → v2 doc: type video, base_model, [api.videos], cost from pricing_skus

Each file is v2_only = true, uses base_model, and authors [api.videos] (POST /api/v1/videos; @openrouter/ai-sdk-provider has videoModel).

SKU → CostV2

SKU pattern CostV2
cents_per_second_output[_res], cents_per_video_output_second_res video.output, unit = "second", cents ÷ 100
cents_per_second_video_continuation_res same, when.input_video = true
duration_seconds[_with|_without_audio][_res] video.output per second (USD), when.generate_audio
text_to_video_ / image_to_video_ / reference_ prefix when.mode = text-to-video / image-to-video / reference-to-video (OpenRouter's generation modes)
video_tokens[_res][_with_video_input|_without_audio] video.output per 1M tokens, when.input_video / generate_audio
cents_per_image_input, reference_images, reference_input_images image.input, unit = "image"
_480p … _1080p, _2k, _4k when.resolution with OpenRouter's request values (480p, 2K, 4K)
videoCost(skus)
  parse every SKU; any unknown or unrepresentable SKU → no cost
  base = plain SKU, else the first one
  for each other SKU, fewest conditions first
    if base + earlier overrides already give its price → skip
    else add override { when: its qualifiers, price }
# google/veo-3.1
[cost.video.output]
unit = "second"
price = 0.4

[[cost.video.output.overrides]]
when = { generate_audio = { equals = false } }
price = 0.2

[[cost.video.output.overrides]]
when = { resolution = { equals = "4K" }, generate_audio = { equals = true } }
price = 0.6

[[cost.video.output.overrides]]
when = { resolution = { equals = "4K" }, generate_audio = { equals = false } }
price = 0.4

generate_audio defaults to true for models with audio (OpenRouter docs), and billing follows that default. Live, Kling 3.0 Std billed $0.63 with no flag and $0.42 with generate_audio: false, which is 5 s × $0.126 and 5 s × $0.084. None of today's SKUs vary by duration.

Unrepresentable prices (no [cost] on these 2)

Model SKU Why
runway/aleph-2 minimum_cents_per_generation = 56 CostV2 has no minimum charge
black-forest-labs/flux-video-upscale cents_per_megapixel_second_precise / _creative megapixel × second isn't a unit

Also noted but not in the SKUs: Kling billed a 3.04 s clip as 5 seconds (see above). Its per-second prices hold from 5 s up.

Lab files

19 new, all v2-only:

models/
├── heygen/             heygen-video-1, avatar-iv
├── black-forest-labs/  flux-3-video, flux-video-edit, flux-video-upscale
├── minimax/            MiniMax-H3-Max
├── alibaba/            wan3.0-video, wan3.0-video-prime, wan2.7, wan2.6, happyhorse-1.0, happyhorse-1.1
├── bytedance-seed/     seedance-2.0-mini, seedance-1.5-pro
├── runway/             gen-4.5, aleph-2
└── kuaishou/           kling-v3.0-pro, kling-v3.0-std, kling-video-o1

Reused: minimax/MiniMax-H3 and MiniMax-Hailuo-2.3, bytedance-seed/seedance-2.0/-2.0-fast/-2.5, xai/grok-imagine-video/-1.5/-1.5-lite, and the three google/veo-3.1*-generate-preview labs (OpenRouter's google/veo-3.1*; the file keeps OpenRouter's name, "Veo 3.1"). OpenRouter's bytedance/ and kwaivgi/ prefixes map to bytedance-seed and kuaishou through a media-only table, so chat models under those prefixes don't change. Each new lab cites its release date and its input formats. New labs output video/mp4 only; generated sound is a track inside the MP4, so they add no generic audio output.

Out of scope

  • generate-v2 still derives api from v1 fields, so the v2 output shows chat-completions instead of videos (known, deferred).

Verification

  • bun packages/core/src/sync/index.ts openrouter --dry-run --no-issues: dev showed 0 created / 7 updated (live DeepSeek, MiMo and GLM price churn) / 566 unchanged. The 30 files come from a real sync run on this branch (30 created), with the 7 unrelated updates reverted; the dry run afterwards shows 0 created and only the same 7 updates.
  • bun run v1:check: v1 output is byte-identical.
  • bun validate: passes.
  • bun test: same 11 failures as dev. 6 new OpenRouter video tests pass: type mapping, per second with resolution and continuation, audio and mode overrides, per-token SKUs, unrepresentable SKUs, and base_model/standalone files.
  • Live: Grok Imagine Video 1.5 Lite 1 s 480p billed $0.02 (= base). Kling checks are above.
  • v2 output (_experimental_v2.0_api.json): all 30 present with type = "video", video/mp4 and their costs.

@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Oct 20, 2026
@rekram1-node
rekram1-node enabled auto-merge (squash) October 20, 2026 23:48
@rekram1-node
rekram1-node disabled auto-merge October 20, 2026 23:48
@github-actions github-actions Bot removed the reviewer: ready Automated review found no actionable items label Oct 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Oct 20, 2026
@github-actions github-actions Bot removed the reviewer: ready Automated review found no actionable items label Oct 21, 2026
@rekram1-node
rekram1-node merged commit d6c7296 into dev Oct 21, 2026
2 checks passed
@rekram1-node
rekram1-node deleted the openrouter-video branch October 21, 2026 02:25
@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@github-actions github-actions Bot added the reviewer: ready Automated review found no actionable items label Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reviewer: ready Automated review found no actionable items

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant