47 lines
1.3 KiB
Python
47 lines
1.3 KiB
Python
import asyncio
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
|
|
FFMPEG_BIN = shutil.which("ffmpeg") or "ffmpeg"
|
|
|
|
async def transcode_to_mobile_mp4(src: Path) -> Path:
|
|
"""
|
|
Перекодировать видео в MP4, совместимый с мобильными клиентами Telegram:
|
|
- H.264 (libx264), профиль main
|
|
- pix_fmt yuv420p
|
|
- movflags +faststart
|
|
- AAC 128k
|
|
Возвращает путь к новому файлу (.tg.mp4).
|
|
"""
|
|
if not src.exists():
|
|
raise FileNotFoundError(f"Source file not found: {src}")
|
|
|
|
dst = src.with_suffix(".tg.mp4")
|
|
cmd = [
|
|
FFMPEG_BIN,
|
|
"-y",
|
|
"-i", str(src),
|
|
"-c:v", "libx264",
|
|
"-preset", "veryfast",
|
|
"-crf", "23",
|
|
"-profile:v", "main",
|
|
"-pix_fmt", "yuv420p",
|
|
"-movflags", "+faststart",
|
|
"-c:a", "aac",
|
|
"-b:a", "128k",
|
|
str(dst),
|
|
]
|
|
|
|
def _run():
|
|
proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
if proc.returncode != 0:
|
|
raise RuntimeError(f"ffmpeg failed: {proc.stderr.decode('utf-8', errors='ignore')}")
|
|
|
|
loop = asyncio.get_running_loop()
|
|
await loop.run_in_executor(None, _run)
|
|
|
|
if not dst.exists():
|
|
raise RuntimeError("Transcode failed: output file not created")
|
|
return dst
|