fix: suppress onnxruntime WSL2 device-discovery warning on every run

Pre-import onnxruntime at startup with stderr redirected to /dev/null,
so the harmless [W:onnxruntime:Default, device_discovery.cc:211] warning
about missing /sys/class/drm/card0/device/vendor is silenced before any
real output begins. Subsequent lazy imports (Silero VAD) hit the cache.

docs(skill): add missing ASS/LRC/HTML trigger phrases and batch chapters caveat

- Add 'ASS subtitles', 'aegisub format', 'LRC subtitles', 'timed lyrics',
  'HTML transcript', 'confidence-colored transcript' to trigger phrases
- Note that --chapters-file takes a single path and overwrites in batch mode
This commit is contained in:
ThePlasmak
2026-02-18 17:30:01 +08:00
parent c0ddd86426
commit 01f130b1eb
2 changed files with 35 additions and 9 deletions
+6 -1
View File
@@ -42,6 +42,9 @@ Use this skill when you need to:
"find where X is mentioned", "search transcript for", "when did they say", "at what timestamp",
"add chapters", "detect chapters", "find breaks in the audio", "table of contents for this recording",
"TTML subtitles", "DFXP subtitles", "broadcast format subtitles", "Netflix format",
"ASS subtitles", "aegisub format", "advanced substation alpha", "mpv subtitles",
"LRC subtitles", "timed lyrics", "karaoke subtitles", "music player lyrics",
"HTML transcript", "confidence-colored transcript", "color-coded transcript",
"separate audio per speaker", "export speaker audio", "split by speaker",
"transcript as CSV", "spreadsheet output", "transcribe podcast", "podcast RSS feed",
"different languages in batch", "per-file language",
@@ -102,6 +105,7 @@ Use this skill when you need to:
- `--chapter-format youtube` (default) outputs YouTube-ready timestamps; use `json` for programmatic use
- **Always use `--chapters-file PATH`** when combining chapters with a transcript output — avoids mixing chapter markers into the transcript text
- If the user only wants chapters (not the transcript), pipe stdout to a file with `-o /dev/null` and use `--chapters-file`
- **Batch mode limitation:** `--chapters-file` takes a single path — in batch mode, each file's chapters overwrite the previous. For batch chapter detection, omit `--chapters-file` (chapters print to stdout under `=== CHAPTERS (N) ===`) or use a separate run per file
**Speaker audio export:**
- Only add `--export-speakers DIR` when the user explicitly asks to save each speaker's audio separately
@@ -116,10 +120,11 @@ Use this skill when you need to:
**RSS / Podcast:**
- Only add `--rss URL` when the user provides a podcast RSS feed URL
- Default fetches 5 newest episodes; `--rss-latest 0` for all; `--skip-existing` to resume safely
- **Always use `-o <dir>`** with `--rss` — without it, all episode transcripts print to stdout concatenated, which is hard to use; each episode gets its own file when `-o <dir>` is set
**Output format for agent relay:**
- **Search results** (`--search`) → print directly to user; output is human-readable
- **Chapter output** → if no `--chapters-file`, chapters appear in stdout under `=== CHAPTERS (N) ===` header after the transcript
- **Chapter output** → if no `--chapters-file`, chapters appear in stdout under `=== CHAPTERS (N) ===` header after the transcript; with `--format json`, chapters are also embedded in the JSON under `"chapters"` key
- **Subtitle formats** (SRT, VTT, ASS, LRC, TTML) → always write to `-o` file; tell the user the output path, never paste raw subtitle content
- **Data formats** (CSV, HTML, TTML, JSON) → always write to `-o` file; tell the user the output path, don't paste raw XML/CSV/HTML
- **ASS format** → for Aegisub, VLC, mpv; write to file and tell user they can open it in Aegisub or play it in VLC/mpv
+29 -8
View File
@@ -1827,6 +1827,22 @@ def format_result(result, fmt, max_words_per_line=None, max_chars_per_line=None)
# ---------------------------------------------------------------------------
def main():
# Pre-import onnxruntime silently to suppress the harmless WSL2 device-discovery warning.
# onnxruntime writes directly to stderr fd when first imported (device_discovery.cc:211).
# By importing it here with fd 2 redirected, we populate sys.modules so that later
# lazy imports (faster_whisper's SileroVADModel) hit the cache instead of re-triggering.
try:
_old_stderr_fd = os.dup(2)
try:
with open(os.devnull, "wb") as _devnull:
os.dup2(_devnull.fileno(), 2)
import onnxruntime as _ort # noqa: F401
finally:
os.dup2(_old_stderr_fd, 2)
os.close(_old_stderr_fd)
except Exception:
pass # If anything goes wrong, just continue — stderr stays intact
# Early exit handlers — must run BEFORE argparse so they work without AUDIO positional arg
_SCRIPT_DIR = Path(__file__).parent
@@ -2451,7 +2467,7 @@ def main():
if compute_type == "auto":
compute_type = "float16" if device == "cuda" else "int8"
if cuda_ok and compute_type == "float16" and args.compute_type == "auto":
if cuda_ok and compute_type == "float16" and args.compute_type == "auto" and not args.quiet:
import re as _re
gpu_name = gpu_name or ""
if _re.search(r"RTX 30[0-9]{2}", gpu_name, _re.IGNORECASE):
@@ -2703,6 +2719,15 @@ def main():
lang = r.get("language", "xx")
model_name = args.model
# ---- Pre-compute chapters (must happen before output formatting for JSON embedding) ----
# Stored in _computed_chapters so the display block below can reuse it without a second call.
_computed_chapters = None
if getattr(args, "detect_chapters", False) and r.get("segments"):
_computed_chapters = detect_chapters(r["segments"], min_gap=args.chapter_gap)
_formats_list = getattr(args, "_formats", [args.format])
if "json" in _formats_list:
r["chapters"] = _computed_chapters # embed in JSON output
# ---- Transcript search mode ----
if getattr(args, "search", None):
matches = search_transcript(
@@ -2769,9 +2794,9 @@ def main():
print(f"\n=== {r['file']} ===")
print(output)
# ---- Chapter detection ----
if getattr(args, "detect_chapters", False) and r.get("segments"):
chapters = detect_chapters(r["segments"], min_gap=args.chapter_gap)
# ---- Chapter detection output ----
if _computed_chapters is not None:
chapters = _computed_chapters # reuse pre-computed result
chapters_output = format_chapters_output(chapters, fmt=args.chapter_format)
if not args.quiet:
if not chapters or len(chapters) == 1:
@@ -2797,10 +2822,6 @@ def main():
# Print to stdout after transcript — clear header so agents can parse it separately
print(f"\n=== CHAPTERS ({len(chapters)}) ===\n{chapters_output}")
# For JSON output, embed chapters in the result too
if args.format == "json":
r["chapters"] = chapters
# Write stats sidecar
_write_stats(r, args)