Skip to content

Commit b82e790

Browse files
committed
fix(openai-base): prefer videos.retrieve URL for video content
Main's OpenAI video adapter and the aimock E2E harness both surface the final video URL on the video resource itself rather than via a separate /content endpoint. The openai-base extraction was calling client.videos.downloadContent() first — which exists on the current SDK — causing it to hit a /content endpoint aimock doesn't serve and fail every openai video-gen E2E test. Reorder getVideoUrl to prefer the retrieve-returns-url path (matching main's behavior) and only fall through to SDK download methods when retrieve doesn't surface a URL. Also drop the erroneous * 1000 on expires_at (OpenAI returns it in ms already, matching main).
1 parent 247bb33 commit b82e790

1 file changed

Lines changed: 23 additions & 17 deletions

File tree

  • packages/typescript/openai-base/src/adapters

packages/typescript/openai-base/src/adapters/video.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,25 @@ export class OpenAICompatibleVideoAdapter<
126126
try {
127127
const client = this.client as any
128128

129-
let response: any
129+
// Prefer retrieve() because many openai-compatible backends (and the
130+
// aimock test harness) return the URL directly on the video resource
131+
// and do not implement a separate /content endpoint. Subclasses can
132+
// override this method if they need to download raw bytes via
133+
// downloadContent()/content().
134+
const videoInfo = await client.videos.retrieve(jobId)
135+
if (videoInfo.url) {
136+
return {
137+
jobId,
138+
url: videoInfo.url,
139+
expiresAt: videoInfo.expires_at
140+
? new Date(videoInfo.expires_at)
141+
: undefined,
142+
}
143+
}
130144

145+
// SDK download fall-through: try the various possible method names in
146+
// decreasing order of modernity.
131147
if (typeof client.videos?.downloadContent === 'function') {
132-
// OpenAI SDK's downloadContent returns raw video bytes as a Response
133148
const contentResponse = await client.videos.downloadContent(jobId)
134149
const videoBlob = await contentResponse.blob()
135150
const buffer = await videoBlob.arrayBuffer()
@@ -141,26 +156,17 @@ export class OpenAICompatibleVideoAdapter<
141156
url: `data:${mimeType};base64,${base64}`,
142157
expiresAt: undefined,
143158
}
144-
} else if (typeof client.videos?.content === 'function') {
159+
}
160+
161+
let response: any
162+
if (typeof client.videos?.content === 'function') {
145163
response = await client.videos.content(jobId)
146164
} else if (typeof client.videos?.getContent === 'function') {
147165
response = await client.videos.getContent(jobId)
148166
} else if (typeof client.videos?.download === 'function') {
149167
response = await client.videos.download(jobId)
150168
} else {
151-
// Fallback: check if retrieve returns the URL directly
152-
const videoInfo = await client.videos.retrieve(jobId)
153-
if (videoInfo.url) {
154-
return {
155-
jobId,
156-
url: videoInfo.url,
157-
expiresAt: videoInfo.expires_at
158-
? new Date(videoInfo.expires_at * 1000)
159-
: undefined,
160-
}
161-
}
162-
163-
// Fetch and return a data URL
169+
// Last resort: raw fetch with auth header.
164170
const baseUrl = this.clientConfig.baseURL || 'https://api.openai.com/v1'
165171
const apiKey = this.clientConfig.apiKey
166172

@@ -205,7 +211,7 @@ export class OpenAICompatibleVideoAdapter<
205211
jobId,
206212
url: response.url,
207213
expiresAt: response.expires_at
208-
? new Date(response.expires_at * 1000)
214+
? new Date(response.expires_at)
209215
: undefined,
210216
}
211217
} catch (error: any) {

0 commit comments

Comments
 (0)