sourav-das's picture
Upload folder using huggingface_hub
a0f35dd verified
import type {
OriginalTrackAsset,
OutputFormat,
SourceKind,
StemAsset,
StemResult,
} from "./types";
export interface SourceImportResponse {
job_id: string;
filename: string;
source_url: string;
resolved_url?: string;
title?: string;
platform: Exclude<SourceKind, "file">;
}
export async function uploadFile(
file: File,
onProgress?: (progress: number) => void
): Promise<{ job_id: string; filename: string }> {
const formData = new FormData();
formData.append("file", file);
const xhr = new XMLHttpRequest();
return new Promise((resolve, reject) => {
xhr.upload.addEventListener("progress", (e) => {
if (e.lengthComputable && onProgress) {
onProgress(e.loaded / e.total);
}
});
xhr.addEventListener("load", () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.responseText));
} else {
try {
const err = JSON.parse(xhr.responseText);
reject(new Error(err.detail || `Upload failed (${xhr.status})`));
} catch {
reject(new Error(`Upload failed (${xhr.status})`));
}
}
});
xhr.addEventListener("error", () => reject(new Error("Upload failed")));
xhr.open("POST", "/api/upload");
xhr.send(formData);
});
}
export async function importUrl(
url: string
): Promise<SourceImportResponse> {
const res = await fetch("/api/import-url", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url }),
});
if (!res.ok) {
const err = await res.json().catch(() => ({ detail: "Request failed" }));
throw new Error(err.detail || `Import failed (${res.status})`);
}
return res.json();
}
export async function startSeparation(
jobId: string,
stems: string[],
outputFormat: OutputFormat
): Promise<void> {
const res = await fetch("/api/separate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ job_id: jobId, stems, output_format: outputFormat }),
});
if (!res.ok) {
const err = await res.json().catch(() => ({ detail: "Request failed" }));
throw new Error(err.detail || `Separation failed (${res.status})`);
}
}
export interface ProgressEvent {
state: string;
progress: number;
message: string;
stems?: Record<string, string>;
error?: string;
}
export function subscribeProgress(
jobId: string,
onEvent: (event: ProgressEvent) => void,
onDone: (stems: StemResult[]) => void,
onError: (error: string) => void
): () => void {
const es = new EventSource(`/api/progress/${jobId}`);
let closedByApp = false;
let terminalEventSeen = false;
let errorTimer: number | null = null;
const clearErrorTimer = () => {
if (errorTimer !== null) {
window.clearTimeout(errorTimer);
errorTimer = null;
}
};
es.onopen = () => {
clearErrorTimer();
};
es.onmessage = (e) => {
try {
const data: ProgressEvent = JSON.parse(e.data);
clearErrorTimer();
onEvent(data);
if (data.state === "done" && data.stems) {
terminalEventSeen = true;
const stemList: StemResult[] = Object.entries(data.stems).map(
([name, filename]) => ({ name, filename })
);
onDone(stemList);
closedByApp = true;
es.close();
} else if (data.state === "error") {
terminalEventSeen = true;
onError(data.error || "Separation failed");
closedByApp = true;
es.close();
}
} catch {
// ignore parse errors
}
};
es.onerror = () => {
if (closedByApp || terminalEventSeen) {
return;
}
if (es.readyState === EventSource.CLOSED) {
onError("Connection to server lost");
closedByApp = true;
es.close();
return;
}
if (errorTimer === null) {
errorTimer = window.setTimeout(() => {
errorTimer = null;
if (!closedByApp && !terminalEventSeen && es.readyState !== EventSource.OPEN) {
onError("Connection to server lost");
closedByApp = true;
es.close();
}
}, 5000);
}
};
return () => {
closedByApp = true;
clearErrorTimer();
es.close();
};
}
export interface ExampleOutputResponse {
song?: string;
original: OriginalTrackAsset;
stems: StemAsset[];
downloadAllUrl: string;
}
export async function fetchExampleOutput(): Promise<ExampleOutputResponse> {
const res = await fetch("/api/examples/default");
if (!res.ok) {
const err = await res.json().catch(() => ({ detail: "Request failed" }));
throw new Error(err.detail || `Example load failed (${res.status})`);
}
return res.json();
}
export function getAudioUrl(jobId: string, filename: string): string {
return `/api/audio/${jobId}/${encodeURIComponent(filename)}`;
}
export function getDownloadUrl(jobId: string, filename: string): string {
return `/api/download/${jobId}/${encodeURIComponent(filename)}`;
}
export function getDownloadAllUrl(jobId: string): string {
return `/api/download/${jobId}/all`;
}