From c28e08b3aa91bf9e79965c9a2a0b2acea64ac177 Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Sat, 12 Sep 2026 18:35:06 +0000 Subject: [PATCH] Fix: transcribe.py nu mai sterge audio daca transcrierea nu pare completa Cauza: am rulat `find transcripts -size -1k -delete` cat transcribe.py scria in acelasi director. faster_whisper scrie bufferat, deci o transcriere de o ora sta sub 1KB minute in sir; find a sters fisierul de sub proces, Python a logat "Transcribed" pe un inode disparut, si audio-ul a fost sters. Lectia 11 (25.11.2025) pierduta complet, re-descarcata. - transcribe_file() intoarce bool, verifica nr. cuvinte vs durata audio - pull_moltbot.sh: staging + mutare doar peste 1KB, in loc de find -delete - PROGRESS.md: documentat, ca sa nu se repete Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01MtSTyTmt6AbCL9j5ajEDm1 --- PROGRESS.md | 18 +++++++++++++++++ pull_moltbot.sh | 27 ++++++++++++++++++++++++++ transcribe.py | 27 ++++++++++++++++++++++---- transcripts/09_Q_and_A/12_18112025.txt | 0 4 files changed, 68 insertions(+), 4 deletions(-) create mode 100755 pull_moltbot.sh create mode 100644 transcripts/09_Q_and_A/12_18112025.txt diff --git a/PROGRESS.md b/PROGRESS.md index d01bdf2..6c1717e 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -169,6 +169,24 @@ exemple long+short, minim 2-3 exemple numerice, secțiune obligatorie referințe web reale). **Citește-l integral înainte de orice lecție nouă.** ## Probleme întâlnite + fix-uri +- **NU rula `find -size -1k -delete` cât rulează + `transcribe.py`.** Greșeală făcută pe 2026-09-12: am folosit-o ca să curăț + fișierele goale aduse de pe moltbot, în timp ce transcrierea locală scria + în același director. `faster_whisper` ține fișierul deschis și scrie + bufferat — o transcriere de o oră stă sub 1KB minute în șir. `find` a + șters fișierul de sub proces; la final Python a închis un handle către un + inode dispărut, a logat "Transcribed" ca și cum ar fi reușit, iar + `transcribe.py` a șters și audio-ul. Lecția 11 (25.11.2025) a fost pierdută + complet și a trebuit re-descărcată. + Fix-uri aplicate: + - `pull_moltbot.sh` — aduce în staging, mută doar fișierele peste 1KB. + Folosește-l în loc de `scp` + `find -delete`. + - `transcribe.py` — `transcribe_file()` întoarce acum bool și **verifică + numărul de cuvinte față de durata audio** (prag: 15% din 100 cuvinte/min) + înainte ca apelantul să șteargă audio-ul. Un fișier dispărut sau o + transcriere suspect de scurtă păstrează audio-ul, deci pierzi doar timp + de CPU, nu și descărcarea. + - **Halucinație whisper** (propoziții repetate în buclă): a apărut la `05_MODUL_4/02_3_STRATEGIA_5_MDSRT.txt`. Fix: re-extrage audio pentru lecția aia (`extract_audio.py` are funcțiile reutilizabile), retranscrie diff --git a/pull_moltbot.sh b/pull_moltbot.sh new file mode 100755 index 0000000..3ae7bd4 --- /dev/null +++ b/pull_moltbot.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Aduce transcrierile gata de pe moltbot. +# +# NU folosi `scp ... && find -size -1k -delete` pe directorul de transcrieri: +# transcribe.py scrie acolo în paralel, iar un fișier în curs de scriere e +# sub 1KB minute în șir. Un `find -delete` l-a șters o dată de sub proces, +# iar transcrierea s-a pierdut complet (audio-ul fusese deja șters). +# +# Aici: aducem într-un director de staging, mutăm doar ce e complet. +set -euo pipefail +DEST=${1:-transcripts/09_Q_and_A} +STAGE=$(mktemp -d) +trap 'rm -rf "$STAGE"' EXIT + +scp -q "root@moltbot:/root/atm/transcripts/*.txt" "$STAGE/" 2>/dev/null || true +moved=0 +for f in "$STAGE"/*.txt; do + [ -e "$f" ] || continue + if [ "$(stat -c%s "$f")" -lt 1024 ]; then + echo " sar peste (incomplet, $(stat -c%s "$f") octeți): $(basename "$f")" + continue + fi + mv "$f" "$DEST/" + echo " adus: $(basename "$f")" + moved=$((moved + 1)) +done +echo "Aduse $moved transcrieri în $DEST" diff --git a/transcribe.py b/transcribe.py index 83cb9e7..74e6a72 100644 --- a/transcribe.py +++ b/transcribe.py @@ -16,13 +16,32 @@ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(me log = logging.getLogger(__name__) -def transcribe_file(model: WhisperModel, audio_path: Path, txt_path: Path) -> None: +# Vorbirea normală dă ~100-150 cuvinte/minut. Sub 15% din asta înseamnă +# halucinație, tăcere, sau o scriere care a eșuat — nu o transcriere bună. +MIN_WORDS_PER_SECOND = 100 / 60 * 0.15 + + +def transcribe_file(model: WhisperModel, audio_path: Path, txt_path: Path) -> bool: + """Întoarce True doar dacă transcrierea rezultată pare completă. + Apelantul șterge audio-ul DOAR pe True — altfel un fișier pierdut + înseamnă re-descărcare, nu doar re-transcriere.""" segments, info = model.transcribe(str(audio_path), language="ro", beam_size=5, vad_filter=True) txt_path.parent.mkdir(parents=True, exist_ok=True) with open(txt_path, "w", encoding="utf-8") as f: for seg in segments: f.write(seg.text.strip() + "\n") - log.info(f" Transcribed: {txt_path.name} (lang={info.language}, duration={info.duration:.0f}s)") + + if not txt_path.exists(): + log.error(f" {txt_path} a dispărut în timpul scrierii — păstrez audio-ul") + return False + words = len(txt_path.read_text(encoding="utf-8").split()) + expected = info.duration * MIN_WORDS_PER_SECOND + if words < expected: + log.error(f" {txt_path.name}: doar {words} cuvinte pentru {info.duration:.0f}s " + f"(minim așteptat {expected:.0f}) — păstrez audio-ul") + return False + log.info(f" Transcribed: {txt_path.name} (lang={info.language}, duration={info.duration:.0f}s, {words} cuvinte)") + return True def main(): @@ -55,8 +74,8 @@ def main(): continue log.info(f"Transcribing: {audio_path}") - transcribe_file(model, audio_path, txt_path) - if not args.keep_audio: + ok = transcribe_file(model, audio_path, txt_path) + if ok and not args.keep_audio: audio_path.unlink() done += 1 diff --git a/transcripts/09_Q_and_A/12_18112025.txt b/transcripts/09_Q_and_A/12_18112025.txt new file mode 100644 index 0000000..e69de29