From 53e947c506144f72d782b659d4bd04495f01ac7f Mon Sep 17 00:00:00 2001 From: Shuming Liu Date: Sun, 13 Sep 2026 13:12:47 +0800 Subject: [PATCH] try again --- .../UserInterfaceState.xcuserstate | Bin 23724 -> 23724 bytes sentence_api/processing.py | 51 ++++++++++-------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/ios/OralTrainer.xcodeproj/project.xcworkspace/xcuserdata/liushuming.xcuserdatad/UserInterfaceState.xcuserstate b/ios/OralTrainer.xcodeproj/project.xcworkspace/xcuserdata/liushuming.xcuserdatad/UserInterfaceState.xcuserstate index 9f45dcdb8abf53f4feeab0b5b67cee07d5d808f5..8f6a29489ac5c7b6effe9c2977c09d94e3278870 100644 GIT binary patch delta 706 zcmX|#H5D6fglJ5{L_XKwI{JR0!6Zo0|O3r zkr3nJ(KzgaVki-h#e|sD+@32NVUJ{ia&T#%nZot7G$aj!8!C=AwY0Vd8WP}^L>elw zrV4AiRVAPo`-2ap%z7u8rOkNa1)pR~fC>jiQcNYJC8!pDkrIy1v%Qf}AQB7>hWfjL z=TFDZg(A_$P^2ds-qQC?3vegRRvJ+rwo=tJBa+%`MMF+WoH*jdnKishT-vNh$<@=Q zH47oV1H%0; zHp0eOip{eH_L?oT59|y3&VF;kb9n*Z$r-nE2QTGiyqv52uwidGB;z;Gy4niJh%wOS GrGEeq8rDz% delta 702 zcmX|-OH5Ni6ozL`?*uWHRut3)XSl)E2agui)+)s&HpUWyF%9z2fREl#eAEOAqC%YO z!o)}7;zk!LqAh}!#uzRvaHA%=5)D>~aig+u#mc2IAx>L$R_9Ot|2zMg^ej!!(q|KN z%|>v56E;CD)WJ5`4m)AD`JCRgvN~3zgV}6rqq)&4T_Lv>}UA`p2%vd;){CsSpeF*DAicE&AJB55qTf`u-fI&|vHt++zH#*AC$GM2Z* zW|@#(2UIa5#*ByFD%mJMZ7`R-oHDLFm91>P;9A+LTc=Tx7LJVaQgUBOZnsaZ zl51W|`3Ag4n!`2y{XLQ6=i^%60lVEgb^ArfjlCBqM;6C<C0cQW&PPYy9J z|OosLRMS75L>^uFw8*)m#?VF9kfBD7;Ms#uL~^kWeB;eKqy xgBZpZY{hoGjMKP)UvUYSIpKxe&PzD*O5VT&W_h??0naa^vvnQ4We&7@*dLV#(ft4b diff --git a/sentence_api/processing.py b/sentence_api/processing.py index 4082597..efaa675 100644 --- a/sentence_api/processing.py +++ b/sentence_api/processing.py @@ -90,8 +90,20 @@ _IOS_VIDEO_CODECS = {"h264", "hevc"} _IOS_AUDIO_CODECS = {"aac", "mp3", "ac3", "eac3", "alac"} -def _probe_stream_codecs(filepath: Path) -> Tuple[Optional[str], Optional[str]]: +def _ffprobe_bin() -> Optional[str]: ffprobe = shutil.which("ffprobe") + if ffprobe: + return ffprobe + ffmpeg = shutil.which("ffmpeg") + if ffmpeg: + candidate = str(Path(ffmpeg).with_name("ffprobe")) + if Path(candidate).is_file(): + return candidate + return None + + +def _probe_stream_codecs(filepath: Path) -> Tuple[Optional[str], Optional[str]]: + ffprobe = _ffprobe_bin() if ffprobe is None: return None, None completed = subprocess.run( @@ -142,13 +154,9 @@ def _ensure_ios_compatible_media(filepath: Path) -> None: return ffmpeg = shutil.which("ffmpeg") if ffmpeg is None: - logger.warning( - "ffmpeg not found; skipping iOS-compatible transcode for %s (%s/%s)", - filepath.name, - video_codec, - audio_codec, + raise RuntimeError( + f"iOS cannot play {video_codec}/{audio_codec}; ffmpeg is required to transcode {filepath.name}" ) - return tmp = filepath.with_suffix(".ios_tmp.mp4") command = [ ffmpeg, @@ -163,7 +171,7 @@ def _ensure_ios_compatible_media(filepath: Path) -> None: "-map", "0:a:0?", "-vf", - "scale='min(1920,iw)':-2", + r"scale=w=min(1920\,iw):h=-2", "-c:v", "libx264", "-preset", @@ -190,20 +198,21 @@ def _ensure_ios_compatible_media(filepath: Path) -> None: ) try: completed = subprocess.run(command, capture_output=True, text=True, timeout=7200) - if completed.returncode == 0 and tmp.is_file() and tmp.stat().st_size > 0: - tmp.replace(filepath) - logger.info("iOS-compatible transcode finished: %s", filepath.name) - return - logger.warning( - "iOS-compatible transcode failed for %s: rc=%d stderr=%s", - filepath.name, - completed.returncode, - (completed.stderr or "")[-400:], - ) - except (subprocess.TimeoutExpired, OSError) as exc: - logger.warning("iOS-compatible transcode error for %s: %s", filepath.name, exc) - finally: + if completed.returncode != 0 or not tmp.is_file() or tmp.stat().st_size <= 0: + message = (completed.stderr or "").strip() or "unknown ffmpeg error" + raise RuntimeError( + f"Could not transcode {filepath.name} from {video_codec}/{audio_codec} to H.264/AAC: {message[-2000:]}" + ) + tmp.replace(filepath) + except Exception: tmp.unlink(missing_ok=True) + raise + video_codec, audio_codec = _probe_stream_codecs(filepath) + if _needs_ios_compatible_transcode(video_codec, audio_codec): + raise RuntimeError( + f"Transcoded {filepath.name} is still not iOS-compatible ({video_codec}/{audio_codec})" + ) + logger.info("iOS-compatible transcode finished: %s", filepath.name) class VideoProcessor: