From 6b1cafbc65111096d67b544ade8fcbeee618300d Mon Sep 17 00:00:00 2001 From: Guillem Hernandez Sola Date: Fri, 8 May 2026 09:14:48 +0200 Subject: [PATCH] fixes for video posting --- bsky_post.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/bsky_post.py b/bsky_post.py index 7fcf0e8..601c68e 100644 --- a/bsky_post.py +++ b/bsky_post.py @@ -318,6 +318,46 @@ def upload_image( logging.error(f"❌ Failed to upload image: {repr(e)}") return None +def upload_video_and_wait( + client: Client, + video_data: bytes, + alt_text: str = "" +) -> models.AppBskyEmbedVideo.Main | None: + try: + logging.info("🎬 Uploading video to Bluesky Video Service...") + + # 1. Upload the video (this goes to the dedicated video service) + # Note: In newer atproto versions, you can use client.upload_blob for videos too, + # but you MUST poll the video job status afterwards. + response = client.app.bsky.video.upload_video(video_data) + job_id = response.job_id + + logging.info(f"⏳ Video uploaded! Job ID: {job_id}. Waiting for processing...") + + # 2. Poll the job status + while True: + status_resp = client.app.bsky.video.get_job_status({'job_id': job_id}) + state = status_resp.job_status.state + + if state == 'JOB_STATE_COMPLETED': + logging.info("✅ Processing complete! Waiting 10s for CDN propagation...") + time.sleep(10) # Give the CDN time to distribute the file + + return models.AppBskyEmbedVideo.Main( + video=status_resp.job_status.blob, + alt=alt_text + ) + elif state == 'JOB_STATE_FAILED': + logging.error("❌ Video processing failed on Bluesky's servers.") + return None + + logging.info(" ...still processing...") + time.sleep(3) # Wait 3 seconds before checking again + + except Exception as e: + logging.error(f"❌ Failed to upload/process video: {repr(e)}") + return None + # ============================================================ # Post @@ -339,12 +379,17 @@ def post_to_bsky( with open(video_path, "rb") as f: video_data = f.read() - logging.info(f"🚀 Sending video post (this may take a moment to process)...") - # client.send_video automatically handles the video service upload and processing wait - result = client.send_video( - text=rich_text, - video=video_data, - video_alt=alt_text, + # Use our custom polling function + video_embed = upload_video_and_wait(client, video_data, alt_text) + + if not video_embed: + logging.error("❌ Aborting post: video upload/processing failed.") + return False + + logging.info(f"🚀 Sending video post...") + result = client.send_post( + text=rich_text, + embed=video_embed, langs=langs )