try again
This commit is contained in:
Binary file not shown.
@@ -90,8 +90,20 @@ _IOS_VIDEO_CODECS = {"h264", "hevc"}
|
|||||||
_IOS_AUDIO_CODECS = {"aac", "mp3", "ac3", "eac3", "alac"}
|
_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")
|
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:
|
if ffprobe is None:
|
||||||
return None, None
|
return None, None
|
||||||
completed = subprocess.run(
|
completed = subprocess.run(
|
||||||
@@ -142,13 +154,9 @@ def _ensure_ios_compatible_media(filepath: Path) -> None:
|
|||||||
return
|
return
|
||||||
ffmpeg = shutil.which("ffmpeg")
|
ffmpeg = shutil.which("ffmpeg")
|
||||||
if ffmpeg is None:
|
if ffmpeg is None:
|
||||||
logger.warning(
|
raise RuntimeError(
|
||||||
"ffmpeg not found; skipping iOS-compatible transcode for %s (%s/%s)",
|
f"iOS cannot play {video_codec}/{audio_codec}; ffmpeg is required to transcode {filepath.name}"
|
||||||
filepath.name,
|
|
||||||
video_codec,
|
|
||||||
audio_codec,
|
|
||||||
)
|
)
|
||||||
return
|
|
||||||
tmp = filepath.with_suffix(".ios_tmp.mp4")
|
tmp = filepath.with_suffix(".ios_tmp.mp4")
|
||||||
command = [
|
command = [
|
||||||
ffmpeg,
|
ffmpeg,
|
||||||
@@ -163,7 +171,7 @@ def _ensure_ios_compatible_media(filepath: Path) -> None:
|
|||||||
"-map",
|
"-map",
|
||||||
"0:a:0?",
|
"0:a:0?",
|
||||||
"-vf",
|
"-vf",
|
||||||
"scale='min(1920,iw)':-2",
|
r"scale=w=min(1920\,iw):h=-2",
|
||||||
"-c:v",
|
"-c:v",
|
||||||
"libx264",
|
"libx264",
|
||||||
"-preset",
|
"-preset",
|
||||||
@@ -190,20 +198,21 @@ def _ensure_ios_compatible_media(filepath: Path) -> None:
|
|||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
completed = subprocess.run(command, capture_output=True, text=True, timeout=7200)
|
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:
|
if completed.returncode != 0 or not tmp.is_file() or tmp.stat().st_size <= 0:
|
||||||
tmp.replace(filepath)
|
message = (completed.stderr or "").strip() or "unknown ffmpeg error"
|
||||||
logger.info("iOS-compatible transcode finished: %s", filepath.name)
|
raise RuntimeError(
|
||||||
return
|
f"Could not transcode {filepath.name} from {video_codec}/{audio_codec} to H.264/AAC: {message[-2000:]}"
|
||||||
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:
|
tmp.replace(filepath)
|
||||||
logger.warning("iOS-compatible transcode error for %s: %s", filepath.name, exc)
|
except Exception:
|
||||||
finally:
|
|
||||||
tmp.unlink(missing_ok=True)
|
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:
|
class VideoProcessor:
|
||||||
|
|||||||
Reference in New Issue
Block a user