From f7107ff2a61004dfbed1f6725517b15fbc816a40 Mon Sep 17 00:00:00 2001 From: David Kifer Date: Sat, 17 Jan 2026 12:14:36 -0500 Subject: [PATCH] added changes --- .../__pycache__/translator.cpython-313.pyc | Bin 12671 -> 12753 bytes .../__pycache__/utils.cpython-313.pyc | Bin 12612 -> 13065 bytes .../ai_transcriber_v2/analyze_recovery.py | 122 + .../ai_transcriber_v2/job_history_odysseus.db | Bin 0 -> 12288 bytes .../logs/transcriber_odysseus_20260112.log | 3522 +++++++++++++++++ .../ai_transcriber_v2/recover_and_fix_v2.py | 6 +- .../ai_transcriber_v2/utils.py | 30 +- 7 files changed, 3666 insertions(+), 14 deletions(-) create mode 100755 video_transcription/ai_transcriber_v2/analyze_recovery.py create mode 100644 video_transcription/ai_transcriber_v2/job_history_odysseus.db create mode 100644 video_transcription/ai_transcriber_v2/logs/transcriber_odysseus_20260112.log diff --git a/video_transcription/ai_transcriber_v2/__pycache__/translator.cpython-313.pyc b/video_transcription/ai_transcriber_v2/__pycache__/translator.cpython-313.pyc index 7930d8867e89b2556cba308af1dbfa4924dcf559..71ece2e21d207c0cb0bda83ea709a065cecdac53 100644 GIT binary patch delta 124 zcmeyLbTOItGcPX}0}${fq-LgWOU#K+Ni9pw$u9s&>H}4#=Es*5CFT_;7iAWdWaj7TZ?@%_qs~>u Ymy(}Tkdc|EJNdT$Z^kW?uN$lY0K;7`4*&oF delta 42 xcmcbZ{6C5JGcPX}0}vQHr)I`(CuO2g9*G>66B!0!D&9_|NttmpI9O|3Cly z-#7ovnVG#l_RhHLp3`YV(2mJc`q%Yexb}0q#pskkqA4XSMMYsMEk^s5WG*Yoni`!_ zlZq%sCncgPvXDuL(v*}@CfQ&VG9@LU5kXdyBt5C66**c=af>GWknXn~$GeL^*}lbi z2mQ#=fcF-!I(Qxr6mNQe#`qw;=zGaD3}uiw{o9wa?_usBgCQ!HMYfGFca*^^3IOVOKdtuT6ZA%Pr*FEHmdvDK&EyE9pP=rV zZhWRVSo0_USmlGE>gMe%oj**{nne0aR3c@SDM@#~ERk$lRbiW6Bt#)(fSwA~yLYl2 zb5fC^4A7_7L(TYHaWS;c_?UE{F;H3B1x~l9L`zHxT1q#nxiJ+u!;S0lC0b~_Y+PeN zhz6YLUFVS!>rI`zSPI7eN&uoS{gzkuha1J5aeK+S;*OGax0^c*&oH*9uw@NM ztzDtVyd}D`L|^j+-Pg`DTC6O#c2$UDk$N<0S}E3y1ejbl!}P|u*@fB-9R}45PyE$iBo%lltaW12qr-3vnWeKfi{_Q-d_0s38e z{nim2!_Plm35QS+)uAEd@@zPYVurm~HpC4+v@;BKawUHE2*>!UA&8z@jd4k1Pa{Gr zDt1sEHLt8V#?gjn1BQK0>T%Q*TqtI2=T<(Jgv0z`7?U1I4)dfJjBZL!wr$+BF>lTY zT3T*x%bRlAcx&5px>Zf3$F;a$E z-H|6rM)-j0Nzj`{zf?4z@1L(|n{g}}IIDNT=Re(bvTN3O+t)Sc=z6f=uDpk^)qBU` zS>(VzylX*gci|c9kG`6jKAAKz0_0{lv%l5hEzPY}{T;;)emoR4$)LN+PJzqWg z#1`Q$;RyGQuh(n1;zl$Obt8f+18yr`4R&3 zx7KQWgqkD$JX|Lfq(hMw?+x(&fuH&+?8P*?Z=>%o>hJLL_th57Q% z8T*P?oR9c%!R6^|M%S8c{U+|(CR0D=u5HEOU&lOP80TH0l9^1wamr+btk6zghe^VQ z2|#GwFHC&+0c&6Pgv-czh%7C`&pbHS%l{}U^Ev=@lbXtD=?v*-5x7K%iW{oxN+)bD g3*{M{VQ`MYB?dR>#~W(#O?r95G0SG$LqZVz7p*$SfdBvi delta 1420 zcmaJ>O>7%Q6rS<^*zx+OahwQTr`g0Mwj1ZCaS+H-TLm1Tg`y~%6)i!s#@Vs6biHfM zu4&4TTmh=+tzwXZDuIwt1xUS6Uw{h1Asj&Bgv4P%To6Z4#Q%W-G@MM^l~CiuidA_#k;Lt9o`S`xY?2}7WyFuvo$4MIF8$AGL=S6`X$1g#K#%mb=vor+?(%i+`ZSxcy;78Ow<>P{fGPm! z1KL2K-^;u{<`lXR><0nRLRyraD@mZm^k^XCx)R7lIlK@$%A=E&6k{6Rjn)nY(eWU9 z@WNf;sj|ewv>`3MMJ^u~$>kMbdODQI##%>5z3?qt0Y@!XakUw2`G+$ZmE}6RXP+C~ zA;Km%aO>_)CpPw-J8YPd&6r%wCdqKsLc?;9SFEUK(WZ(l%elz>4YSd}1T#O?wAH?A zKf@kF8?%aR@4p##DUhooweQWVbsGKas78k%&vfiN)X^2}b%@=+vDax^xS|&7j$@Tn z_UMZ0^hveQMy`vElG?(q%gBmUojOXZGk;A*$ie4D-ecV-?{nbKftU<@0oC1Nj6O5_ z82w=OFx;eH%vMD{p)@g98obSvf7s8hu`h5L{GO$c&lSdYL{U2a{mAH+^}6-Wsc%Ng zuPOU?y=!wBSX4??5p0Xm>X@*dkgFMCI}N#>kr)=CFIyIBp)zUH?~Z3mL1{s`8J3RZ zIRt-eglh{7eA(UTc&0@jrsMPDV`sR1nZqRxTO4k1xXIx*Mf0QZGuoYhIWh-NkqKt} E7c75aNdN!< diff --git a/video_transcription/ai_transcriber_v2/analyze_recovery.py b/video_transcription/ai_transcriber_v2/analyze_recovery.py new file mode 100755 index 0000000..80f40fa --- /dev/null +++ b/video_transcription/ai_transcriber_v2/analyze_recovery.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +import os +import sys +import argparse +import socket +from dotenv import load_dotenv +from tqdm import tqdm + +# Load config +script_dir = os.path.dirname(os.path.abspath(__file__)) +env_path = os.path.abspath(os.path.join(script_dir, '../../.env_files/.env.aitranscribe')) +if os.path.exists(env_path): + load_dotenv(env_path) +else: + load_dotenv() + +from utils import check_srt_duration_match, check_path_permissions, detect_file_encoding + +def analyze_directory(folder_path, target_lang="English"): + print(f"🔍 Analyzing {folder_path} for broken/partial translations...") + + # Check Permissions + perm_ok, perm_msg = check_path_permissions(folder_path) + if not perm_ok: + print(perm_msg) + return + + issues_found = [] + total_scanned = 0 + + # Walk through directory + for root, dirs, files in os.walk(folder_path): + for file in files: + if file.endswith(".srt") and \ + not file.endswith(f".{target_lang}.srt") and \ + not file.endswith(f".{target_lang}.deep_translate.srt") and \ + not file.endswith(f".{target_lang}.local_llm.srt") and \ + not file.endswith(".invalid") and \ + not file.endswith(".failed_validation"): + + source_srt_path = os.path.join(root, file) + base_name = os.path.splitext(file)[0] + + # Paths to check + path_gemini = os.path.join(root, f"{base_name}.{target_lang}.srt") + path_deep = os.path.join(root, f"{base_name}.{target_lang}.deep_translate.srt") + path_local = os.path.join(root, f"{base_name}.{target_lang}.local_llm.srt") + + existing_translation_path = None + method = "None" + + if os.path.exists(path_local): + existing_translation_path = path_local + method = "Local LLM" + elif os.path.exists(path_gemini): + existing_translation_path = path_gemini + method = "Gemini" + elif os.path.exists(path_deep): + existing_translation_path = path_deep + method = "DeepTranslate" + + total_scanned += 1 + + if existing_translation_path: + # Validate duration + is_valid, msg = check_srt_duration_match(source_srt_path, existing_translation_path) + if not is_valid: + issues_found.append({ + "source": source_srt_path, + "translation": existing_translation_path, + "method": method, + "reason": msg + }) + else: + # Missing translation + issues_found.append({ + "source": source_srt_path, + "translation": "MISSING", + "method": "None", + "reason": "No translation file found." + }) + + # --- Report --- + print("\n" + "="*50) + print(f"📊 Analysis Report for: {folder_path}") + print("="*50) + print(f"Total Source Transcripts Scanned: {total_scanned}") + print(f"Issues Found: {len(issues_found)}") + print("-" * 50) + + if issues_found: + print("Detailed Issues:") + for i, issue in enumerate(issues_found, 1): + print(f"{i}. {os.path.basename(issue['source'])}") + print(f" Target: {os.path.basename(issue['translation']) if issue['translation'] != 'MISSING' else 'MISSING'}") + print(f" Error: {issue['reason']}") + print("-" * 30) + + # Optional: Save to file + report_file = f"analysis_report_{socket.gethostname()}.txt" + with open(report_file, "w", encoding="utf-8") as f: + f.write(f"Analysis Report - {datetime.now().isoformat()}\n") + for issue in issues_found: + f.write(f"{issue['source']} | {issue['reason']}\n") + print(f"\nReport saved to: {report_file}") + else: + print("✅ No issues found! All translations appear healthy.") + +if __name__ == "__main__": + from datetime import datetime + + parser = argparse.ArgumentParser(description="Analyze Translations (Read-Only)") + parser.add_argument("folders", nargs='+', help="One or more paths to folders to scan") + parser.add_argument("--lang", default="English", help="Target language (default: English)") + + args = parser.parse_args() + + for folder in args.folders: + if os.path.exists(folder): + analyze_directory(folder, args.lang) + else: + print(f"Error: Folder '{folder}' does not exist. Skipping.") diff --git a/video_transcription/ai_transcriber_v2/job_history_odysseus.db b/video_transcription/ai_transcriber_v2/job_history_odysseus.db new file mode 100644 index 0000000000000000000000000000000000000000..536c21ed556c8c9e10ff70834d18bc2f6ebeb0fb GIT binary patch literal 12288 zcmeI#&riZI6bJAQjS30iLBjRjgv6-CqZcPON`xtM7&$G46`dJBTuZ{)c=CVXZ}Q*q z=t>-k(S$pGo3zV&FYVgTcIjQa8EQ#`aXb{7PS`H9EOti37_*YTk@U2gcry)>r-@fJ ziygl2<%^#zQ<$^Dy!f$d0_qTe00bZa0SG_<0uX=z1R(Ga1zwM=?Q*GPz1dpyBKbV- zDbq7`m)jmE&pvN*G8wAmvSC0C$K#jWCFjN?r_*d6P%b+NBk50sexiHZtzX$ct4a$! zRcWbGJFc2JGLFZwKa@&|M@b%k@Ju!mO8e7EAhZnVBH4h~XmL|eT26d9)3NC5bg5-N z$&OS%4tw(NQj{$Bt0ITJQjh5|p>6&+`5(bN1cAQ4L!>O`7VKrCX&uo=X zOBM@9ft;zAD7oAFVyefB*f&&u&5Y(=zhnNWycu@QfCd2wKmY;|fB*y_009U<00Izz lz`6?L%)xN~U)Rrzb3p(C5P$##AOHafKmY;|fB*y*0$)(+ati (passed, message) """ if not os.path.exists(source_srt_path) or not os.path.exists(target_srt_path): return False, "One or both SRT files missing." + def load_subs_robust(path): + # Try detected encoding first + detected_enc = detect_file_encoding(path) + try: + return pysubs2.load(path, encoding=detected_enc) + except Exception: + pass + + # Fallback encodings + encodings = ['utf-8', 'cp1252', 'latin-1', 'utf-16', 'shift_jis'] + for enc in encodings: + try: + return pysubs2.load(path, encoding=enc) + except Exception: + continue + raise Exception(f"Could not decode {os.path.basename(path)} with any standard encoding.") + try: - source_subs = pysubs2.load(source_srt_path) - target_subs = pysubs2.load(target_srt_path) + source_subs = load_subs_robust(source_srt_path) + target_subs = load_subs_robust(target_srt_path) except Exception as e: return False, f"Error parsing SRTs: {e}"