From ff453bafba7fd6589246a6a9594edf8d571d70de Mon Sep 17 00:00:00 2001 From: Guillem Hernandez Sola Date: Tue, 19 May 2026 19:02:58 +0200 Subject: [PATCH] Some fixes --- tiktok2bsky.py | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/tiktok2bsky.py b/tiktok2bsky.py index 44fc7e6..8cf2be2 100644 --- a/tiktok2bsky.py +++ b/tiktok2bsky.py @@ -69,7 +69,7 @@ SCRAPE_VIDEO_LIMIT = 30 VIDEO_MAX_AGE_DAYS = 3 VIDEO_MAX_DURATION_S = 179 # Bluesky hard limit is 180s -VIDEO_MAX_SIZE_BYTES = 45 * 1024 * 1024 # 45 MB +VIDEO_MAX_SIZE_BYTES = 20 * 1024 * 1024 # 20 MB # Bluesky login retry config BSKY_LOGIN_MAX_RETRIES = 4 @@ -546,38 +546,37 @@ def compress_video(input_path: str, output_path: str, if duration <= 0: logging.error( - f"❌ compress_video: ffprobe returned duration={duration} " - f"— file is not a valid video: {input_path} " - f"({os.path.getsize(input_path)} bytes)" + f"❌ compress_video: invalid duration={duration} " + f"for {input_path} ({os.path.getsize(input_path)} bytes)" ) return False trim_to = min(duration, max_duration) - target_bits = max_size_bytes * 8 * 0.90 - target_kbps = int(target_bits / trim_to / 1000) - video_kbps = max(200, target_kbps - 128) + # Target 85% of the size budget to leave headroom for container overhead + target_bits = max_size_bytes * 8 * 0.85 + total_kbps = int(target_bits / trim_to / 1000) + audio_kbps = 96 + video_kbps = max(200, total_kbps - audio_kbps) logging.info( f"🎬 Compressing: duration={duration:.1f}s → trim={trim_to:.1f}s, " - f"video_bitrate={video_kbps}k" + f"video_bitrate={video_kbps}k (target ≤ {max_size_bytes // 1024 // 1024}MB)" ) cmd = [ "ffmpeg", "-y", "-i", input_path, "-t", str(trim_to), - # Scale to fit within 1280×720, then pad to even dimensions - # The pad filter is required because libx264 needs width/height - # divisible by 2. Portrait TikTok videos (9:16) would otherwise - # produce odd widths like 405px and crash the encoder. - "-vf", "scale='min(1280,iw)':'min(720,ih)':force_original_aspect_ratio=decrease,pad=ceil(iw/2)*2:ceil(ih/2)*2", + # Scale to 720p max, pad to even dimensions (required by libx264) + "-vf", "scale='min(1280,iw)':'min(720,ih)':force_original_aspect_ratio=decrease," + "pad=ceil(iw/2)*2:ceil(ih/2)*2", "-c:v", "libx264", "-b:v", f"{video_kbps}k", - "-maxrate", f"{video_kbps * 2}k", - "-bufsize", f"{video_kbps * 4}k", + "-maxrate", f"{video_kbps}k", # hard ceiling — no burst above target + "-bufsize", f"{video_kbps * 2}k", "-c:a", "aac", - "-b:a", "128k", + "-b:a", f"{audio_kbps}k", "-movflags", "+faststart", "-pix_fmt", "yuv420p", output_path, @@ -589,6 +588,16 @@ def compress_video(input_path: str, output_path: str, return False final_size = os.path.getsize(output_path) + + # Reject if still over the hard limit + if final_size > max_size_bytes: + logging.error( + f"❌ Compressed file still too large: " + f"{final_size / 1024 / 1024:.1f} MB > " + f"{max_size_bytes / 1024 / 1024:.0f} MB limit. Skipping." + ) + return False + logging.info( f"✅ Compressed video: {final_size / 1024 / 1024:.1f} MB → {output_path}" ) @@ -598,7 +607,6 @@ def compress_video(input_path: str, output_path: str, logging.error(f"❌ compress_video error: {e}") return False - def download_video(url: str, output_path: str, cookies: list = None) -> bool: """