68 行
1.8 KiB
TypeScript
68 行
1.8 KiB
TypeScript
import { ENV } from "./_core/env";
|
|
import { fetchWithTimeout } from "./_core/fetch";
|
|
|
|
export type RemoteMediaSession = {
|
|
id: string;
|
|
userId: string;
|
|
title: string;
|
|
archiveStatus: "idle" | "queued" | "processing" | "completed" | "failed";
|
|
previewStatus?: "idle" | "processing" | "ready" | "failed";
|
|
previewSegments?: number;
|
|
markers?: Array<{
|
|
id: string;
|
|
type: string;
|
|
label: string;
|
|
timestampMs: number;
|
|
confidence?: number;
|
|
createdAt: string;
|
|
}>;
|
|
playback: {
|
|
webmUrl?: string;
|
|
mp4Url?: string;
|
|
webmSize?: number;
|
|
mp4Size?: number;
|
|
ready: boolean;
|
|
previewUrl?: string;
|
|
};
|
|
lastError?: string;
|
|
};
|
|
|
|
function getMediaBaseUrl() {
|
|
if (!ENV.mediaServiceUrl) {
|
|
throw new Error("MEDIA_SERVICE_URL is not configured");
|
|
}
|
|
return ENV.mediaServiceUrl.replace(/\/+$/, "");
|
|
}
|
|
|
|
function getMediaCandidateUrls(path: string) {
|
|
const baseUrl = getMediaBaseUrl();
|
|
if (baseUrl.endsWith("/media")) {
|
|
return [`${baseUrl}${path}`];
|
|
}
|
|
return [`${baseUrl}${path}`, `${baseUrl}/media${path}`];
|
|
}
|
|
|
|
export async function getRemoteMediaSession(sessionId: string) {
|
|
let lastError: Error | null = null;
|
|
|
|
for (const url of getMediaCandidateUrls(`/sessions/${encodeURIComponent(sessionId)}`)) {
|
|
const response = await fetchWithTimeout(url, undefined, {
|
|
timeoutMs: ENV.mediaFetchTimeoutMs,
|
|
retries: ENV.mediaFetchRetryCount,
|
|
retryMethods: ["GET"],
|
|
});
|
|
if (response.ok) {
|
|
const payload = await response.json() as { session: RemoteMediaSession };
|
|
return payload.session;
|
|
}
|
|
|
|
const message = await response.text().catch(() => response.statusText);
|
|
lastError = new Error(`Media service request failed (${response.status}): ${message}`);
|
|
if (response.status !== 404) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
throw lastError ?? new Error("Media service request failed");
|
|
}
|