v0.2.11 /relay/capabilities + /relay/transcribe-url (yt-dlp in container)
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
// GET /relay/capabilities — operator-aware metadata for Recap clients
|
||||
// to plan their audio handling. Returns the upper bounds the relay's
|
||||
// CURRENT routing config can comfortably accept, so Recap can decide
|
||||
// whether to chunk a long video before sending it.
|
||||
//
|
||||
// Today's logic:
|
||||
// - When the operator's transcribe_backend_preference routes through
|
||||
// Gemini at all (gemini_first / gemini_only), we report Gemini-safe
|
||||
// limits (60 min / 30 MB / 2700 s chunks). Even with hardware as
|
||||
// overflow, the FIRST attempt is Gemini, which needs the chunk
|
||||
// budget.
|
||||
// - When the operator's preference is hardware-only (or hardware-
|
||||
// first with overflow to Gemini disabled in spirit), we report
|
||||
// "unbounded" — the operator's Parakeet wrapper can typically
|
||||
// ingest 2+ hour podcasts in a single shot, so chunking just adds
|
||||
// extra inference passes and timestamp-stitching overhead.
|
||||
//
|
||||
// Recap reads this once on boot + on policy refresh; when its
|
||||
// transcriptionProvider is "relay", it honors these limits instead of
|
||||
// its own hardcoded thresholds. For non-relay providers, Recap's
|
||||
// internal per-provider thresholds apply.
|
||||
|
||||
import express from "express";
|
||||
import { getConfigSnapshot } from "../config.js";
|
||||
|
||||
export function capabilitiesRouter() {
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/capabilities", async (_req, res) => {
|
||||
const cfg = await getConfigSnapshot();
|
||||
const txPref =
|
||||
cfg.relay_transcribe_backend_preference || "gemini_first";
|
||||
const hasParakeet = !!cfg.relay_parakeet_base_url;
|
||||
|
||||
// Conservative default: Gemini-safe limits unless the operator has
|
||||
// explicitly said "use hardware (only or first) and I've got a
|
||||
// Parakeet endpoint wired up". Without the Parakeet endpoint we
|
||||
// can't make use of larger inputs — Gemini's the only path —
|
||||
// so we'd just be lying to the client.
|
||||
const hardwareCapable =
|
||||
hasParakeet && (txPref === "hardware_only" || txPref === "hardware_first");
|
||||
|
||||
if (hardwareCapable) {
|
||||
res.json({
|
||||
// Effective unbounded — Parakeet wrappers commonly handle 2+
|
||||
// hour audio in one shot. Set high but finite ceilings so a
|
||||
// 24-hour file doesn't OOM the operator's GPU box silently.
|
||||
max_audio_mb: 500,
|
||||
max_audio_minutes: 240,
|
||||
preferred_chunk_seconds: null,
|
||||
// Diagnostic — Recap doesn't need this but the dashboard / a
|
||||
// curious operator might want to know which limit shape they
|
||||
// returned and why.
|
||||
reason: "hardware-capable backend preference (" + txPref + ")",
|
||||
});
|
||||
} else {
|
||||
res.json({
|
||||
// Gemini File-API + practical reliability limits. Matches
|
||||
// Recap's pre-relay defaults so existing chunking behavior
|
||||
// is preserved.
|
||||
max_audio_mb: 30,
|
||||
max_audio_minutes: 60,
|
||||
preferred_chunk_seconds: 2700, // 45 min chunks
|
||||
reason: "Gemini-backed preference (" + txPref + ")",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
Reference in New Issue
Block a user