Skip to content

getVideoContent() rejects video/mp4 responses (only accepts application/octet-stream) #506

Description

@tombeckenham

Summary

videoGeneration.getVideoContent() throws on a successful download. The video-content endpoint returns 200 with Content-Type: video/mp4 and a valid MP4 body, but the generated client only accepts application/octet-stream, so the response fails to match and the call errors instead of returning the stream.

This is the TypeScript counterpart of OpenRouterTeam/python-sdk#175 (get_video_content raise error because of the mismatch Content-Type) — same root cause, both SDKs generated from the same spec.

Version

@openrouter/sdk@0.12.79

Reproduction

import { OpenRouter } from '@openrouter/sdk'

const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY })

// 1. Submit + poll to completion
const job = await client.videoGeneration.generate({
  videoGenerationRequest: {
    model: 'bytedance/seedance-2.0-fast',
    prompt: 'A red balloon rising in a blue sky',
    duration: 4,
  },
})
let s = await client.videoGeneration.getGeneration({ jobId: job.id })
while (s.status !== 'completed' && s.status !== 'failed') {
  await new Promise((r) => setTimeout(r, 5000))
  s = await client.videoGeneration.getGeneration({ jobId: job.id })
}

// 2. Download the completed content — throws
const stream = await client.videoGeneration.getVideoContent({ jobId: job.id })

Observed

Unexpected Status or Content-Type: Status 200 Content-Type video/mp4
Body:  ftypisom�isomiso2avc1mp41 ...

The body is a valid MP4 — note the ftypisom signature. Downloading the same unsigned_urls[0] manually confirms it:

GET <unsigned_urls[0]>  (Authorization: Bearer <key>)
→ 200, content-type: video/mp4, 1,497,720 bytes, starts with `ftypisom`

Root cause

In esm/funcs/videoGenerationGetVideoContent.js:

  • the request sends Accept: "application/octet-stream", and
  • the response is matched with M.stream(200, …) keyed to the octet-stream content type,

while the upstream provider (Seedance 2.0, and presumably all video models) serves Content-Type: video/mp4. The spec types the content response as application/octet-stream; the live endpoint does not honor that, so the generated matcher rejects every real download.

Suggested fix

Have the video-content operation accept the actual media content types (video/mp4, ideally video/* / any 2xx body) as a passthrough stream, rather than only application/octet-stream — matching what the endpoint returns. Same change is needed in python-sdk (#175).

Context / downstream impact

Surfaced while building an OpenRouter video adapter for TanStack AI (TanStack/ai#740). We work around it by downloading unsigned_urls[0] directly with the Authorization header instead of using getVideoContent; filing here so the SDK path can eventually be used.

Refs: OpenRouterTeam/python-sdk#175

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions