tonhowtf/omniget · error

waveform_peaks/detect_shot_changes error surfaced to user…

Error message

waveform_peaks/detect_shot_changes error surfaced to user via err() (localized toast)

What it means

loadMedia computes waveform peaks and shot-change timestamps via Rust commands waveform_peaks and detect_shot_changes; if either invoke rejects, err() shows the failure as a localized toast and peaks/shots stay empty (analysis features disabled for that media).

Solutions

  1. Check the toast text to identify which of the two invokes failed and why.
  2. Verify the media file exists and its codec is supported by the backend decoder (test with ffmpeg directly if bundled).
  3. Invoke waveform_peaks first in isolation to pinpoint the failing command.
  4. Handle the two invokes with separate try/catch so one failure doesn't discard the other's result.

Example fix

// before
try {
  peaks = await invoke<number[]>("waveform_peaks", { input: sel, buckets: 600 });
  shots = await invoke<number[]>("detect_shot_changes", { input: sel, threshold: 0.4 });
} catch (e) { err(e); }
// after
try { peaks = await invoke<number[]>("waveform_peaks", { input: sel, buckets: 600 }); } catch (e) { err(e); }
try { shots = await invoke<number[]>("detect_shot_changes", { input: sel, threshold: 0.4 }); } catch (e) { err(e); }
Defensive patterns

Strategy: validation

Validate before calling

if (!sel || typeof sel !== "string") return;
const exists = await invoke<boolean>("path_exists", { path: sel }).catch(() => false);
if (!exists) { showToast("error", $t("downloads.sw.media_missing")); return; }

Type guard

function isMediaPath(v: unknown): v is string {
  return typeof v === "string" && /\.(mp4|mkv|webm|mp3|wav|m4a|flac)$/i.test(v);
}

Try / catch

try {
  peaks = await invoke<number[]>("waveform_peaks", { input: sel, buckets: 600 });
  shots = await invoke<number[]>("detect_shot_changes", { input: sel, threshold: 0.4 });
} catch (e) {
  err(e);
} finally {
  busy = false;
}

Prevention

When it happens

Trigger: invoke('waveform_peaks',{input,buckets:600}) or invoke('detect_shot_changes',{input,threshold:0.4}) rejecting — media file missing/unreadable, unsupported codec/container that the backend decoder (e.g. ffmpeg) can't open, or backend decode failure.

Common situations: Selecting a video with a codec the bundled decoder lacks; huge files causing backend memory/time failures surfaced as invoke errors; media path changed since selection; backend ffmpeg integration missing.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/5cb10775229ee192. Report an issue: GitHub.

Appendix: source

Thrown at src/components/downloads/SubtitleWorkshop.svelte:86

      loadedPath = sel;
      peaks = [];
      shots = [];
    } catch (e) {
      err(e);
    } finally {
      busy = false;
    }
  }

  async function loadMedia() {
    const sel = await openDialog({ multiple: false });
    if (!sel || typeof sel !== "string") return;
    busy = true;
    try {
      peaks = await invoke<number[]>("waveform_peaks", { input: sel, buckets: 600 });
      shots = await invoke<number[]>("detect_shot_changes", { input: sel, threshold: 0.4 });
    } catch (e) {
      err(e);
    } finally {
      busy = false;
    }
  }

  function applyShift() {
    if (!shiftMs) return;
    cues = cues.map((c) => ({
      ...c,
      start_ms: Math.max(0, c.start_ms + shiftMs),
      end_ms: Math.max(0, c.end_ms + shiftMs),
    }));
  }

  function applyReplace() {
    if (!findText) return;
    let n = 0;
    cues = cues.map((c) => {

View on GitHub (pinned to 8600b91f42)